Most advice about AI coding assumes one assistant per project. Reality is messier: you start a feature in Claude Code, your teammate prefers Cursor, and a long refactor ends up in Codex because that is what was open. Working with multiple AI assistants on the same codebase is now normal, and the failure shows up fast.

The new tool does not know that you rejected the queue-based approach two weeks ago. It does not know which instruction file it should follow. It re-suggests the library you removed, or asks a question you answered in a conversation that lives inside a different tool's history.

This article treats that as a portability problem, not a tool problem. You will get a file layout that every assistant can read, a rule for what should differ between tools and what must not, a short handoff routine for switching mid-task, and a trigger list for when to write something down instead of hoping a tool remembers it. All of it works with plain Markdown files.

Why one project ends up with more than one assistant

Nobody plans this. It accumulates.

You pick a default assistant and use it for weeks. Then one of these happens:

  • A teammate joins and has a strong preference. They are faster in their tool, and asking them to switch costs more than it saves.
  • You hit a task that suits a different shape of tool: a wide multi-file refactor in a terminal agent, a tight in-editor change with inline completion.
  • A tool has a bad day — rate limits, an outage, a model change — and you finish the task somewhere else.
  • You are evaluating. You want to know whether the other one handles your codebase better, and the only honest test is real work.

None of these are mistakes. The mistake is assuming the project state travels with you. It does not. What travels is whatever is written in the repository.

The real problem: multiple AI assistants remember differently, or not at all

Each assistant has its own idea of continuity, and they do not overlap.

Conversation history is per-tool. A long session where you worked out why the sync layer retries three times and then gives up is stored by that tool, for you, on that machine. Another assistant cannot see it. Neither can your teammate. Neither can you, six months later, if you no longer use that tool.

Instruction files are read selectively. Claude Code reads CLAUDE.md. Codex and many other agents read AGENTS.md. Editors keep project rules in their own configuration. An instruction that lives in only one of these is invisible to the others, which means the rule you thought was project policy is actually a setting in one program.

Anything a tool "learned" implicitly is not written down anywhere. If an assistant infers your test command by watching you run it, that inference dies with the session. The next tool starts from the code and guesses again.

So the practical model is simple: an assistant knows the code, plus whatever files you point it at. Everything else is temporary. Once you accept that, the fix is obvious — stop improving your relationship with one tool and start improving the repository.

Put context in the project, not in any one tool's memory

The target is a project where any assistant, opened cold, can answer three questions from files alone: how do we work here, what did we already decide, and how did we get here.

That maps to three kinds of content, kept separate:

KindAnswersRead byChanges
Instructions"How do we work here?"Every assistant, every sessionRarely
Memory"What did we decide, and why?"When the assistant needs historyOften
Sessions"How did we get there?"On demand, for the hard partsNever, once saved

A layout that survives tool changes:

project/
  CLAUDE.md              # short; points at the shared file
  AGENTS.md              # short; points at the shared file
  .prjcontext/
    instructions/
      conventions.md     # the real rules, written once
    memory/
      decisions.md
      rejected.md
      state.md
    sessions/
      2026-09-14-sync-design.md

The important move is the first one. Keep the rules in one file and make the tool-specific files thin pointers to it. Duplication is what drifts.

<!-- CLAUDE.md -->
# Project instructions

Read `.prjcontext/instructions/conventions.md` first — it is the source of
truth for conventions, commands and boundaries.

Before proposing an architectural change, read
`.prjcontext/memory/decisions.md` and `.prjcontext/memory/rejected.md`.

Claude Code specifics:
- Prefer editing files in place over creating new ones.

AGENTS.md gets the same body with its own last section. If you write the rules twice, in six weeks they will disagree, and you will not know which one the assistant followed. For how to write the rules themselves, see CLAUDE.md and AGENTS.md: writing project instructions your assistant follows.

What should differ between assistants, and what should not

Not everything should be shared. Some things genuinely belong to one tool.

Must be shared, in files, identical for every tool:

  • Conventions: types, error handling, where database access lives, naming.
  • Commands: how to run tests, lint, build, seed a dev database.
  • Boundaries: directories not to touch, generated files, vendored code.
  • Decisions and their reasons.
  • Rejected approaches, with the reason for rejection.
  • Current state: what is half-done, what is blocked.

Can differ per tool, and should stay small:

  • Tool-specific behaviour toggles and permissions.
  • How the tool is allowed to run commands.
  • Formatting quirks of how that tool likes instructions phrased.

A useful test: if a rule would still be true when the project is opened in a text editor by a human, it is shared context. If it only makes sense while a particular program is running, it is tool configuration.

The rejected-approaches file deserves special attention in a multi-tool project, because it is the single entry that most often stops wasted work:

## Rejected

- **Background queue for image processing** (2026-08-28)
  Tried it, dropped it. Adds a second service to deploy for a job that
  finishes in under 200 ms inline. Revisit only if p95 goes above 2 s.

