Work with a coding agent¶
A coding agent writes a correct ankka service when it has two things: the documentation of the ankka
version you are using, and a way to act on the platform and on the services running on your machine.
ankka ships both. The documentation comes as an Agent Skill, and the actions come as a Model Context
Protocol (MCP) server built into the CLI, ankka mcp.
The skills¶
An Agent Skill is a directory an agent loads when a task needs it: a SKILL.md saying what it is for and
the rules to hold, and reference files it opens on demand. ankka's documentation is rendered into
fourteen skills, one per kind of task, so an agent writing an entity loads the entity rules and not the
deployment guide:
| Skill | For |
|---|---|
ankka |
orientation: what ankka is, installing it, the first service, the SDK maps, limitations |
ankka-design |
decomposing a domain into components, where each rule lives, what may lag, service boundaries and the context map of a project of several services, and the component table that records each choice and the alternative it beat |
ankka-inspect |
checking a service running on this machine, or every service of a project, against its specification's acceptance scenarios, through its endpoints, its declared queries and its traces |
ankka-port |
porting an existing system: recording what the running original does, a specification that says how each requirement was established, and parity tests that hold the rebuild to the recordings |
ankka-entities |
event sourced and key value entities, serialization and evolution |
ankka-views-consumers |
views, consumers and broker topics |
ankka-workflows |
workflows, timers and timed actions |
ankka-agents |
agents, tools, sessions, guardrails, models, streaming, multi-agent orchestration |
ankka-endpoints |
HTTP endpoints, ACLs, errors, server-sent events |
ankka-python |
a service in Python beside the sidecar |
ankka-typescript |
a service in TypeScript on Node.js beside the sidecar |
ankka-rust |
a service in Rust, built to a WebAssembly module the runtime loads |
ankka-deploy |
the descriptor, the CLI, images, deploying, exposing, observing and troubleshooting |
ankka-platform |
installing and administering the platform itself |
Each skill's SKILL.md holds the rules an agent must hold for that task, and its references/ directory
holds the pages of this documentation the task needs. The samples in those pages are copied from code the
ankka build compiles and tests, so an agent that reads them writes current signatures and imports.
In a project made from the template, the skills are already there. ankka init and
sbt new thinkmorestupidless/ankka.g8 create .claude/skills/ in the new project, holding the
documentation of the ankka version the project was created with, and a .mcp.json that starts
the MCP server. Claude Code loads both with no configuration. Other agents that read Agent
Skills can be pointed at the skills directory.
In any other project, install the Claude Code plugin from the ankka marketplace:
/plugin marketplace add thinkmorestupidless/ankka-marketplace
/plugin install ankka@ankka
The plugin carries the same skills, and it registers ankka mcp as an MCP server, so the CLI must be on
your PATH for the tools to start. Install the tools covers building the CLI. The
marketplace is published from the ankka repository on every release, so the plugin's version is the
platform version whose documentation it holds.
Code review as a skill¶
The same marketplace carries pr-review, code review as skills, which needs nothing from ankka:
/plugin install pr-review@ankka. /pr-review 123 reviews a pull request, /pr-review feature/x a
branch, /pr-review main..HEAD a range and /pr-review --working-tree the uncommitted changes:
against a general checklist, then against the checklist of each language the change touches (Scala,
Java, Kotlin, Go, Python, Rust, TypeScript), reading the repository's own instructions and rule files
first, and it reports findings labelled by severity with a verdict. It posts nothing unless asked.
A repository shapes the review without forking the plugin, in three layers, each beating the one below and all of them beating the bundled checklists:
- Its instruction and rule files.
CLAUDE.md,AGENTS.mdand.claude/rules/*.mdare read before the code, and a rule they state overrules any item in the skills. - A
REVIEW.md. At the root, or in a directory for the changes under it, it is the repository's own checklist, applied beside the general one. An optional## pr-reviewsection says what of the plugin not to use, or what to use as well:
## pr-review
- skip: pr-review-typescript # the repository's own TypeScript rules stand
- skip: general/Commit and PR hygiene
- load: acme-review-rules # a project or personal skill, loaded as well
- A skill of its own. A project or personal skill named
pr-review-<language>replaces the bundled one for that language.
Repositories built with spec-kit can run the review as a hook at the end of /speckit-implement, in
the worktree and before anything is pushed; the plugin's README says how, and how to disable or
replace it.
The MCP server¶
ankka mcp is an MCP server over standard input and output. It offers three groups of tools, and the
documentation as resources.
| Group | Tools | Acts on |
|---|---|---|
| Control plane | whoami, list_organizations, list_projects, list_services, get_service, service_history, service_logs, apply_service, expose_service, unexpose_service, pause_service, resume_service, restart_service, delete_service |
deployed services, as the logged-in user |
| This machine | list_local_services, describe_local_service, local_traces, query_local_entity, call_local_endpoint, local_agent_session |
services running locally |
| Documentation | search_docs, read_doc, and every page as an ankka://docs/<path> resource |
this CLI's version of the docs |
Connect Claude to it¶
ankka mcp install configures a client to start the server, whichever way you work:
| You use | Run | What it changes |
|---|---|---|
Claude Code, in a project made by ankka init |
nothing | the project's .mcp.json already names the server |
| Claude Code, in every project | ankka mcp install |
Claude Code's own configuration, for you, through claude mcp add --scope user |
| Claude Code, in one existing project, for everyone who works on it | ankka mcp install --scope project |
a .mcp.json in the project, to commit |
| Claude Desktop | ankka mcp install --client desktop |
Claude Desktop's claude_desktop_config.json; quit and reopen Desktop afterwards |
Claude Code asks before starting a project's server. A .mcp.json is part of the repository, so
Claude Code asks each person once whether to trust it. ankka init leaves that question in place rather
than answering it for you: a repository that could start programs without asking could start any.
The project file names ankka; the others name a path. A .mcp.json is read on other machines, so
it names the command and relies on PATH. Claude Desktop is started from the Dock rather than a shell
and does not see your shell's PATH, so ankka mcp install writes the absolute path of the first
ankka on yours, and for the JVM build a JAVA_HOME, so the launcher finds Java without one either.
--command names a different ankka.
Nothing is overwritten. Every write keeps the other servers and settings in the file, and an
existing server named ankka is left as it is and shown to you; --force replaces it. --dry-run
prints what would change and changes nothing. When the claude command is not on PATH,
ankka mcp install changes nothing and prints the command to run, or the plugin to install instead.
Any other MCP client starts the server the same way. A client that takes a JSON configuration names the command and its argument:
{
"mcpServers": {
"ankka": { "command": "ankka", "args": ["mcp"] }
}
}
Started by hand at a terminal, ankka mcp prints a line on standard error saying it is waiting for a
client, and then waits: its standard output carries protocol messages and nothing else. Press Ctrl-D to
stop it. An MCP client starts it over pipes, and then it prints nothing but the protocol.
ankka mcp takes the same --url, --token and --project options as every other command, and reads
the same environment variables and saved settings. It resolves them on every tool call rather than once
at start, so an ankka login or ankka config set project in another terminal takes effect on the next
call without restarting the client.
What the tools can do¶
The control plane tools do what the matching commands do, as you. Each is one call to the control
plane with your saved login, and the control plane authorizes it exactly as it authorizes the command
line. An agent cannot do anything through ankka mcp that you could not type. apply_service checks a
descriptor with the platform's own validation before anything is sent, so a malformed descriptor comes
back to the agent as a readable error.
Tenancy administration is not offered. Creating and deleting organizations and projects, inviting and removing members, and disabling organizations stay on the command line. They are rare, they are a person's decision, and a tool that exists is a tool a model may choose.
Every tool says how far it reaches. Tools carry the protocol's annotations: read-only tools change
nothing, destructive ones may remove or replace something, and idempotent ones do nothing more the second
time. MCP clients use these to decide what to confirm with you before running. delete_service,
pause_service, unexpose_service, apply_service and call_local_endpoint are marked destructive.
The local tools see what the local console sees. call_local_endpoint sends an ordinary HTTP
request to the service's own port, so the endpoint's ACL applies to it exactly as it does to curl.
query_local_entity runs only the queries a component declared; a command is refused by the service.
The local console describes the same data for a person.
The server says when a newer release exists. The documentation tools serve the pages of the
command line's own release. When a newer release has been published, the server's instructions end with
the line the command line gives, whoami and installation_status carry a release field naming the
command line's release, the latest and that line, and search_docs and read_doc begin with a note
saying the pages are an older release's. installation_status also says when the installation runs a
newer release than the command line. The server reads the latest release when it starts, waiting up to
two seconds before its first answer, and again each day it runs; CI and ANKKA_NO_UPDATE_CHECK=1
turn this off, as they do for the command line.
The development loop, for an agent¶
With the skill and the server, an agent can take a change from code to a running, observed service:
- Decide the components and write them down as a table, one row per requirement, naming the close
alternative each choice beat (the
ankka-designskill). - Read the page for the component it is writing, with
read_docor from the skill. - Write the code and its unit test, and run
sbt testoruv run pytest. - Run the service locally, then check it against the specification (the
ankka-inspectskill):describe_local_serviceto compare what it registered with the table,call_local_endpointfor each acceptance scenario,query_local_entityfor the state each one left, andlocal_tracesto see which components each request went through. - Build the image and
apply_servicea descriptor, then pollget_serviceuntil the service isReady, and readservice_logsif it is not.
Documentation for other tools¶
The documentation site publishes the same pages for any tool that reads the web:
| Address | Holds |
|---|---|
https://docs.ankka.cloud/llms.txt |
every page's title, link and one-sentence description, by section |
https://docs.ankka.cloud/llms-full.txt |
every page in one file |
https://docs.ankka.cloud/<page>.md |
one page as Markdown, beside its HTML |
https://docs.ankka.cloud/docs-index.json |
every page's metadata and headings |
The site describes the latest release. The skill in a project and the pages inside the CLI describe the version they were built with, which is the better source while you work on a service pinned to an older version.