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:
"UseAGENTS.mdfor short, repository-wide conventions. UseSKILL.mdfor 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.

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.

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.

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.