mate
Reference

Command Reference

Current Mate CLI commands and their execution contexts.

Setup And Linking

CommandContextPurpose
mate companion setupCompanion rootCreate or reconfigure a companion explicitly.
mate companion linkWorking repository, TTYSelect or clone a companion, write the link, and install its requirements.
mate companion list [--json]Linked contextList linked repositories.
mate companion openLinked contextAdd the working repository and companion to the preferred editor.
mate companion tuiLinked context, TTYOpen a shell in the resolved companion.
mate companion syncLinked contextSync the companion with its Git upstream, interactively at a terminal.
mate companion update [--yes]Linked contextRegenerate the companion’s Mate-managed files with the newest stable Mate.
mate working cleanupWorking repositoryRemove Mate’s local integration from a linked working repository.

mate companion link does not accept flags. Its selection and any required installation confirmation are interactive. The default workflow is:

mate install
mate companion link
mate opencode

mate companion update requires a stable Mate that is also the newest stable release; otherwise it stops and asks you to run mate update first. It regenerates the companion’s Mate-managed files, skills, and OpenSpec output, raises engines.mate to the running version, and then offers to commit and push exactly the files it wrote. --yes commits and pushes without asking. Outside an interactive shell and without --yes, the changes stay uncommitted. A file you had edited locally before the update is reported, not silently overwritten.

mate working cleanup runs from a working repository linked to a companion. It removes the local .mate projection, Mate’s Git excludes, and the OpenSpec store pointer, and updates the Claude settings Mate wrote. Tracked files and product work are untouched, and the next link or launch recreates what it needs. Run from a companion or a repository that is not linked, it exits non-zero.

Installation And Health

CommandPurpose
mate install [--yes]Install and verify core requirements or refresh the active companion requirements.
mate doctorShow context, policy, selected capabilities, and tool status.
mate config [--vscode]Open the global ~/.mate configuration directory.

mate install --yes skips interactive confirmation and is required when the process has no TTY. It can run before a companion is linked; in that context it installs only Mate’s core requirements.

Comment Guidance

Shared agent guidance prefers sparse, concise comments explaining non-obvious intent, constraints, or workarounds—not filler or restatements of code. Use JSDoc for JS/TS API documentation and line or ordinary block comments for local notes, including JSX-supported expression comments. Preserve required documentation and contract details, tool directives, legal notices, and language-appropriate syntax. Concision does not mean terse implementation code or rewriting unchanged comments.

This is guidance, not an automated comment checker or completion gate. Repository-owned conventions and unrelated verification requirements are unchanged; stricter rules require an explicit repository decision. Existing companions receive the wording through normal managed-guidance regeneration.

Agent Launch

mate claude [-- agent-args...]
mate opencode [-- agent-args...]

Launch commands use a linked Working Repository by default. The companion’s allowed agents list must include the requested agent. To launch from the Companion Repository without a Working Repository, use the reserved token after the separator:

mate opencode -- --companion

Companion-scoped launches run the adapter from the Companion Repository, keep companion Git and runtime synchronization, policy enforcement, and capability preflight, but skip Working-Repository projection, automatic indexing, and Working-Repository-only hooks. The agent environment carries no MATE_REPO_PATH or MATE_REPO_ID.

Mate synchronizes managed companion files before launch. If the companion’s configuration uses Git auto mode, it also fetches and merges the configured upstream first:

mate claude -- --no-git
mate opencode -- --no-git

The --no-git switch is Mate’s option only when it appears after the -- separator. --companion selects the companion scope and --yes suppresses the interactive confirmation; these are also Mate options only after the separator. All other arguments after the separator are forwarded to the agent.

Confirmation is shown only when standard input is a TTY. Non-interactive launches proceed without a prompt.

OpenCode: Wrap, Prepare, Launch

