Skip to content
Nauro

Guides

Connect your agent

The default path is the local stdio MCP server: nauro serve --stdio resolves the project store from the repo's .nauro/config.json. nauro setup and nauro adopt write that stdio entry directly into each surface's config file. A separate, optional cloud path reaches the project from surfaces without a local copy via nauro auth login, nauro link --cloud, nauro sync, and the remote connector at https://mcp.nauro.ai/mcp. As of 1.0, the stdio MCP tool contract is stable and follows semantic versioning; the cloud connector and hosted store are generally available, versioned and operated separately.

Two connection planes: local stdio vs cloud connector

Nauro has two distinct transports for the same store and payloads:

  • Local. The stdio MCP server, spawned per-session by the agent client. It is canonical for any machine with a working copy.
  • Cloud. The hosted HTTP connector at https://mcp.nauro.ai/mcp, used from surfaces without a local checkout (claude.ai web) or from another machine.

stdio is the sole supported local transport; the former local FastAPI HTTP transport was retired (per the serve.py docstring). The cloud connector is HTTP and lives in a separate, private hosted server.

The stdio server resolves project context from the current directory's .nauro/config.json; there is no --project flag on serve (one source of truth, per the serve.py docstring).

Commit .nauro/config.json as the portable project-identity pointer. Client wiring is machine-local because it records an absolute executable path. Setup regenerates that wiring per machine, adds its repo-local files to a managed .gitignore block, and refuses to write a machine-local path into a file already tracked by git.

Same store and payloads on both planes: the stdio server delegates to the transport-agnostic implementations in nauro.mcp.tools, which call into nauro_core.operations.

Local plane Cloud plane
Transport stdio (spawned per session) HTTP connector
Endpoint nauro serve --stdio https://mcp.nauro.ai/mcp
When to use Any machine with a working copy (canonical) Surfaces with no local checkout, or another machine
Project resolution From the cwd's .nauro/config.json From the authenticated cloud project

The local stdio server registers 10 MCP tools (7 read, 3 write). The shared nauro_core.mcp_tools.ALL_TOOLS registry has 11; list_projects is remote-only because local installs auto-resolve to the single project store.

Counted the other way: 11 tools total (8 read, 3 write), with list_projects among the reads; the local-only subset is 7 read + 3 write = 10.

text · local stdio tools
get_context, get_raw_file, list_decisions, get_decision,
diff_since_last_session, search_decisions, check_decision,
propose_decision, flag_question, update_state

# list_projects is remote-only (11th tool in nauro_core.mcp_tools.ALL_TOOLS)

Source: serve.py; stdio_server.py (module docstring; run_stdio); tools.py (module docstring); README.md (MCP tools section).

The local stdio MCP server (nauro serve --stdio)

nauro serve --stdio calls run_stdio(), which runs a best-effort session-start pull (_pull_on_startup()), then mcp.run(transport="stdio"). The MCP client (Claude Code, Cursor, Codex) spawns this process and talks over stdin/stdout. Nauro sends no product analytics.

The --stdio flag is hidden and a no-op: it is accepted only for backward compatibility with installed client configs that spawn nauro serve --stdio. stdio is now the only transport (the serve Typer option is hidden=True with default True).

On startup, _pull_on_startup() resolves the project through the canonical two-tier waterfall: walk up to a .nauro/config.json, then try a v2 registry repo-path match. The v1 registry is not a resolution fallback.

If the project is cloud-mode with a stored token, it pulls the latest from remote (pull_before_session) before accepting tool calls. It never raises: on failure the server logs a warning and starts with local state.

Store resolution precedence inside tools is: an explicit project_id argument, else the cwd's .nauro/config.json, else the registry. When unresolved, tools return a guidance envelope (NOT_A_NAURO_REPO / WELCOME_NO_PROJECT) rather than crashing.

The FastMCP server is constructed as FastMCP("nauro", instructions=MCP_INSTRUCTIONS, log_level="WARNING").

The "nauro" name pairs with the stdio entry's command; behavioral guidance ships via MCP server instructions, not an injected CLAUDE.md block. Setup automatically strips Nauro's retired marked block if it finds one. A separate Nauro-owned two-line CLAUDE.md bridge may import @AGENTS.md so Claude Code also sees the generated shared context.

python · stdio_server.py
def run_stdio() -> None:
    """Run the MCP server over stdio (called by `nauro serve --stdio`)."""
    _pull_on_startup()
    mcp.run(transport="stdio")

