Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tooling

This page answers: as an agent integrating with Argon (writing code, calling diagnostics, wiring an MCP harness), what does the tooling surface look like and how do I use it?

For the language itself, see Quick Reference. For why this surface exists in the shape it does, see RFD-0027. For the diagnostic schema’s stability commitment, see RFD-0028.

Architecture in one paragraph

Argon’s agent-facing tooling is layered. Tier 0 is the universal floor: every ox subcommand relevant to agents accepts --json and emits payloads conforming to schemas under share/argon/schemas/. Any harness that can run a shell command and parse JSON is integrated. Tier 1 is the MCP transport: ox mcp exposes the same operations as MCP tools, bytewise-identical to the CLI JSON. Tier 2 is the VS Code / Cursor extension for in-editor humans (and IDE-mode agents). Tier 3 is per-agent skill / rules files (share/agents/_common/argon-skill.md plus per-agent variants) that teach agents which Tier 0 / Tier 1 capability to reach for.

All four tiers are backed by a single in-process surface library, oxc-agent-surface. Transports never reimplement operations; they’re wire-format projections of typed Rust function calls.

Tier 0 — universal CLI + JSON schemas

Every agent-relevant subcommand accepts --json:

CommandSchemaNotes
ox check --jsondiagnostics.schema.json (v1.0, ratified by RFD-0028)Type-check + meta-property calculus + package constraints. Returns a DiagnosticsReport.
ox explain <code>(planned: explain.schema.json)Diagnostic code → prose with example fix. Currently text output.
ox query <name> --json(planned: query-result.schema.json)Run a named query against compiled state. Bindings + provenance.
ox tree --json(planned: package-tree.schema.json)Resolved package tree + lockfile state.
ox why <package>(planned: provenance.schema.json)Path-to-package explanation; provenance walk.

Schema files ship inside the toolchain at ~/.argon/toolchains/<version>/share/argon/schemas/. Their version manifest is version.json:

{
  "schema_set": "0.1.0",
  "schemas": { "diagnostics": "1.0.0" },
  "stable": ["diagnostics"]
}

Schemas listed in stable have crossed SemVer 1.0 via their ratification RFD; pin against those with confidence. Pre-1.0 schemas may break between minor toolchain releases.

Example: ox check --json

$ ox check --json | jq '{schema_version, summary}'
{
  "schema_version": "1.0.0",
  "summary": { "errors": 1, "warnings": 0, "infos": 0 }
}

The full payload:

{
  "schema_version": "1.0.0",
  "diagnostics": [
    {
      "code": "OE0226",
      "severity": "error",
      "message": "metarel endpoint mismatch",
      "primary_span": {
        "file": "src/lease.ar",
        "byte_start": 142, "byte_end": 154,
        "line_start": 8, "col_start": 5,
        "line_end": 8, "col_end": 17
      },
      "primary_label": "expected `kind`, found `role`",
      "secondary_labels": [],
      "help": null,
      "package_origin": "ufo",
      "provenance_chain": []
    }
  ],
  "summary": { "errors": 1, "warnings": 0, "infos": 0 }
}

Every Diagnostic carries the same nine fields. severity is one of "error" | "warning" | "info". primary_span is null for spanless diagnostics (CLI-layer cross-format errors with no .ar source); when present, it carries both 0-indexed UTF-8 byte offsets and 1-indexed UTF-16 line/column. Column units are UTF-16 code units, matching LSP’s code-unit-width convention so multi-byte characters land in the same column an LSP-aware editor would compute. Indexing diverges from LSP — LSP’s Position is 0-indexed for both line and character — so an agent passing these into LSP Position fields must subtract 1 from each. Argon emits the editor-display form (1-indexed) per RFD-0028.

Exit code: 0 when summary.errors == 0, non-zero otherwise. Configuration errors in ox.toml short-circuit before any diagnostic compilation runs and surface as their own diagnostics in the same payload shape.

Tier 1 — MCP transport (ox mcp)