mate opencode from a Working Repository syncs the companion with Git, wraps the repository for OpenCode when that wrap is missing or out of date, re-projects the companion copies and runs the capability preflight, then starts plain opencode. mate claude runs the same preparation and wraps the repository for Claude. At a terminal the companion Git sync is interactive, and a sync that still fails stops the launch. When another companion sync is running, the launch says so and waits for it. It sets no OPENCODE_CONFIG_DIR, so your global OpenCode configuration (~/.config/opencode) applies as usual; an OPENCODE_CONFIG_DIR or OPENCODE_CONFIG_CONTENT you set yourself is passed through. With -- --no-git only the local preparation runs.

Because the wrap carries everything, plain opencode in a wrapped repository is equivalent: before the session starts, the Mate plugin re-projects the companion copies and runs the capability preflight, waiting at most 30 seconds, and enables Mate’s MCP servers once that is done. It never waits on the network: the companion Git sync then runs in the background, fast-forward only, on every session start. Changes it brings in are re-projected into the running session. It cannot prompt, so a diverged history, a local edit the update would overwrite, or an unreachable remote is reported as a warning to restart with mate opencode, whose attended sync can resolve it, and the session keeps running on the current companion. This also holds when OpenCode’s shared background service was started from another directory.

Claude: Wrap, Then Launch

mate claude works like mate opencode: a launch is a wrap followed by a launch. Its preparation wraps the repository for Claude when that wrap is missing (never wrapped, or wrapped only for OpenCode) and reconciles it when it is out of date, before Claude starts. The launch then passes only what a wrap cannot deliver: the companion guidance, Mate’s own plugin, and any Claude plugin folder of an enabled Capability that the wrap could not publish. Capability hooks, Capability plugin folders (context-mode’s among them), Mate’s MCP servers, the companion skills and access to the companion directory come from the wrap, so each loads once. A companion-scoped launch has no wrap, so it passes every plugin folder itself. If the wrap fails, the launch stops before Claude starts and names the document that failed.

There is no launch-only mode for Claude any more: every mate claude from a Working Repository writes the wrap’s git-excluded documents and may write the repository’s entry in ~/.claude.json. A companion-scoped launch (mate claude -- --companion) has no Working Repository and wraps nothing.

Plain claude in a Claude-wrapped repository is prepared too: a SessionStart hook runs the local preparation (companion files, the Claude documents, the capability preflight), waiting at most 30 seconds, then starts the companion Git sync in the background, fast-forward only. A failure or warning is shown to you, never to the model, and the session starts either way. Capability MCP servers may start before the preflight finishes. Capability plugin folders, context-mode’s among them, load as well in a folder Claude Code trusts. Claude loads plugins before the SessionStart hook runs, so a Capability enabled since the last preparation loads from the session after it. mate doctor lists the folders and whether plain sessions load each one.

Mate’s managed Claude settings turn off Claude Code features that compete with Mate’s own workflow: they deny the EnterPlanMode and DesignSync tools and set enableArtifact: false, beside autoMemoryEnabled: false. Those tool denies are fixed. While secret guardrails are on, the managed deny list also carries Read and Edit deny rules for the default secret files (the Edit rule also covers Write); see Secret Guardrails. ExitPlanMode stays allowed, so plan mode entered by hand (Shift+Tab) can still be left. A managed launch applies these settings through --settings, and deny rules from there cannot be re-allowed from your own settings.

The managed settings also hide Claude Code’s commit and pull request attribution with attribution: { "commit": "", "pr": "", "sessionUrl": false }, so the session is never told to add a Co-Authored-By: Claude trailer. Mate writes the object form, never attribution: false, which Claude Code before v2.1.281 rejects along with the whole settings file. Your own setting wins: when your user settings, or the repository’s .claude/settings.json or .claude/settings.local.json, set attribution (or the older includeCoAuthoredBy), Mate leaves the key out. A managed launch checks again at every start. Model co-author trailers are still refused; see Commit Attribution.

Wrapping

mate wrap [--companion PATH]
mate unwrap

