MemoryLake
Back to all articles
TutorialSeptember 8, 2026·11 min read

How to Migrate From Codex to OpenHands Without Losing Context (2026)

This migration looks like it should take ten minutes. Codex reads AGENTS.md. OpenHands reads AGENTS.md. Copy the repository, point the new agent at it, done.

Then the agent starts ignoring the guidance that used to work, or worse, follows all of it at once in situations where only a third of it applies. The file name is identical on both sides. The loading strategy behind it is not remotely the same, and that is the entire migration.

One boundary before we start: this is about moving the instruction layer from Codex to a different agent runtime. If you are moving Codex to a terminal-native agent instead, migrating from Codex to Warp covers a different destination. And if your current problem is that Codex is not picking up the rules you already wrote, why Codex skips your AGENTS.md rules is the right starting point instead of a migration — as is why Codex forgets project context if the loss is happening mid-session rather than at load time.

What actually transfers

Both tools document their discovery precisely, which makes the difference easy to see once you read them side by side.

Codex assembles everything into a single ordered chain before it starts work:

"Codex builds an instruction chain when it starts (once per run; in the TUI this usually means once per launched session)."

Discovery starts globally, in the Codex home directory, where it "reads AGENTS.override.md if it exists. Otherwise, Codex reads AGENTS.md" and "uses only the first non-empty file at this level." Then it walks the project:

"Starting at the project root (typically the Git root), Codex walks down to your current working directory."

In each directory along that path it checks for AGENTS.override.md, then AGENTS.md, then any fallback names configured in project_doc_fallback_filenames, and "includes at most one file per directory." The merge is a concatenation: "Codex concatenates files from the root down, joining them with blank lines. Files closer to your current directory override earlier guidance because they appear later in the combined prompt."

And there is a hard ceiling: Codex "stops adding files once the combined size reaches the limit defined by project_doc_max_bytes (32 KiB by default)."

OpenHands starts from the opposite premise. Its root AGENTS.md is always-on, but everything else is deliberately held back until it is relevant. The documentation lays out the mechanisms in a table: AGENTS.md at the repository root means "Full content is included in the initial system prompt," while an Agent Skill at .agents/skills/<skill-name>/SKILL.md means "Name and description are advertised first; the agent invokes the full skill when relevant."

The guidance that follows is the single most important sentence for anyone arriving from Codex:

"Use AGENTS.md for short, repository-wide conventions. Use SKILL.md for focused knowledge that is needed only for some tasks."

And the warning attached to it:

"Always-on content occupies the conversation context from the beginning. Keep AGENTS.md concise and move lengthy or specialized instructions into on-demand skills and references."

So: your rule content transfers verbatim. Your rule structure does not. In Codex, nesting directories is the conditionality mechanism — you place a file close to the specialized work and it lands late in the concatenated prompt. In OpenHands, nesting is not the mechanism at all; the mechanism is a skill's description, or a declared trigger, or a declared path pattern.

Flattening a Codex chain into one OpenHands AGENTS.md is not a shortcut. It is the specific thing the destination's documentation tells you not to do.

The manual migration

Step 1: Split the chain by how often each part actually applies

Walk your Codex instruction chain from the root down and sort every block into one of three piles.

Always true, everywhere. The test command, the package manager, the "never edit generated files" rule, the naming convention that holds across the repository. This is your new root AGENTS.md, and it should be short. If your current root AGENTS.md is long because it grew toward the 32 KiB cap, this is the moment to find out how much of it was actually universal.

Only true in one area. Everything that lived in a nested AGENTS.md because it applied to the payments service, or the frontend, or the migrations folder. These become skills with a paths declaration. OpenHands documents this as a deterministic rule rather than a suggestion: paths "turns the file into a path-triggered rule. The rule is not advertised to the model and is injected once per conversation when a matching file is read, edited, or created."

This pile is where the migration gains something. In Codex, a nested file applies because you started the session in or below that directory — the scoping is a side effect of where you are standing. A paths pattern applies when the agent actually touches a matching file, regardless of where the session started. That is a more precise version of what you were trying to express.

