Set up agents
Three pieces give a coding agent everything it needs: the skills, the MCP server and the AGENTS.md section. They reinforce each other, and axx init sets up all three for the agents the repository already uses. Test with an agent shows them in use.
What axx init sets up
Section titled “What axx init sets up”axx init works in the repository only and lists every file it writes. It never writes to your home directory.
| When the repository has | axx init writes |
|---|---|
| anything | the AGENTS.md section and the skills in .agents/skills/ |
.claude/, CLAUDE.md or .mcp.json (Claude Code) |
.mcp.json, links the skills into .claude/skills/, and imports AGENTS.md into CLAUDE.md where Claude Code reads that instead (AGENTS.md) |
.codex/ (Codex) |
.codex/config.toml |
.cursor/ (Cursor) |
.cursor/mcp.json |
.vscode/ (VS Code) |
.vscode/mcp.json |
.gemini/ or GEMINI.md (Gemini CLI) |
.gemini/settings.json |
In a repository with a CLAUDE.md and a .cursor/ directory:
create axx.yaml create axx-packs.yaml create features/smoke/smoke.feature create .github/workflows/acceptance.yml create AGENTS.md update CLAUDE.md (imports AGENTS.md for Claude Code) create .gitignore create .agents/skills (5 skills) create .claude/skills (linked for Claude Code) create .mcp.json (the axx MCP server for Claude Code) create .cursor/mcp.json (the axx MCP server for Cursor)
packs this repository points to, not added (`axx pack show <name>` says what one does): kafka README.md mentions Kafka; infra/compose.yaml runs a Kafka image sql README.md mentions PostgreSQL; infra/compose.yaml runs a database image add those it tests with `axx pack add kafka sql`
Codex keeps its MCP servers in ~/.codex/config.toml; `axx mcp install --agent codex --scope user` adds axx there.next: put your service's command, port and health check in axx.yaml and the smoke feature, then `axx doctor` and `axx run`Axx adds its server to the files that exist: other servers and settings stay where they are, and a file that has the axx server already is left alone, so running axx init again changes nothing. A file Axx cannot read back exactly, such as JSON with comments, is left alone too: its line says so, and axx mcp install --agent <agent> shows what to add by hand. Codex usually reads its servers from your home directory, which axx init never writes, so it prints the command that does. axx init --no-agents skips the skills and the MCP servers.
axx init also lists the packs the repository points to: the images in its compose files, the clients in its dependency manifests, its schema files (Avro, protobuf, AsyncAPI, GraphQL), and what its README and docs name. It says why for each and adds none of them: you or your agent add the ones the tests need.
Commit what axx init wrote, so every contributor and every CI agent gets it. The skills are the exception: axx generates them, so .gitignore keeps them out, and each person or agent installs their own with axx skills install.
Skills
Section titled “Skills”axx skills install # this repositoryaxx skills install --scope user # your home directory, for every repositoryaxx skills update # where they are installed, to this axx'saxx skills listinstall writes the skills to .agents/skills/ (read by Codex, Cursor, Gemini CLI and Copilot) and, when the repository uses Claude Code (a .claude/ directory, CLAUDE.md or .mcp.json), links them into .claude/skills/ for it. --claude links them anyway, and --no-claude never; with --scope user, they are linked when your home directory has .claude/. A .claude/ that holds nothing but these links does not count as using Claude Code, so axx doctor does not ask a Codex repository for a Claude Code MCP server. axx init installs them the same way.
In a project, install also adds the skills to .gitignore: .agents/skills/axx-*, its lock file and .claude/skills/axx-*, so that skills of your own in those directories stay in the repository. A fresh clone has none until someone runs axx skills install; the AGENTS.md section tells agents so, and axx doctor warns. A repository that already holds them keeps them, as .gitignore does not govern tracked files: install says so and gives the git rm --cached command that takes them out, leaving the files in place, after which the next install ignores them.
| Skill | Teaches |
|---|---|
axx-acceptance-tests |
the shape of a feature, what the steps’ tables take, waiting, and a suite laid out by feature |
axx-test-data |
seeds, payloads and mock bodies in fixture factories: axx fixtures, identities, adoption, axx lint, CI |
axx-setup |
axx init, services and readiness, CI, agent integration |
axx-custom-steps |
custom steps as Go packs |
axx-debugging |
reading failures, exit codes and logs |
The AGENTS.md section holds the workflow and the rules, and the skills add what it leaves out. They carry no pages of steps: axx steps lists your project’s steps, your custom packs’ included, a line each, and axx steps show <id>... gives the documentation of those whose line leaves an agent unsure, several at once. Agents read pages a chunk at a time, about ten times the tokens. They carry no pages of error codes either: axx explain <code> gives each one. axx upgrade updates them where they are installed, and axx skills update does after any other upgrade; axx doctor warns when they come from another version. Files you edited are kept unless you pass --force, and files the skills no longer have are removed. The same skills are published at /.well-known/agent-skills/index.json.
MCP server
Section titled “MCP server”axx mcp serves Axx over the Model Context Protocol on stdio. Because it is the installed binary, its answers match your Axx version and your project’s steps. When an agent connects, the server gives it the workflow and the rules of the AGENTS.md section.
| Tool | Does |
|---|---|
steps_search |
without a query, the catalog: every step of the project, one line each; with one, the steps that fit it (id, expression, table columns and an example; 6 by default), a step it returned before as its id only, and the steps of Axx’s other packs that fit it better, with the pack to add; with pack, one pack’s steps, added or not |
step_explain |
with a line, how it matches (or the closest steps: first the line written out when it keeps an expression’s notation, or with its ordinal moved where the step has it; for a step of a pack the project lacks, that pack); with an id or several, the steps’ documentation and examples, for packs the project lacks too |
feature_validate |
check feature files or feature text without running them or the services; warnings come from axx lint’s feature checks (a scenario that checks several behaviors in turn among them), and hints name scenarios whose checks prove little |
lint_run |
run axx lint: values such as seed ids that collide across files, with file:line, and the rules that found something |
scenarios_run |
run scenarios (paths, tags, names), starting the services and stopping them unless they are up; returns failures with expected and actual, the warnings feature_validate and lint_run would give, and for a passing run their hints |
failure_context |
logs, attachments and the last request and response of one failure; without a run ID, of the latest run |
env |
the services: up keeps them running to inspect them, down stops them and cleans up, and status says which are running, left over from a killed run, or not cleaned up (axx env on the command line) |
config_show |
the effective axx.yaml, with secrets redacted, and its packs (axx config show) |
scaffold |
starter contents for a feature or an axx.yaml |
steps_try |
try steps in a live scenario that stays open between calls, until restart |
To check what it wrote, an agent calls feature_validate, lint_run and scenarios_run, in one turn. The first two need no services, and scenarios_run starts the services and stops them.
Packs add tools of their own, which look at the scenario steps_try keeps open. The web-core pack’s:
| Tool | Does |
|---|---|
web_page |
the page the session’s web app is on: its elements as steps name them, what a screen reader reads, script errors and a screenshot |
An agent tries the steps it is unsure of, looks at the page they led to, then writes them into the feature:
{"steps": "Given the portal web app with the following properties:\n | url | http://localhost:8400/portal |\nWhen the \"/quote\" page is opened"}The scenario’s services must be running: env up keeps them running while an agent tries steps. With an axx host serving the project, steps_try gets services of its own. The session’s browsers close when the agent restarts it or the server stops.
It also serves the axx.yaml JSON Schema as a resource and a write-acceptance-tests prompt. Pass --profile ci (or any profile) to apply it to every tool call. A server has the packs the project listed when it started: after axx pack add, restart it, as its error says.
Connect an agent
Section titled “Connect an agent”axx mcp install --agent <agent> adds the server to one agent’s configuration: in the repository by default, or with --scope user in your home directory, which only this command writes, and only when you ask. Like axx init, it keeps what the file holds and leaves a file that has axx alone. --dry-run shows what it would write.
axx mcp install --agent cursor # .cursor/mcp.jsonaxx mcp install --agent codex --scope user # ~/.codex/config.toml--agent |
--scope project (the default) |
--scope user |
|---|---|---|
claude (Claude Code) |
.mcp.json |
prints claude mcp add --scope user axx -- axx mcp |
codex (Codex) |
.codex/config.toml |
~/.codex/config.toml ($CODEX_HOME/config.toml when set) |
cursor (Cursor) |
.cursor/mcp.json |
~/.cursor/mcp.json |
vscode (VS Code, GitHub Copilot) |
.vscode/mcp.json |
prints code --add-mcp '{"name":"axx","command":"axx","args":["mcp"]}' |
gemini (Gemini CLI) |
.gemini/settings.json |
~/.gemini/settings.json |
Claude Code keeps your own servers with the rest of its state, and VS Code in its profile, so for them Axx prints the agent’s own command instead of editing those files. Codex loads a project’s .codex/config.toml only once you trust the project.
This is what each agent’s file gets.
Claude Code
Section titled “Claude Code”{ "mcpServers": { "axx": { "command": "axx", "args": ["mcp"] } }}Claude Code asks before it starts a server from a project’s .mcp.json. Or install the skills and the server together as a plugin:
/plugin marketplace add nimbusxr/axx/plugin install axx@nimbusxr[mcp_servers.axx]command = "axx"args = ["mcp"]Cursor
Section titled “Cursor”{ "mcpServers": { "axx": { "command": "axx", "args": ["mcp"] } }}VS Code (GitHub Copilot)
Section titled “VS Code (GitHub Copilot)”{ "servers": { "axx": { "type": "stdio", "command": "axx", "args": ["mcp"] } }}Gemini CLI
Section titled “Gemini CLI”{ "mcpServers": { "axx": { "command": "axx", "args": ["mcp"] } }}Check the setup
Section titled “Check the setup”axx doctor checks, for the agents the repository uses (and Codex, when your machine has it), that the skills are installed and that the agent finds the axx MCP server, in the repository’s file, your own, or (Claude Code) the plugin. What is missing is a warning with the command that fixes it:
ok agent skills 5 skillsok Claude Code skills 5 skillsok Claude Code MCP axx server in .mcp.jsonwarn Cursor MCP no axx server in .cursor/mcp.json → `axx mcp install --agent cursor` adds itAgents in a sandbox without Docker
Section titled “Agents in a sandbox without Docker”Some harnesses run the agent in a sandbox that may not use Docker, so its runs cannot start the services. Start axx host in the project on your own machine: the agent’s runs, axx up and MCP sessions get their services from it, clean for each run, and it starts only what you approved. Run tests from an agent’s sandbox shows how.
AGENTS.md
Section titled “AGENTS.md”axx init adds a managed section to AGENTS.md, the file most agents read first. Running axx init again updates the section in place and leaves the rest of the file alone:
<!-- axx:begin (managed by `axx init`; edit outside this block) -->## Acceptance tests (axx)axx (github.com/nimbusxr/axx, "axxeptance") runs acceptance criteria, written as Gherkin scenarios, black-box against therunning services. It answers for itself, offline and for the version installed: no need for its website or source.
1. Look at the project first: its README and docs, `axx.yaml` (the services), `axx-packs.yaml` (the packs), `features/`.2. Find the steps: read the list of every step of the project's packs once. A step's line is usually enough to write it: look up the documentation only of those that leave you unsure (what a table's rows hold, say), all in one call. With the axx MCP tools: `steps_search` without a query, then `step_explain` with ids (`steps_try` tries steps in a live scenario). Without them: `axx steps`, then `axx steps show <id>...`. A step the project's packs lack: `axx steps search <words>` finds it in axx's other packs and names the pack (`axx pack add <name>`).3. Write one scenario per acceptance criterion with those steps, written out: each {name} replaced with a value, a(n) as "a" or "an", [[...]] kept without the brackets or left out. Never invent step text.4. Check, and fix what is reported, in one command: `axx validate && axx lint && axx run --compact`. Validate (the features) and lint (the test-data rules) need no services; their errors stop it, their warnings do not. The run starts the services and stops them. With the MCP tools, in one turn: `feature_validate`, `lint_run`, `scenarios_run`; `failure_context` explains a failure. An error's code: `axx explain AXX-E…`. `axx up` and `axx down` only keep the services running to inspect them.
Rules axx checks, and agents get wrong:- A scenario is one behavior: Given the state it starts from (a request it needs done first is executed in a Given), one When for what someone does, Then what is true afterwards. A request that checks the outcome (a lookup that finds nothing stored) is added with the others and executed in the When. A When after a Then is another scenario. Each acceptance criterion is a scenario of its own, even when one action shows several.- Ordinals count in the order a scenario adds requests, responses and selections: the 2nd is its second; none, the 1st.- Every scenario uses data of its own (ids, names, keys): scenarios run in parallel and data persists between runs.- A value means what it says in every table: `53111` a number, `"53111"` the string, `null`, `undefined` (no such property). Checks are strict; an empty cell, `01067` or a number where only text fits (a header) is an error saying what to write.- Check what the service did (a response property, a row, an event) and why it refused, not only status codes.- Feature files read as acceptance criteria, in plain language: no programming constructs, no variables.- `services:` in axx.yaml are what runs on its own, reached by an address; a program its user starts (a CLI, an MCP server over stdio) is run by its step's `command`. `axx schema --outline` lists axx.yaml's keys.- Payloads, seeds or mock bodies that repeat: fixture factories generate them (`axx fixtures`; optional, recommended where data repeats); `axx fixtures adopt` turns hand-written ones into one.
If `.agents/skills` has the axx skills, they add what this leaves out: axx-acceptance-tests (feature shape, payloadtables), axx-test-data (fixture factories), axx-debugging (failures), axx-setup, axx-custom-steps. `axx skills install`installs or updates them.<!-- axx:end -->Claude Code reads AGENTS.md only where no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md is in the folder or one above it; where one is, it reads those instead. So in a repository that uses Claude Code, axx init adds @AGENTS.md, Claude Code’s import, to the project’s CLAUDE.md (or to .claude/CLAUDE.md, or to a new CLAUDE.md when the one Claude Code reads is your own CLAUDE.local.md or a folder above), and Claude Code reads the section with it. A CLAUDE.md that imports AGENTS.md already, or links to it, is left alone.
Docs for agents
Section titled “Docs for agents”Agents need neither this site nor axx’s source: axx answers for itself, offline and for the version installed. axx pack list and axx pack show <name> cover every pack axx publishes, added to the project or not; axx steps search <words> finds steps in all of them, with the pack to add; axx steps show <id>... documents steps of any of them, several at once; a step from a pack the project lacks names that pack when axx validate or axx run reads it; and axx explain <code> explains an error code. The MCP server’s steps_search and step_explain do the same. For agents that read the site anyway:
- Every page on this site has a Markdown twin: append
.mdto the path (/guides/set-up-agents.md). Pages advertise it with<link rel="alternate" type="text/markdown">. /llms.txtindexes the site;/llms-full.txtand/llms-small.txtcontain it in one file.- The
axx.yamlschema is at/schemas/v0/axx.schema.json;axx schemaprints the same thing offline, andaxx schema --outlinelists its keys, a line each, at a fraction of its size. - Agents that browse the site in a browser with WebMCP get its tools there:
axx_packs,axx_pack,axx_find_steps,axx_search_docsandaxx_read_page.