The Problem
Instructions converged on AGENTS.md and skills converged on SKILL.md. MCP server configuration did not. Every tool keeps its own file, in its own format, in its own place:
Add a server by hand and you write it 18 times, then watch the copies drift apart.
agents keeps one source of truth in .agents/ and materializes it for every tool you enable.
Quick Start
# 1. Install
npm install -g @agents-dev/cli
# 2. Interactive setup — picks integrations, adds MCP servers, syncs everything
agents start
# 3. Re-sync whenever config changes
agents sync
.agents/agents.json is now the single source of truth. agents sync --check exits 2 when a tool config has drifted, so it works as a CI gate.
Supported Integrations
Eighteen tools. "Verified" means the tool's own CLI was run against the file this project writes; the rest follow vendor documentation and are worth reporting on if something is off.
Skills column. bridge means a symlink from the tool's directory to .agents/skills (a copy where symlinks are unavailable). native means the tool reads .agents/skills itself, so nothing is created. — means the tool's project-level skill location is not implemented here.
Grok folder trust. Grok ignores a project's MCP servers and its skills until the folder is trusted, and says nothing about it: grok inspect simply lists none. Trust lives in ~/.grok/trusted_folders.toml, separate from config.toml. agents doctor reports an untrusted folder and agents doctor --fix records the trust.
Shared files. .mcp.json is read by both Claude Code and Copilot CLI, so agents writes it once for both. A server targeted at only one of them is still visible to the other; the sync says so rather than pretending targets isolate it.
Goose secrets. Goose reads credentials from the environment through env_keys, so values are never written into its config. The sync lists which variables have to exist in your shell.
Project Layout
your-project/
├── AGENTS.md ← Canonical instructions for all tools
├── CLAUDE.md ← Generated Claude wrapper (`@AGENTS.md`)
├── .agents/
│ ├── agents.json ← MCP servers, profiles, config (commit this)
│ ├── local.json ← Secrets & overrides (gitignored)
│ ├── mcp_config.json ← Generated Antigravity workspace MCP
│ ├── skills/ ← Reusable workflow definitions
│ │ └── my-skill/SKILL.md
│ └── generated/ ← Auto-generated artifacts (gitignored)
│
│ ┌─── Generated by `agents sync` ───┐
├── .mcp.json │ Claude Code + Copilot CLI
├── .codex/config.toml │ Codex
├── .grok/config.toml │ Grok Build
├── .gemini/settings.json │ Gemini CLI
├── .cursor/mcp.json │ Cursor
├── .vscode/mcp.json │ Copilot VS Code
├── .amp/settings.json │ Amp
├── .factory/mcp.json │ Factory Droid
├── .kilo/kilo.jsonc │ Kilo
├── .devin/mcp_config.json │ Devin CLI
├── .zed/settings.json │ Zed
├── opencode.json │ OpenCode
├── .junie/mcp/mcp.json │ Junie
└── .claude/skills → .agents/skills │ Skill bridges
Git strategy. In the default
source-onlymode, only.agents/agents.json,.agents/skills/andAGENTS.mdare committed: everything the sync generates is gitignored and rebuilt from them. Incommit-generatedmode the generated files stay out of.gitignore, so a clone gets working tool configs without installing this CLI. That is how you commit.mcp.jsonfor the rest of the team.Either way, files that hold a tool's own settings (
.zed/settings.json,.amp/settings.json,.kilo/kilo.jsonc) and.github/mcp.jsonare never added to.gitignore: the sync merges its entries into them and leaves the rest of the file, including whether you track it, to you.
Command Overview
Setup & Sync
Diagnostics
MCP Servers
Profiles
Plugins
Skills & Integrations
Global Mode
Run any command with --global (or -g, or from $HOME) to manage MCP servers and skills machine-wide from ~/.agents/agents.json:
agents init -g
agents connect -g --llm opencode,codex,grok
agents sync -g
Tools that only have a user-level config (Claude Desktop, Devin Desktop, Goose) are written there in both modes.
Agent Plugins
Agent Plugins 1.0.0 is a vendor-neutral package format for skills and MCP servers, read by ChatGPT and Codex, Cursor, GitHub Copilot, Kiro and VS Code. A package is a directory with plugin.json, an mcp.json and a skills/ folder, which is close to what .agents/ already holds.
agents plugin export --name my-stack --plugin-version 1.0.0
dist/agent-plugin/
├── plugin.json $schema, name, version, description
├── mcp.json $schema, mcpServers
└── skills/ copied from .agents/skills
Export reads .agents/agents.json only, never local.json: what ships is the ${VAR} placeholder from the committed file, and the command prints which variables the package needs. ${PROJECT_ROOT} becomes the specification's ${PLUGIN_ROOT}.
Going the other way, agents plugin import ./some-plugin adds the package's servers under its plugin name (my-stack.docs) so nothing you already defined is replaced.
Context Budget
MCP servers cost context before an agent does any work: every tool definition is loaded up front.
agents mcp budget
MCP context budget:
everything 13 tools ~ 1916 tokens
filesystem 11 tools ~ 1240 tokens
broken error: spawn broken-server ENOENT
Servers 3
Tools 24
Estimated ~3156 tokens of context
The command speaks MCP 2026-07-28 directly over stdio and streamable HTTP, so the numbers come from the servers themselves. Servers built against the handshake revisions (2025-11-25 and earlier) are detected and handled the way the specification prescribes, so both eras work. Token counts are estimated from the size of the tool definitions, not measured by a model. Add --verbose for a per-tool breakdown, and --profile to measure what one profile would cost.
Servers whose config still contains an unresolved ${VAR} are skipped rather than started.
MCP Server Examples
# From a catalog URL
agents mcp add https://mcpservers.org/servers/context7-mcp
# stdio server
agents mcp add my-server --command npx --arg @my-org/mcp-server --arg /path/to/project
# HTTP server with a secret header
agents mcp add company-api --url "https://api.company.com/mcp" \
--secret-header "Authorization=Bearer YOUR_API_TOKEN"
# Only for specific tools
agents mcp add ide-server --command ide-mcp --target cursor --target zed
A server definition supports timeout, connectTimeout, tools, disabledTools, oauth, headersHelper, bearerTokenEnvVar and envFile. Each is written only for the tools that document it, and the sync says when a field is dropped for a target that does not support it.
Values support ${VAR} and ${VAR:-default}, plus ${PROJECT_ROOT}.
Security
- Secret-looking values are moved to
local.jsonand replaced with${PLACEHOLDER}inagents.jsonwhen a server is added. agents doctorwarns about literal secrets in committed config.- Env keys and header names are validated before they reach a config file or a shell.
agents plugin exportnever readslocal.json.- A config this CLI does not gitignore keeps the
${VAR}placeholder fromagents.json, whether the value would have come fromlocal.jsonor from your shell. Amp, Zed and Kilo share a file with the tool's own settings, and.github/mcp.jsonis a file teams review; the sync lists which variables to export so those tools can resolve them.commit-generatedmode holds secrets back from every generated config for the same reason. - A config this CLI rewrites keeps the permissions it had, so a file you restricted to
0600stays that way.
Team Workflow
Lead sets up the project:
agents start
agents mcp add https://mcpservers.org/servers/context7-mcp
git add .agents/agents.json .agents/skills/ AGENTS.md && git commit -m "Add agents config"
In source-only mode that is everything the team needs: each clone runs agents sync and
gets the tool configs locally. Switch syncMode to commit-generated if you would rather
commit .mcp.json and the rest for people who do not install the CLI.
New member onboards:
git clone <repo> && cd <repo>
agents start # keeps the committed config, writes local tool files
CI:
agents sync --check # exits 2 when a tool config drifted from .agents/
FAQ
Documentation
docs/agents-system.md— how sync, skills and generated files workdocs/EXAMPLES.md— project setupsCONTRIBUTING.md— development workflowCHANGELOG.md— release history