ox mcp is the Model Context Protocol server. Speaks JSON-RPC 2.0 over stdio. Configure your agent (Cursor, Claude Code, opencode, Codex, Continue, Aider) to launch it as an MCP server. oxup agents register writes the relevant config for detected agents on toolchain install — see Tier 4 below.

Tool surface

ToolWrapsReturns
argon_checkox check --json over a workspaceDiagnosticsReport (text content with JSON body)
argon_explainox explain <code>Text
argon_check_file(planned) file-scoped checkDiagnosticsReport
argon_queryox query --jsonBindings + provenance
argon_packagesox tree --jsonPackage tree
argon_whyox why --json (post-provenance)Provenance walk

Tool payloads are bytewise-identical to CLI JSON because both transports route through the same oxc-agent-surface library — drift between channels is structurally impossible.

Lifecycle (v0 vs v1)

ox mcp ships in two scheduled phases within one release cycle.

  • v0 (current): thin spawning transport. Each MCP tool call invokes the corresponding ox CLI subcommand as a child process and streams its JSON output back. No persistent compiler state. Cold cache on every call. Simple lifecycle.
  • v1 (next): persistent OxcContext. Holds one Salsa database across tool calls; warm caches across requests; correct cache invalidation against file changes between calls. Production-traffic shape. Same wire surface — clients targeting v0 work unchanged on v1.

See RFD-0027 for the rationale on shipping v0 first.

Wire example

→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0.0"}}}
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","serverInfo":{"name":"argon","version":"0.4.x"},"capabilities":{"tools":{}}}}

→ {"jsonrpc":"2.0","id":2,"method":"tools/list"}
← {"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"argon_check","description":"...","inputSchema":{...}},...]}}

→ {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"argon_check","arguments":{"workspace":"/abs/path/to/project"}}}
← {"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{\"schema_version\":\"1.0.0\",...}"}],"isError":false}}

Workspace is optional; omitted falls back to the server’s launch CWD. Absolute paths only — relative paths surface a -32602 invalid params error to avoid CWD-drift surprises across tool calls.

Tier 2 — IDE extension

The Argon VS Code / Cursor extension wraps ox-lsp for in-editor humans and IDE-mode agents that pick up diagnostics via the editor’s extension-to-context glue. Install with:

oxup extension install

Or cursor --install-extension <vsix> against a release VSIX. Once installed, the language server activates on .ar files, populates the InfoView panel, and surfaces diagnostics through the editor’s standard publishDiagnostics channel. Agents running inside Cursor / VS Code see those diagnostics as part of their normal context.

Tier 2 is unchanged by RFD-0027 — it’s the existing surface, retained.

Tier 3 — per-agent skills / rules

Skill / rules files teach an agent which Tier 0 / Tier 1 capability to reach for. They’re documentation pointers, not implementations.

oxup agents register (called automatically by oxup install / update / default) walks every share/agents/<id>/ directory in the active toolchain and drops the skill file at the agent-specific config location:

AgentTarget
Cursor~/.cursor/rules/argon.md
Claude CodeSkill plugin via ~/.claude/settings.json marketplace pointer
Codex~/.codex/AGENTS.md
opencoderule file under opencode’s rule directory

Single-source content lives at share/agents/_common/argon-skill.md. Per-agent variants under share/agents/<id>/ wrap that body with the frontmatter each agent expects. Substantive edits land in _common first.

If you maintain agent integrations in your project, you can override the global skill with a project-local file at <workspace>/.cursor/rules/argon.md (or the equivalent for your agent). Project-local rules win over global ones.

Tier 4 — registration as data

share/agents/<id>/registration.toml is a per-agent descriptor read by oxup agents register. Adding a new agent that uses an existing handler kind is a share/ data drop — no Rust changes required.

Descriptor shape:

[agent]
id = "cursor"
name = "Cursor"

[detect]
config_dir = "~/.cursor"   # ~ expanded against $HOME

[[register]]
kind = "mcp-server"
config_relative = "mcp.json"
server_name = "argon"
argv = ["ox", "mcp"]