Only true for certain tasks. Release checklists, incident runbooks, the long explanation of how the data pipeline is wired. These become ordinary skills with a name and a description. They cost almost nothing until they are invoked, which is why they can be as long as they need to be — the opposite of the constraint you were working under with a concatenated chain and a byte cap. One caveat worth keeping in mind as you move things into skills: agent skills are not memory. A skill is a procedure the agent can invoke, not a record of what your team decided.

There is a fourth pile worth naming: guidance that is triggered by a phrase rather than a file. OpenHands supports that too — triggers "injects the skill when a keyword or command appears in a user message" and the skill stays available for model invocation as well. If a file declares both, the documentation is explicit that "paths takes precedence."

Step 2: Fix the filename assumptions that flip direction

Two details will bite you, and they point opposite ways.

Codex requires you to register any non-standard instruction filename. Its documentation states that filenames not on the project_doc_fallback_filenames list "are ignored for instruction discovery." If your repository ended up with a CLAUDE.md that Codex reads, it reads it because someone put it on that list.

OpenHands does the reverse by default: "OpenHands also recognizes CLAUDE.md and GEMINI.md as model-specific repository context." Nothing to register. Which means a CLAUDE.md you had been ignoring — or had deliberately left out of Codex's fallback list — becomes live on arrival. Check for one before your first run.

The other detail is AGENTS.override.md. Codex uses it in two places: globally, where it wins over AGENTS.md entirely, and per directory, where it is checked first. It is a useful escape hatch for temporary local behavior. OpenHands' skills documentation does not describe an override filename of that kind, so any AGENTS.override.md in your tree is a file with no documented reader on the far side. Decide per file whether its content belongs in the root AGENTS.md, in a scoped skill, or nowhere.

One more note on legacy files: OpenHands documents that "a legacy .md skill without a trigger is always loaded in full" and recommends preferring AGENTS.md for that case so the intent is clear. If you are porting a pile of loose Markdown, that is the sentence to plan around — a bare .md skill will behave like always-on content, which puts you right back in the position you are migrating out of. If your instruction files started life as a CLAUDE.md, converting a CLAUDE.md into an AGENTS.md covers the naming and content differences in more detail.

The Better Way: A decision layer neither runtime owns

Everything above is a restructuring job, and you will do a version of it every time the loading model changes underneath you. Codex uses a byte-capped concatenation. OpenHands uses progressive disclosure. The next tool will use something else.

What survives all of it is the reasoning: why the convention exists, what you rejected, and what incident put the rule there in the first place. That never fits comfortably in an instruction file, because an instruction file is a list of commands and should stay short on both platforms.

MemoryLake holds that layer outside both runtimes and serves it to whichever agent is asking, over MCP or the API. Codex keeps its own local memories and OpenHands keeps its skills catalog exactly as they are.

Step 1: Create an API key

Generate a key and make your first request in about thirty seconds, before you start splitting files.

Creating a MemoryLake API key so project facts live outside both the Codex instruction chain and the OpenHands skill set
Creating a MemoryLake API key so project facts live outside both the Codex instruction chain and the OpenHands skill set

Step 2: Upload your first memories

As you sort each block in Step 1, you will keep asking "why is this here." Write the answer down as you go — the decision, the alternative you rejected, the constraint behind it. Documents and other files go in the same place.

Uploading the project decisions that would otherwise be squeezed against Codex's 32 KiB instruction-chain limit into MemoryLake
Uploading the project decisions that would otherwise be squeezed against Codex's 32 KiB instruction-chain limit into MemoryLake

Step 3: Connect your AI & agents

Give Claude, Codex, OpenClaw, and OpenHands access over MCP or the API. An agent that can query the decision layer stops needing the rationale inlined into the always-on file, which is what lets the root AGENTS.md stay as short as both vendors recommend.

Connecting OpenHands, Codex and other agents to MemoryLake over MCP and the API
Connecting OpenHands, Codex and other agents to MemoryLake over MCP and the API

What this changes in practice

The first change is that the 32 KiB conversation ends. Teams hitting Codex's cap have two documented options — raise the limit or split across nested directories — and both are ways of managing a budget. On the OpenHands side the budget question moves: the root file should be short not because of a byte cap but because always-on content competes for context from the first message. A decision layer that is queried on demand is how the short file stays short without losing the reasoning.