Source: serve.py; stdio_server.py (run_stdio, _pull_on_startup, FastMCP construction).

nauro setup [claude-code|cursor|codex|all]: what it writes

nauro setup wires the local stdio server into each surface's config by writing the file directly, not by shelling out to the client's own mcp add.

All surfaces use the same key name nauro and the same entry shape: {"command": "<validated absolute path to nauro>", "args": ["serve", "--stdio"]}. _find_nauro_command probes candidates with --version and prefers a durable absolute pipx, uv tool, system, or equivalent install. If only a working project-venv sibling is available, setup records it with a fragility warning. Otherwise it records the best path it has and warns that MCP may not work; bare nauro is the terminal fallback.

Subcommand Writes Key / scope Flags
setup claude-code <repo>/.mcp.json per registered repo path mcpServers.nauro (project scope) --project, --remove, --with-hooks
setup cursor <repo>/.cursor/mcp.json per repo mcpServers.nauro --project, --remove
setup codex ~/.codex/config.toml [mcp_servers.nauro] (user-global) --remove, --with-hooks
setup all Claude Code + Cursor + Codex in one call; refreshes Nauro-managed AGENTS.md all of the above --project, --remove, --with-subagents, --force-overwrite, --with-skills, --with-hooks

Adopt, setup, and incidental regeneration paths preserve an unmanaged AGENTS.md and warn. nauro sync is the sole explicit overwrite path. A # Manual section survives replacement.

setup claude-code automatically removes Nauro's retired marked block from CLAUDE.md. When no CLAUDE.md exists, the shared AGENTS.md regeneration seam writes a Nauro-owned two-line bridge containing @AGENTS.md. An existing foreign CLAUDE.md is never modified: an existing live import is accepted, otherwise setup prints an advisory. Teardown removes only the validated Nauro-owned bridge. Setup also prunes a redundant user-scope HTTP nauro entry from ~/.claude.json; a user-defined stdio entry is left alone.

Standalone nauro setup codex --remove preserves the user-global entry while any Nauro project remains registered, including the current project when it is the only one. Clear it for the last project with nauro setup all --remove from that project. setup all continues across per-handler errors so partial coverage still reports progress.

--with-subagents (on setup all / adopt) installs the bundled planner, executor, reviewer, and tech-lead roles for both supported agent surfaces. Claude Code receives Markdown definitions in ~/.claude/agents/; Codex receives TOML definitions in ~/.codex/agents/. Cursor has no subagent format.

A differing Nauro-owned skill or agent definition is refreshed and its prior content is saved to a sibling .bak. --force-overwrite skips that backup and overwrites in place. Files outside Nauro's owned names are left untouched.

Claude Code's bundled definitions reference cloud tools through mcp__claude_ai_Nauro__*, so its remote connector must be named exactly Nauro. Codex renders the same role instructions in its native format and does not share that connector-name constraint.

--with-hooks wires two surface-specific integrations. Claude Code gets an advisory UserPromptSubmit hook in <repo>/.claude/settings.local.json that retrieves related decisions for each turn. Codex gets SessionStart and SubagentStart hooks in <repo>/.codex/hooks.json that inject the Nauro protocol and current L0 context.

Both hook integrations are project-scoped, idempotent, and fail open. Removal strips only Nauro-authored entries. Codex skips new or changed hooks until the user reviews and trusts them through /hooks. Cursor has no hook integration.

json · .mcp.json (Claude Code / Cursor)
{
  "mcpServers": {
    "nauro": {
      "command": "<validated absolute path to nauro>",
      "args": ["serve", "--stdio"]
    }
  }
}
toml · ~/.codex/config.toml
[mcp_servers.nauro]
command = "<validated absolute path to nauro>"
args = ["serve", "--stdio"]
shell
$ nauro setup all --with-skills --with-subagents # complete Claude Code + Codex workflow
$ nauro setup all --with-hooks                 # optional Claude Code + Codex hooks
$ nauro status                                 # diagnose integration wiring
$ nauro doctor                                 # check store integrity

Source: setup.py (claude_code, cursor, codex, all_); integrations/orchestrator.py (setup_all_surfaces); integrations/agents.py (materialize_agents); integrations/claude_hooks.py; integrations/codex_hooks.py.

nauro adopt: register and wire in one shot (existing repo)