Detection is per-agent presence — missing config dir means the registration step is a silent no-op. Registration steps are idempotent on re-run; toolchain bumps re-aim transparently.

Currently supported handler kinds:

  • claude-marketplace — merge a marketplace pointer + enabledPlugins entry into Claude Code’s ~/.claude/settings.json. Used by share/agents/claude-code/registration.toml.
  • mcp-server — merge an mcpServers.<name> entry into the agent’s MCP JSON config. Used by share/agents/cursor/registration.toml. The same kind works for any agent consuming the standard MCP mcpServers shape.

New kinds extend the RegistrationStep enum + dispatch in oxup::agents. Adding a kind is a Rust change; adding a new agent that uses an existing kind is purely a share/ data drop.

I want to … do Y

TaskReach for
Get diagnostics on a workspaceox check --json (or argon_check over MCP)
Understand what a diagnostic code meansox explain <code> (or argon_explain over MCP)
See what packages a workspace depends onox tree --json (or argon_packages over MCP)
Run a named query against compiled stateox query <name> --json (or argon_query over MCP)
Wire my agent up to call Argon’s MCP toolsoxup agents register (runs automatically on oxup install)
Install the editor extensionoxup extension install
Pin against a stable wire formatcheck share/argon/schemas/version.json’s stable array
Override the global skill content for one projectdrop a project-local rule file (e.g. .cursor/rules/argon.md)

Stability discipline

  • Schemas in stable: SemVer-locked. Breaking change → major bump; additive change → minor bump. Consumers pin.
  • Schemas not in stable: pre-1.0, may break between minor toolchain releases. Each schema graduates to 1.0 via its own follow-up RFD as the underlying surface stabilizes.
  • MCP wire shape: tracks the published MCP spec revision. The server announces its supported protocolVersion during initialize; clients negotiate.
  • Tool names + argument shapes: stable within a major. Adding a new tool is non-breaking; renaming or removing a tool requires a major bump.
  • CLI flags: --json is stable; per-command flag changes follow the standard ox CLI deprecation cycle.

Anti-patterns

  • Don’t infer diagnostics from prose. Parse the JSON. The wire format is the contract.
  • Don’t fork wire shapes between transports. CLI JSON, MCP tool payloads, and (future) LSP-extended response bodies are all the same data, projected from the same in-process surface. If you find yourself reconstructing a payload differently in different places, you’ve drifted.
  • Don’t depend on a non-stable schema in production. Pre-1.0 schemas may evolve. Use them, but pin to the toolchain version, and watch the next ratification RFD.
  • Don’t hand-author files generated by oxc-codegen. Schemas, TypeScript bindings, and the diagnostic registry are emitted from Rust source-of-truth types via schemars / ts-rs. Drift is gated by oxc-codegen check in CI.
  • Don’t run ox mcp with relative workspace paths. v0 rejects them with -32602 invalid params; this is intentional and stays in v1.

Where this ships

  • Schemas: ~/.argon/toolchains/<version>/share/argon/schemas/
  • Skill content (single-source): ~/.argon/toolchains/<version>/share/agents/_common/argon-skill.md
  • Per-agent variants: ~/.argon/toolchains/<version>/share/agents/<id>/
  • Registration descriptors: ~/.argon/toolchains/<version>/share/agents/<id>/registration.toml
  • ox binary: ~/.argon/toolchains/<version>/bin/ox
  • LSP binary: ~/.argon/toolchains/<version>/bin/ox-lsp

oxup proxies (~/.argon/bin/ox, etc.) resolve the active toolchain via ox-toolchain.toml walk-up and exec the version-specific binary; integration code never hard-codes an absolute path.

See also

  • RFD-0027 — the architecture rationale (why CLI is the floor, why MCP is Tier 1, why registration is data).
  • RFD-0028 — diagnostics schema 1.0 ratification.
  • Anti-Patterns — Argon-language anti-patterns (vs the tooling-specific ones above).
  • Decision Guides — choosing between Argon language constructs.