The second change is that scoping gets sharper. A paths pattern is a stronger statement than "this file sits in the payments directory," and it fires on the file the agent actually touches rather than on where the session began.

The third change shows up during the overlap period. Most teams run both for a few weeks. Two instruction trees with two loading models will diverge in ways nobody notices until an agent does something the other one would not have. One shared decision layer means the reasons stay identical even while the file layouts differ.

Best practices for the Codex to OpenHands move

Measure your root file before you copy it. If your Codex chain was pushing the byte cap, the honest question is how much of it was ever universal. Most of the answer is "less than you think."

Convert directory nesting into declared patterns. Do not reproduce your Codex directory layout in OpenHands and expect the same behavior. Nesting was the scoping mechanism on one side; a paths declaration is the scoping mechanism on the other.

Audit for CLAUDE.md and GEMINI.md before the first run. They go from needing registration to being recognized automatically. That is usually welcome and occasionally a surprise.

Give every skill a description that names when it applies. Discovery advertises the name and description only. A description that says what the skill does but not when to use it will not get invoked at the right time.

Do not put reasoning in the always-on file. Both vendors tell you to keep it concise. Rationale belongs in a store the agent queries, not in the block loaded on every message.

Expect summarization on long sessions. OpenHands documents a context condenser that keeps recent messages intact and summarizes older content once history exceeds a configured size. That is a sensible way to manage a long conversation, and it is a good reason not to treat the conversation as your record of anything.

Conclusion

Codex and OpenHands read a file with the same name and treat it in nearly opposite ways. Codex concatenates an ordered chain from the project root down to your working directory, one file per directory, until it hits a byte cap. OpenHands loads the root file in full and holds everything else behind a description, a keyword trigger, or a path pattern.

That difference is the migration. The content ports verbatim; the structure has to be rebuilt around a loading model that rewards a short always-on file and unlimited on-demand detail. Along the way you get two filename surprises that point in opposite directions, and one escape hatch — AGENTS.override.md — with no documented equivalent.

Split the chain by how often each part applies, convert nesting into declared patterns, and keep the reasoning somewhere neither runtime owns. Then the next loading model is a restructuring job and not an archaeology project.

Frequently asked questions

Can I just copy my whole AGENTS.md chain into one OpenHands AGENTS.md?

You can, and it will function, but it is the case the destination documentation warns about: always-on content occupies the conversation context from the beginning, and OpenHands explicitly recommends keeping AGENTS.md concise and moving lengthy or specialized instructions into on-demand skills. A flattened chain also loses all the scoping that directory placement was providing in Codex.

Does OpenHands have a size limit on AGENTS.md like Codex's 32 KiB cap?

Its skills documentation does not specify a byte limit for AGENTS.md. What it does specify is the cost model — always-on content is in the context from the first message — and the recommendation to keep the file concise. So the constraint is real but expressed as guidance about context occupancy rather than as a configurable byte ceiling.

What happens to my nested AGENTS.md files?

Their content transfers; their scoping mechanism does not. In Codex a nested file applies because your working directory is inside that subtree. In OpenHands, convert each one into a skill with a paths declaration so it is injected when the agent touches a matching file. The documentation notes the rule is not advertised to the model and is injected once per conversation on first match.

Should I turn off Codex's local memories before migrating?

There is no need to, and they are worth understanding rather than discarding — turning on Codex's local memories covers what that surface holds and how to control it. OpenAI's own guidance is to keep required team guidance in AGENTS.md or checked-in documentation rather than relying on memories for rules that must always apply. That advice survives the migration unchanged.

How do I handle a rule that should only fire when I say a certain word?

That is what triggers is for — a keyword or command in a user message injects the skill, and it remains available for model invocation as well. If you declare both triggers and paths on the same file, the documentation states that paths takes precedence.

Will the context condenser drop my project rules mid-session?

The condenser operates on conversation history — it keeps recent messages intact, preserves key information, and summarizes older content once history exceeds a configured size, with the earliest events retained. Your always-on AGENTS.md content and your skills are instruction sources rather than conversation turns. The practical lesson is the same one that applies everywhere: a long chat is not a durable record, so keep the things you need to survive in files and in a queryable store.