nauro adopt bootstraps a project from an existing repo. It detects the repo root (or --repo), refuses non-git directories (_is_git_repo), guards against re-adopting (an existing .nauro/config.json), and runs a same-name collision pre-check against the local v2 registry (_check_collision via find_projects_by_name_v2).

Use nauro adopt --with-skills --with-subagents for the complete Claude Code and Codex workflow. Plain nauro adopt is the minimal path: it wires MCP and installs the core nauro-adopt skill.

It then registers a v2 project (register_project_v2, mode=local), writes .nauro/config.json (save_repo_config), and scaffolds the store (scaffold_project_store), before wiring MCP and materializing skills across Claude Code, Cursor, and Codex via setup_all_surfaces.

After wiring, adopt smoke-tests the wired binary by booting <nauro> serve --stdio briefly (_smoke_test_wired_binary, default timeout 1.5s): a clean exit on stdin EOF (returncode 0) or a process still running at timeout is healthy; a non-zero exit before timeout (an import crash) prints a WARNING.

The closing message instructs the user to restart their agent and invoke /nauro-adopt in Claude Code or $nauro-adopt in Codex. Cursor uses the installed rule.

Adopt preserves an unmanaged AGENTS.md and warns.

Flags: --name, --repo, --print-prompt (mutually exclusive with all other flags; prints the canonical /nauro-adopt skill body to stdout via load_adopt_body() for pasting into chat surfaces), --no-setup-and-skills (skip MCP wiring and skill materialization), --with-subagents, --force-overwrite, --with-skills, and the teardown trio --remove / --purge-store / --yes (next paragraph).

If the repo is already adopted and the caller passes --with-subagents / --with-skills / --force-overwrite, adopt installs just those artifacts onto the existing adoption (_install_into_adopted_repo via setup_all_surfaces, registration untouched) instead of dead-ending.