- **Switching the ORM** (2026-09-05)
  Considered, not done. Migration cost is weeks; the actual pain is two
  slow queries. Fix the queries instead.

Without this file, every new assistant re-proposes the queue. With it, each one reads two lines and moves on. Project memory for AI coding covers the other entry types in detail.

Switching tools mid-task without losing the thread

The riskiest moment is a handoff in the middle of unfinished work: half a refactor, a failing test, a plan that only exists in one conversation.

Before you close the first tool, spend two minutes producing a handoff note. Ask the assistant you are leaving to write it — it has the context, you have the judgement:

Summarise this session for a different assistant that has never seen it. Cover: the goal, what we changed and where, what we tried and dropped and why, what is still failing, and the next step. Keep it under 30 lines. No code.

Save it as the current state:

<!-- .prjcontext/memory/state.md -->
## In progress — checkout refactor (2026-09-25)

Goal: move payment retries out of `CheckoutService` into `PaymentClient`.

Done: `PaymentClient.retry()` added, unit tests pass.
Not done: `CheckoutService` still calls the old path in two places
  (`submit()`, `resume()`).
Tried and dropped: a decorator-based retry — made stack traces unreadable.
Open question: does `resume()` need idempotency keys? Probably yes.
Next: migrate `submit()`, then delete `legacy_retry.ts`.

Then open the second tool and point it at the file before asking for anything: "Read .prjcontext/memory/state.md and .prjcontext/instructions/conventions.md, then continue from Next." Delete or archive the entry when the task lands, so state.md never becomes a graveyard.

The same note is what lets you move between machines, not just between tools — continuing an AI coding project on another machine uses the same handoff shape.

When to write it down instead of trusting a tool to remember

You cannot write down everything, and a bloated memory file is as useless as an empty one. Use triggers instead of discipline.

Write an entry when:

  • You chose between real options. Two viable approaches, one picked. Record the loser and the reason, not just the winner.
  • You rejected something an assistant proposed. If you argued with a tool for ten minutes, the next tool will start that argument again.
  • You discovered a constraint. A rate limit, an ordering requirement, a dependency that breaks on Node 20. Constraints are invisible in code and expensive to rediscover.
  • You stopped mid-task. Anything you would need to explain to yourself on Monday.
  • A session produced reasoning you would want to reread. Save the transcript itself rather than summarising it badly. Which AI coding sessions are worth keeping gives selection criteria.

And skip it when the answer is already in the code, in a test, or in a commit message. If an assistant could work it out by reading the repository in thirty seconds, do not duplicate it.

One habit makes the rest work: at the end of a session, ask "did anything change that a different tool would need to know?" Usually the answer is no. When it is yes, it takes a minute.

How PrjLab handles this

We built PrjLab because context that only helps if it reaches the next tool also has to reach the next machine and the next person. A PrjLab repository stores your files together with three explicit kinds of context: .prjcontext/instructions/ (project instructions — CLAUDE.md and AGENTS.md at the project root are recognised too), .prjcontext/memory/ for decisions and notes, and .prjcontext/sessions/ for the conversations you chose to keep.

You push from the terminal with the prj CLI — prj init, prj status to see what would be captured, then prj push. Every push creates an immutable version you can open in the browser, with a list of changes and a line diff, so you can see when an instruction file actually changed. On another machine or for a teammate, prj clone or prj pull brings the whole picture down; prj pull never overwrites local edits — conflicting files are reported instead of replaced.

Repositories are private by default. You can share by handle as a reader (view and clone) or a writer (also push), and removing someone takes effect immediately — useful when the person who prefers a different assistant is the one who needs your decisions file. The CLI skips obvious secrets such as .env files and anything in .gitignore or .prjignore, but it is a safety net rather than a complete scanner, so check prj status before pushing. PrjLab sits beside git, not instead of it. The getting-started guide walks through the first push.

Frequently asked questions

Do I need both CLAUDE.md and AGENTS.md? If more than one kind of assistant touches the project, yes. Keep both short and have both point at a single shared instructions file, so the rules exist once and only the tool-specific tail differs.

Will a second assistant read files I do not explicitly mention? Do not count on it. Assistants read what they are configured to read plus what you point them at. The reliable pattern is to name the files in your instruction file and again in your first message after switching tools.

Is it worth saving transcripts if they are long and messy? Save the few where the reasoning matters — a design argument, a debugging session that found a non-obvious cause. Add a two-line summary in your memory file with a pointer to the transcript, so a new assistant can read the summary and open the detail only if needed.

How do I stop the shared files from going stale? Tie updates to events, not to a schedule: a decision, a rejection, a discovered constraint, an interrupted task. Reviewing the diff of your instruction and memory files when you push is usually enough to catch drift.

Start with the getting-started guide if you want your instructions, memory and sessions to travel with the project instead of with one tool.