mate wrap makes sessions you start yourself (claude, opencode) load the companion. For OpenCode it writes .opencode/opencode.json regions (Mate plugin, companion skills, references.mate, permissions, MCP servers, and settings from the companion’s own .opencode/opencode.json that your repository does not set) and copies the companion’s .opencode/ files (commands, agents, skills, plugins, tools) into your repository’s .opencode/ as regular, git-excluded files. Mate records every copy it owns:

  • a file your repository already has at the same path wins; Mate warns and leaves it;
  • an owned copy you edited locally is replaced on the next re-projection, with a warning naming the companion file to edit instead;
  • a file removed from the companion is withdrawn from your repository.

Paths into the Mate installation go through ~/.mate/runtime/, which every mate run keeps pointing at the installed version, so a wrapped repository survives a reinstall or Node switch. Installing or upgrading does not create that directory; the first mate run does. Until then, plain opencode in a wrapped repository starts without the companion guidance and reports the missing directory, so run mate once after upgrading. If you uninstalled Mate, run mate unwrap (or mate once after reinstalling).

For Claude it writes .claude/settings.local.json regions (the artifact-path guard, banner, guidance and session-prepare hooks, every enabled Capability’s hooks, permissions, the secret-file deny rules while secret guardrails are on, and the same disabled features as a managed launch: the EnterPlanMode and DesignSync deny entries and enableArtifact: false) and the repository’s MCP servers into ~/.claude.json. That file is rewritten only when the servers change. An enableArtifact value you already set in .claude/settings.local.json is left as it is. The wrap also places the managed attribution value, unless one of your Claude settings already sets attribution; an attribution you set in .claude/settings.local.json is left as it is.

The wrap also links each companion skill folder (.claude/skills/<name>) and each companion command folder, such as OpenSpec’s .claude/commands/opsx/, into your repository’s .claude/, so /opsx:* works in plain claude too. A path your repository already has wins, and mate unwrap removes only the links Mate created.

Each enabled Capability’s Claude plugin folder is published as its own local marketplace and enabled in .claude/settings.local.json (extraKnownMarketplaces and enabledPlugins). Claude Code loads it from the folder itself, without copying it.

  • Marketplace file. A folder’s marketplace file is .claude-plugin/marketplace.json. If the plugin’s author ships one that lists the plugin, as context-mode does, Mate uses it. Otherwise Mate writes its own, named mate-plugin-<plugin>, and removes it when the Capability is disabled. Mate never changes a marketplace file it did not write. A file of Mate’s that no longer matches what Mate writes is rewritten at the next pass; until a rewrite succeeds, the wrap does not enable the folder, and mate claude passes it instead.
  • Folders that are not published load only through mate claude. Each is named once per command, with the reason: in one note from mate wrap, in one warning from mate claude, and not at all by mate session prepare, which plain sessions run. A folder is not published when:
    • the folder holds a marketplace file that Mate did not write and that does not list the plugin;
    • the plugin’s name cannot form a marketplace name;
    • your Claude Code configuration already uses the marketplace name with another source, for example context-mode added from GitHub. Mate leaves your marketplace alone;
    • Mate could not write its marketplace file into the folder, for example because the folder is read-only. The message gives the error.
  • Claude Code’s records. Claude Code records these plugins in ~/.claude/plugins/. Those records stay after mate unwrap, and have no effect once the plugin is no longer enabled.

Both session kinds work in a wrapped repository: plain claude / opencode and mate claude / mate opencode. Every managed launch wraps the repository for its runtime, so mate wrap is only needed for a repository you want to use with plain sessions before your first managed launch there. Session preparation keeps the documents current, so a Capability enabled after the wrap reaches the next session without re-wrapping. mate unwrap withdraws the documents and the owned copies and keeps the repository link; the withdrawal holds until the next mate claude or mate opencode there, which wraps again.

Session Preparation

mate session prepare --repo <dir> [--json] [--sync]