nauro adopt --remove is the inverse: after a confirmation prompt (--yes skips it) it un-wires the MCP, skill, subagent, and hook entries, strips the generated AGENTS.md (a # Manual section is preserved), deletes .nauro/config.json, and deregisters the repo. Only this repo is dropped when the project spans several, and the store is kept unless --purge-store is passed on the project's last repo.

The always-installed skill set is SKILL_NAMES = ("nauro-adopt",); --with-skills additionally installs OPT_IN_SKILL_NAMES = ("nauro-ship-task", "nauro-context", "nauro-loop"). nauro-ship-task references the @nauro-* subagents and nauro-loop dispatches that chain, so passing --with-skills without --with-subagents prints SHIP_TASK_NEEDS_SUBAGENTS_NOTICE; nauro-context composes only existing MCP tools and carries no such notice.

shell
$ cd /path/to/repo
$ nauro adopt --with-skills --with-subagents
$ nauro status
# Restart, then use /nauro-adopt in Claude Code or $nauro-adopt in Codex

Source: adopt.py (adopt, _is_git_repo, _smoke_test_wired_binary, _check_collision, _install_into_adopted_repo, --print-prompt, load_adopt_body); setup.py (SKILL_NAMES, OPT_IN_SKILL_NAMES).

Cloud path: auth login → link --cloud → sync (distinct steps)

The cloud path is opt-in and reaches a project from surfaces without a local copy or from another machine. It is three separate steps.

Step 1, nauro auth login. An Auth0 Authorization Code + PKCE (S256) flow. It opens a browser, runs a localhost callback server on REDIRECT_PORT = 18457 (redirect_uri http://localhost:18457/callback), waits up to 120s for the code, exchanges it, and stores tokens in ~/.nauro/config.json under the "auth" key (with sub, sanitized_sub, user_id, access_token, refresh_token).

The public OAuth identifiers (not secrets) are DEFAULT_API_URL=https://mcp.nauro.ai, DEFAULT_AUTH0_AUDIENCE=https://mcp.nauro.ai/mcp, and AUTH0_SCOPES="openid profile email offline_access read:context write:context".

The closing message tells cloud users to add https://mcp.nauro.ai/mcp as a connector and, for Codex, to set mcp_oauth_callback_port = 8765 at the top of ~/.codex/config.toml.

Step 2, nauro link --cloud. A one-time, one-way promotion of the current repo's local-only project to cloud. It reads the local-mode .nauro/config.json, requires auth (errors with "Run 'nauro auth login' first" otherwise), calls the remote POST /projects (create_project) to mint a cloud project_id, re-keys the local store directory and v2 registry entry under the new id (rename_project_id_v2, preserving repo_paths and store contents), and rewrites .nauro/config.json to mode=cloud with server_url=https://mcp.nauro.ai (DEFAULT_API_URL).

There is no inverse "unlink to local". The re-key is the irreversible step and persists before the push; the initial push (push_changed_files) is best-effort: a transient presign/S3 failure warns and exits 0, and nauro sync retries the upload.

Step 3, nauro sync. Captures a snapshot and explicitly replaces AGENTS.md in associated repos; it is the sole overwrite path, and a # Manual section survives replacement. With cloud sync configured it does a git-style pull-then-push: pull first (_pull_via_presign: GET /sync/manifestPOST /sync/presign → S3 GETs), then push (push_store_to_cloud).

For a local-only project it captures the snapshot and reports "local-only project; nothing to upload". Flags: --message/-m, --project, --status. The MCP update_state tool records what changed; sync does not touch state_current.md.

nauro attach <project_id> is the cloud equivalent of init --add-repo: associate the current repo with an existing cloud project (membership is verified against GET /projects via list_projects before any local write), writing a cloud-mode .nauro/config.json. For a fresh start, nauro init --cloud <name> creates a cloud-scoped project up front.

After the steps, add https://mcp.nauro.ai/mcp as an MCP connector in your tool's settings. Enter the URL exactly, with no trailing slash.

shell
$ nauro auth login
$ nauro link --cloud   # one-time: promote the local project to cloud
$ nauro sync
# then add https://mcp.nauro.ai/mcp as an MCP connector (no trailing slash)

Source: auth.py (login, DEFAULT_API_URL, DEFAULT_AUTH0_AUDIENCE, AUTH0_SCOPES, REDIRECT_PORT, REDIRECT_URI, closing message); link.py (link); sync.py (sync, _pull_via_presign, _pull_from_cloud); attach.py (attach); cloud_projects.py (create_project, list_projects); README.md (Cross-surface sync section).

Codex remote connector

  • Add the hosted connector under a name distinct from the local nauro stdio server: codex mcp add nauro-cloud --url https://mcp.nauro.ai/mcp.
  • Pin the OAuth callback port at the top of ~/.codex/config.toml: mcp_oauth_callback_port = 8765. Codex's callback uses a fixed, pre-registered port; without this line Codex picks a random port and login fails. The closing message from nauro auth login also surfaces this requirement.
  • Requires Codex 0.131.0 or newer. Enter the URL exactly as shown, with no trailing slash. If login reports a callback-port error, free port 8765.
  • This is separate from nauro setup codex, which wires the local stdio server under [mcp_servers.nauro] in the same ~/.codex/config.toml. The remote connector (nauro-cloud) and the local stdio server (nauro) coexist under different names.
shell
$ codex mcp add nauro-cloud --url https://mcp.nauro.ai/mcp
toml · top of ~/.codex/config.toml
mcp_oauth_callback_port = 8765

Source: README.md (Codex remote connector section); auth.py (login closing message); setup.py (_configure_codex, the local stdio entry under [mcp_servers.nauro]).

Chat surfaces (Claude.ai, Perplexity)

Chat-paste mode does not create projects. First run nauro adopt --name <project> from a terminal: that registers the project, wires MCP across surfaces, and installs the skills.

Only then can the chat agent seed context.

After adoption, point the chat agent at docs/adopt-prompt.md. nauro adopt --print-prompt outputs the same canonical /nauro-adopt skill body to stdout (without the intro paragraph) for copy/paste.

Chat surfaces have no shell, so the skill operates only on content the user pastes (Step 3b) and only against an already-adopted project (verified in Step 2). The code-evidence path (Step 4) and the targeted probes (Step 6b) are unavailable; the skill skips from Step 3b directly to Step 5.

On chat surfaces the skill passes the project's id as the explicit project_id argument on every MCP call (propose_decision, update_state, flag_question, get_context, list_decisions, check_decision, get_decision).

Auto-resolve would otherwise route to the user's default project, not the one being seeded when local and cloud projects coexist.

Reaching a project from a chat surface without a local copy still requires the cloud connector (https://mcp.nauro.ai/mcp) configured in that tool's settings: the cloud path above must already be done.

shell
$ nauro adopt --name <your-project-name>   # register + wire MCP + install skills
# then in chat, follow docs/adopt-prompt.md (or: nauro adopt --print-prompt)

Source: docs/adopt-prompt.md (intro, Surface modes, Step 2, Step 3b); README.md (Chat surfaces line); adopt.py (--print-prompt, load_adopt_body).

Key facts and gotchas

  • The local stdio MCP entry is keyed nauro with shape {"command": "<validated absolute path to nauro>", "args": ["serve", "--stdio"]} when a durable install is available. Resolution validates candidates, prefers durable absolute paths, warns before recording a fragile working path, and uses bare nauro only as the warned terminal fallback.
  • setup writes config files directly: claude-code → <repo>/.mcp.json (project scope, per repo); cursor → <repo>/.cursor/mcp.json (per repo); codex → ~/.codex/config.toml under [mcp_servers.nauro] (user-global).
  • The cloud connector URL is https://mcp.nauro.ai/mcp; enter it exactly, with no trailing slash.
  • Codex remote connector: codex mcp add nauro-cloud --url https://mcp.nauro.ai/mcp; requires mcp_oauth_callback_port = 8765 at the top of ~/.codex/config.toml; requires Codex 0.131.0 or newer.
  • auth.py constants: DEFAULT_API_URL=https://mcp.nauro.ai, DEFAULT_AUTH0_AUDIENCE=https://mcp.nauro.ai/mcp, REDIRECT_PORT=18457, REDIRECT_URI=http://localhost:18457/callback, AUTH0_SCOPES="openid profile email offline_access read:context write:context"; tokens are stored in ~/.nauro/config.json under "auth"; the callback timeout is 120s.
  • The cloud path is three distinct steps kept separate: nauro auth loginnauro link --cloud (one-time, one-way promotion; no inverse) → nauro sync.
  • The local stdio server registers 10 MCP tools (7 read, 3 write); nauro_core.mcp_tools.ALL_TOOLS has 11 (8 read, 3 write); list_projects is remote-only.
  • stdio is the only supported local transport (the FastAPI HTTP transport was retired); --stdio is a hidden no-op kept for backward compatibility; there is no --project flag on serve.
  • nauro adopt registers a v2 project (mode=local), wires all surfaces via setup_all_surfaces, smoke-tests the binary, and installs the nauro-adopt skill. Use /nauro-adopt in Claude Code, $nauro-adopt in Codex, or the installed rule in Cursor.
  • Complete workflow: nauro adopt --with-skills --with-subagents. The four roles install into ~/.claude/agents/ as Markdown and ~/.codex/agents/ as TOML. Cursor has no subagent format.
  • Claude Code's workflow definitions require the remote connector name Nauro so their mcp__claude_ai_Nauro__* tools resolve. Codex does not share that connector-name constraint.
  • nauro setup all --with-hooks writes Claude Code's advisory UserPromptSubmit hook to <repo>/.claude/settings.local.json and Codex's SessionStart / SubagentStart hooks to <repo>/.codex/hooks.json. Review new Codex hooks through /hooks.
  • Verification: nauro status diagnoses MCP and workflow wiring; nauro doctor checks store integrity. Start a fresh agent session for the final MCP check.
  • Chat surfaces: run nauro adopt in a terminal first (chat-paste mode does not create projects), then point the agent at docs/adopt-prompt.md; the skill passes an explicit project_id on every MCP call.
  • setup claude-code prunes a redundant user-scope HTTP nauro entry from ~/.claude.json because project-scope stdio is canonical and a same-name collision can resolve to the wrong store (only the HTTP/url entry is pruned; a user-defined stdio entry is left alone).

Gotchas to watch for:

  • The local stdio entry uses command/args (nauro serve --stdio), not a url; the url form (https://mcp.nauro.ai/mcp) is only for the hosted/remote connector. Do not present the cloud URL as the local .mcp.json value.
  • nauro setup codex (local stdio under [mcp_servers.nauro]) is a different thing from the Codex remote connector nauro-cloud added via codex mcp add --url. They coexist under different names in the same ~/.codex/config.toml.
  • link --cloud is one-way and irreversible: the re-key persists before the cloud push, and a failed push does not roll it back (it warns, exits 0, and you retry with nauro sync). There is no "unlink to local" command.
  • Codex's 8765 port is Codex-side and unrelated to nauro's own 18457 auth-login callback port.
  • Cloud-mode projects cannot be extended with init --add-repo; use nauro attach <project_id> instead.