MemoryLake
Back to all articles
TutorialSeptember 7, 2026·12 min read

How to Migrate From Cursor to opencode Without Losing Context (2026)

opencode's documentation makes this migration sound like a configuration line. Its rules page says you can point an instructions array at files you already have, "rather than having to duplicate them to AGENTS.md," and the documented example includes .cursor/rules/*.md right there in the list. Copy that, keep working, done.

Two things go wrong with that plan, and both are visible in the vendors' own docs if you read them side by side.

The first is a file extension. Cursor project rules are .mdc files, and Cursor is explicit that "a plain .md file in .cursor/rules is ignored by the rules system." A glob of .cursor/rules/*.md therefore matches none of your actual rules — it silently matches nothing, and nothing is the hardest failure to notice.

The second is bigger and cannot be fixed with a glob. Cursor has four ways a rule can be applied, three of which are conditional. opencode's instructions array has one: everything listed gets combined. So the migration does not lose your rules. It loses the conditions on them, which for a mature .cursor/rules directory is most of the engineering you did.

This guide covers what transfers as-is, the two manual steps that fix the glob and the conditions, and where the third category — the stuff neither tool's rule system is built for — should actually live.

What actually transfers

Rule content transfers verbatim. Both tools take plain Markdown instructions and put them in front of the model. Cursor describes the mechanism plainly: "Large language models don't retain memory between completions. Rules provide persistent, reusable context at the prompt level," and "when applied, rule contents are included at the start of the model context." opencode's framing is nearly identical — an AGENTS.md holding "instructions that will be included in the LLM's context to customize its behavior for your specific project," and its docs even say the concept "is similar to Cursor's rules."

A root AGENTS.md transfers with no work. If you were already using Cursor's AGENTS.md option — which Cursor positions as a "simple alternative to .cursor/rules" — opencode reads it directly. Project-root rules in opencode "only apply when you are working in this directory or its sub-directories."

Your .mdc rule files transfer as files, once the glob is right. opencode's instructions array takes file paths and glob patterns, so the files can stay exactly where they are in .cursor/rules/. You are pointing at them, not moving them. That is genuinely nicer than rewriting, and it is the reason to do this migration this way rather than flattening everything into one file.

Frontmatter does not transfer. This is the load-bearing loss. Cursor's four rule types are Always Apply, Apply Intelligently ("when Agent decides it's relevant based on description"), Apply to Specific Files ("when file matches a specified pattern"), and Apply Manually ("when @-mentioned in chat"). Those come from three frontmatter fields interacting: with alwaysApply: false and globs provided, a rule is "auto-attached when a matching file is in context"; with alwaysApply: false and a description but no globs, "Agent reads the description and pulls the rule in when relevant"; with neither, it is "included only when you @-mention the rule in chat."

opencode has no documented counterpart to any of that. Its docs state that "all instruction files are combined with your AGENTS.md files." A rule that used to appear only when you touched src/components/** now appears on every request, as does the one you had set to manual because it was a rarely-needed migration checklist. Nothing breaks loudly. Your prompt just gets much larger and much less focused, which is the failure mode we described in why agents ignore your instruction files.

@file references inside rules do not transfer. Cursor rules can reference other files inline — a rule that ends with @migration-template.sql pulls that template in. opencode's docs are direct: "opencode doesn't automatically parse file references in AGENTS.md." The two supported workarounds are listing the referenced files in instructions yourself, or writing explicit prose telling the agent to read them.

Team Rules do not transfer. Cursor's Team Rules are managed from the Cursor dashboard on Team and Enterprise plans, "take precedence" over other rule types, and can be marked so they "cannot be disabled in Customize." That is an organizational control surface, not a file. Whatever those rules say has to be re-expressed as committed files — which also means it stops being enforceable in the same way.

What Cursor has and opencode does not, and the reverse. Cursor's documented persistence mechanism is rules in their four forms; a search of Cursor's documentation index returns no hits for a memory store that writes itself, so the accurate statement is that there is no documented counterpart to one. opencode's documented mechanisms are AGENTS.md files, the instructions array, and a /init command. Neither tool documents a store that accumulates what you learned while working — which is the third category this guide keeps coming back to.

The manual migration

Step 1: Fix the glob, then run /init on top of it

Start with the instructions array in your project's opencode.json. The documented example uses .md; your rules are .mdc, and Cursor supports subdirectories like .cursor/rules/frontend/components.mdc. So the pattern you want is .cursor/rules/**/*.mdc, which catches nested rule folders too. Keep .md in the list as well if you have any plain-Markdown docs in there that Cursor was ignoring but you actually want opencode to read — an unusual but real case, since Cursor drops those files and opencode will not.