Runs what a managed launch prepares, without starting an agent, for each runtime the repository is wrapped for. Without --sync it touches no remote: it syncs and self-heals companion files, reconciles the wrapped documents in one pass (for OpenCode including the copies), and runs the capability preflight per runtime. When another companion sync holds the lock, it skips at once. With --sync it first fetches and fast-forwards the companion, then runs that local preparation only when the companion moved. A diverged history, an overlapping local edit or an unreachable remote is a warning to restart with the managed launch of a wrapped runtime (mate opencode or mate claude), not a failure. Every companion sync (managed launches, mate companion sync, session-start repairs and this command) is serialized through one lock per companion under ~/.mate/locks/. The command refuses a repository wrapped for neither runtime and names mate wrap. --json prints each step’s outcome, the runtimes each step answered for, and the warnings. It reports no Claude plugin-folder problems; mate wrap and mate doctor name them. The OpenCode plugin and the Claude session-prepare hook call this for you.

Exit Status And Signals

A launch exits with a status reflecting how the agent process ended: zero when the agent exited zero, non-zero when it did not. The JSON result is still printed, but it no longer stands in for the status.

A launch also forwards SIGINT and SIGTERM to the agent process it spawned and waits for that process to exit before exiting itself, so nothing is left running behind it. An agent that ends on a forwarded signal is reported as the signalled stop it was — 128 + signal, the usual shell convention — so a caller can tell a clean shutdown from a crash. At a terminal this is unchanged in practice: Ctrl-C reaches the whole foreground process group, so the agent is stopped once and the shell is returned.

This has no opt-out: a caller that read success from a zero exit will see agent failures.

Capabilities

CommandPurpose
mate cap openspec <subcommand> [args...]Run OpenSpec through the active context.
mate cap graphify <subcommand> [args...]Run Graphify through the active context.
mate cap indexRefresh enabled Graphify and TokenSave indexes.
mate cap index --graphifyRefresh only Graphify.
mate cap index --tokensaveRefresh only TokenSave.

The two index flags cannot be combined. When both Graphify and TokenSave are enabled, the default index flow refreshes TokenSave and then refreshes Graphify against the resulting state.

Every Graphify extraction Mate runs, and every one an agent runs through the graphify wrapper, leaves secret files out: Mate rewrites the secret region of the repository’s .graphifyignore and passes the secret patterns as --exclude. Afterwards it removes any secret that still reached the output and keeps the rest of the graph. A secret never stops the run. See Secret Guardrails.

Artifacts And Updates

CommandPurpose
mate artifact pending [--json]List archived changes and drifted specs that are not published yet.
mate artifact publish <target> [options]Commit, tag, and push one archived change.
mate updateUpgrade an npm-managed Mate installation and reinstall requirements.
mate update --checkCheck for an update without installing it.

mate artifact pending is read-only. It lists each archived OpenSpec change whose files are still uncommitted in the companion, with the canonical specs it applied, and separately lists uncommitted specs no pending change accounts for.

The publish target is a dated archive anchor (YYYY-MM-DD-<name>) or a change name that matches exactly one archive. Publishing never archives: archive the change first. Options:

  • --specs [<path>...] publishes drifted canonical specs as their own publication instead of a change; with paths, only those specs.
  • --all publishes every pending change in order, then the remaining spec drift, and stops at the first conflict or error.
  • --type openspec selects the publisher; it is the default.
  • --no-push commits and tags locally without pushing.
  • --json prints machine-readable results.

mate artifact finish is the deprecated name of publish: it still works but prints a warning. Update accepts --yes to skip its confirmation prompt.

mate artifact publish scans the files it is about to commit for secrets before the commit step. A finding stops the publication at a secret-scan step with no commit, tag, or push, and reports each file, line, and rule id without the value. With secrets.guardrails: false the scan is skipped with a one-line notice.

Exit And Recovery Behavior

Unknown commands print the current usage text and exit non-zero. Missing or stale installation state is repaired automatically when every requirement is already available. If a requirement is missing, the companion is ambiguous, or the Mate engine requirement is unsatisfied, Mate prints the reason and points to mate install instead. Doctor, setup, link, update, help, and version remain available so the state can be repaired.