Add the files your Cursor rules used to reference with @, since those references will no longer be followed. If you had a rule pointing at @migration-template.sql, the template needs to be in instructions or explicitly named in prose.

Then run /init. This is the step people skip, and it is the one that pays. opencode's /init "scans the important files in your repo, may ask a couple of targeted questions when the codebase cannot answer them, and then creates or updates AGENTS.md with concise project-specific guidance," and it explicitly considers "references to existing instruction sources like Cursor or Copilot rules." Crucially, running it is not destructive: "If you already have an AGENTS.md, /init will improve it in place instead of blindly replacing it." Running it after wiring up instructions means it can see what you already have rather than reinventing it.

One precedence rule to know before you create anything: opencode resolves "local files by traversing up from the current directory (AGENTS.md, CLAUDE.md)" and a global file at ~/.config/opencode/AGENTS.md, and "the first matching file wins in each category. For example, if you have both AGENTS.md and CLAUDE.md, only AGENTS.md is used." If your repo has been running on a CLAUDE.md, creating an AGENTS.md turns it off. Same pattern applies globally: ~/.config/opencode/AGENTS.md takes precedence over ~/.claude/CLAUDE.md.

Step 2: Decide what each unconditional rule now costs

Now go through the .mdc files you just pointed at and read only their frontmatter. Sort them into three piles.

Rules with alwaysApply: true are free. They were unconditional in Cursor and they are unconditional in opencode. Nothing to do.

Rules with globs were scoped to file types or directories. In opencode they are now always on. For a short one — five lines of TypeScript conventions — that is fine, and flattening it is the right call. For a long one, you have two honest options: trim it to the part that is worth paying for on every request, or leave it out of instructions and load it deliberately when you are working in that area. There is no third option that preserves the conditionality, and pretending otherwise is how instruction files quietly triple in size.

Rules with a description and no globs are the most interesting pile, because Cursor was using the description as a retrieval signal — the "Agent reads the description and pulls the rule in when relevant" behavior. That mechanism has no home in opencode. What you can preserve is the intent: keep the description text as the first line of the rule so a human scanning the combined prompt can see what it is for, and consider whether the rule is really a rule or a fact you learned. Quite often it is the latter, which means it belongs in the next section rather than in instructions at all.

Rules with neither field were manual, @-mention-only. These are usually checklists and templates. Leave them out of instructions entirely and reference them by path when you need them. opencode's docs suggest exactly this pattern for external files — teach the agent to read a file when a condition applies, rather than loading it up front.

Cursor's own best-practice advice is worth carrying over while you do this: "Keep rules under 500 lines," "split large rules into multiple, composable rules," and "reference files instead of copying their contents — this keeps rules short and prevents them from becoming stale as code changes." All three matter more in opencode than in Cursor, because there is no conditional layer absorbing your excess. If you would rather not lose conditionality at all, migrating Cursor rules to Codex covers a destination whose scoping works differently, and migrating Cursor to Claude Code covers another.

The Better Way: keep the discovered facts out of the rules entirely

Sorting the frontmatter piles usually surfaces something uncomfortable: a meaningful share of your .cursor/rules content is not rules. It is history. "Don't use the batch endpoint for reconciliation, it times out over ten thousand rows." "Auth tokens are minted by the legacy service until Q1, so don't add scopes here." Those are facts somebody learned the hard way, filed in the only durable place the tool offered.

Rules are the wrong container for them, in both tools. Cursor says it itself: rules are "persistent, reusable context at the prompt level," re-sent every time. A fact you learned in July is not prompt-level configuration; it is knowledge, it accumulates without bound, and it is discovered rather than authored.

MemoryLake is where that half goes. It sits outside both tools, holds what your team established rather than how your team works, and is readable over MCP or an API by whichever client you are in today. The practical effect on this migration is that the instructions array stays short enough that losing conditionality does not hurt.

Step 1: Create an API key

Generate a key and make your first request in about thirty seconds. One key covers every surface, which is the point — the knowledge should not belong to an editor.

Creating a MemoryLake API key so discovered facts stay out of the rules entirely
Creating a MemoryLake API key so discovered facts stay out of the rules entirely

Step 2: Upload your first memories

Drop in the documents, images, and files that already carry your project's established decisions, plus the rule files you just identified as history rather than convention. Start with what you are tired of re-explaining.

Uploading the project facts that used to live in always-on Cursor rules into MemoryLake
Uploading the project facts that used to live in always-on Cursor rules into MemoryLake

Step 3: Connect your AI & agents

Give Claude, Codex, OpenClaw, and other agents access over MCP or the API. In an opencode session, that means the established facts are retrievable on demand instead of permanently occupying your combined instruction prompt.

Connecting Cursor and opencode to the same MemoryLake store over MCP and the API
Connecting Cursor and opencode to the same MemoryLake store over MCP and the API

What this changes in practice

The instructions array stays small, which is what makes the loss of conditionality survivable. Cursor's conditional layer existed because rule directories grow; if the growth goes somewhere else, the flat array is genuinely fine.

Team Rules stop being a migration blocker. The organizational content that lived in Cursor's dashboard splits cleanly: enforceable conventions become committed files, and established decisions become memories that every teammate's agent reads regardless of tool or plan tier.

Switching again gets cheap. opencode's instructions array and Cursor's .mdc frontmatter are both tool-specific formats. A store reachable over MCP is not, which means the next move is a config change rather than a knowledge audit.

And the specific annoyance that pushes people to write rules in the first place — being corrected on the same thing twice, or re-teaching the agent where things live in the repository — gets addressed at the right layer. That was never a rules problem. It was a memory problem being solved with a prompt.

Best practices after moving from Cursor to opencode

Verify the glob matched something. After wiring up instructions, ask opencode to summarize the guidance it loaded. If your Cursor rules are absent, the extension is the first thing to check.

Run /init after wiring, not before. It improves an existing AGENTS.md in place, so let it see your real setup.

Keep one instruction home per directory. AGENTS.md suppresses CLAUDE.md in the same place, so pick one and delete the other rather than leaving a dead file that looks live.

Be careful with remote instruction URLs. opencode can load instructions from a URL, and "remote instructions are fetched with a 5 second timeout." That makes a shared team rules file possible and also makes your session dependent on a host being up.

Do not recreate @ references by pasting content. Add the file to instructions or name it in prose. Pasting is what Cursor's own guidance warns against, since the copy goes stale.

Move history out before you flatten. Flattening conditional rules is only safe if the rules are actually conventions. Anything that reads like a war story belongs in a memory layer.

Conclusion

The honest summary of this migration is that opencode's instructions array is a genuinely good idea — reusing the rule files you already wrote beats rewriting them — with two documented gaps that the published example does not warn you about. One is trivial once you see it: the glob has to be .mdc, not .md, because Cursor ignores plain Markdown in .cursor/rules and your rules are therefore all .mdc. The other is structural: instructions combines everything it is given, so Cursor's Always / Intelligently / By-File / Manual distinction collapses to always-on.

Both are manageable, and the second one mostly because much of what filled up your rules directory should never have been a rule. Point the glob correctly, run /init on top, sort the frontmatter into free, expensive, and on-demand, and move the accumulated history to a layer that neither tool has to own. What is left is a short instruction file that says how to work in this repository — which is all a rules system was ever good at.

Frequently asked questions

Why did opencode load none of my Cursor rules?

Almost certainly the extension. Cursor project rules must be .mdc — Cursor states that "a plain .md file in .cursor/rules is ignored by the rules system because it has no frontmatter" — while opencode's documented example glob is .cursor/rules/*.md. Change it to .cursor/rules/**/*.mdc, which also covers rules organized in subfolders.

Does opencode respect globs and alwaysApply in my rule files?

No documented support for either. opencode's docs say "all instruction files are combined with your AGENTS.md files," with no conditional layer described. Treat everything you list in instructions as always on.

Will opencode read my CLAUDE.md?

Yes, as a fallback. In a project directory it uses CLAUDE.md "if no AGENTS.md exists," and globally it uses ~/.claude/CLAUDE.md if ~/.config/opencode/AGENTS.md does not exist. Creating an AGENTS.md in the same place turns the CLAUDE.md off, since "the first matching file wins in each category."

Is /init safe to run on a repo that already has instructions?

Yes. opencode's docs state that "if you already have an AGENTS.md, /init will improve it in place instead of blindly replacing it." It also scans for existing instruction sources like Cursor or Copilot rules while it works.

What happens to Cursor Team Rules?

They do not carry over. Team Rules live in the Cursor dashboard on Team and Enterprise plans and can be marked so members cannot disable them. In opencode, the equivalent is committed files plus a shared memory layer — which is more portable and less enforceable.

How do I keep context across machines now?

Neither tool's rule system does that for you; rules are files you commit, and per-machine config is per machine. If that is the actual problem you are solving, stopping Cursor from forgetting across machines and carrying Cursor context across sessions cover the pattern, and it applies unchanged in opencode.