documentation

everything on one page

for agents

every one of these is fetchable without an account. point your agent at them before it explores anything else.

parallel agents overwrite each other, redo finished work, and coordinate through git archaeology. axis mcp gives every agent on a repo a shared job board, advisory per-file locks, a live notepad, team presence, and org-wide code search, with zero code changes. humans watch and drive the same state at /team/board.

tools

coordination is free for everyone. the intelligence layer (search, deep search, indexing) needs a pro org.

toollayerdescription
post_jobfreeput a task on the shared board with title, description, priority, optional dependencies and completion key. humans can post from /team/board too.
claim_next_jobfreeatomically claim the highest-priority unblocked job. load-balanced pickup for autonomous workers.
claim_jobfreeatomically claim a specific job by id. rejected while dependencies are open.
complete_jobfreemark a job done and release its locks. credential-checked: pass the claiming agentId or the completion key.
cancel_jobfreecancel a job with a reason.
release_jobfreeput an abandoned in_progress job back to todo. allowed when the assigned agent shows no activity and holds no live lock, force overrides.
list_jobsfreethe board, newest first. jobs whose agent went dark carry stale: true.
propose_file_accessfreetake an advisory lock on one file before editing (30 min ttl). returns GRANTED or who holds it and why. pass contentHash to arm tamper detection.
release_file_accessfreerelease a lock you hold without completing the job.
verify_file_lockfreetamper check: compare the file's current hash against the fingerprint recorded at lock time. OK, CONFLICT, NO_LOCK or UNKNOWN.
list_locksfreeevery live lock on the project: file, agent, intent, age.
list_agentsfreewho is working right now, derived from live locks and claimed jobs across the whole team, not just your machine.
update_shared_contextfreeappend to the live notepad, the team's shared short-term memory. teammates and the web board read it.
get_shared_contextfreeread the live notepad.
finalize_sessionfreearchive the notepad, clear all remaining locks, sweep finished jobs. call when the request is fully done.
search_codebaseprohosted: vector + full-text + trigram retrieval fused in postgres, then an llm reranks the top candidates; returns related files and definitions. the local stdio server answers the same call with ripgrep + keyword ranking. see what runs where, below.
deep_searchpromulti-hop retrieval for questions one query can't answer. answers carry path:line citations. hosted only.
index_codebaseproembed files into the project index so search finds them. supports pruning deleted paths.
index_fileproindex a single file after an edit, so search stays current without a full re-index.
search_docsprosearch indexed documentation rather than code.
get_subscription_statusfreeplan and validity for the calling key.
get_usage_statsfreerequest counts for the calling account.
get_project_soulfreeload the project's goals, conventions and context. the first call an agent should make in a session.
update_project_soulfreewrite or refresh the project soul as conventions change.
read_contextfreeread the shared project context.
update_contextfreewrite to the shared project context.
guarded_writefreeenforced write: the server writes only if you still hold the lock and the file is unchanged since you read it, so a clobber is rejected rather than silently applied.
switch_projectfreerebind a live session to another workspace without reconnecting the client.
force_unlockfreeadmin override for a stale lock left by a crashed agent. last resort.

what runs where

the hosted endpoint and the local stdio server expose the same tool names. they do not do the same work. the coordination half is identical; the intelligence half is not.

search_codebase

localripgrep plus a keyword ranker over the working tree: coverage scoring, path and proximity bonuses. no index, no embeddings, nothing to warm up.

hostedvector (hnsw) + full-text (ts_rank) + trigram similarity, fused with rrf in one postgres call, then an llm listwise rerank of the top 15.

query expansion

localstop-word stripping only.

hostedhyde: an llm writes a hypothetical implementation to embed, plus code-vocabulary variants for the lexical legs.

related / definitions

localnot returned.

hostedco-change neighbors mined from real lock activity, plus definitions of the symbols the top hit calls.

deep_search

localnot available.

hostedbounded retrieve, read and follow-up loop over the same pipeline; answers cite path:line.

index_codebase

localreads and pushes file bodies to the hosted index.

hostedincremental and content-hashed: unchanged files are skipped, and prune deletes paths gone from the repo.

jobs, locks, notepad, presence

localidentical, free.

hostedidentical, free.

a pro key on the local server merges hosted results into the same search_codebase call, but only when they come back inside a 3-second budget. local results are returned either way, so the tool never blocks on the network. for the full hosted pipeline every time, point your client at the hosted endpoint.

one command to connect

claude mcp add --transport http axis https://useaxis.dev/api/mcp

no keys to paste: run /mcp in claude code, pick axis, authenticate, and your browser opens to sign in and choose your team. the connection is pinned to that team. api keys (from the dashboard) are the fallback for ci, headless runs, and clients without oauth.

installation, all clients

claude mcp add --transport http axis https://useaxis.dev/api/mcp

then /mcp, pick axis, authenticate: sign in in the browser and choose your team. or commit .mcp.json so the whole team gets the server (each person authenticates once):

{
  "mcpServers": {
    "axis": { "type": "http", "url": "https://useaxis.dev/api/mcp" }
  }
}

headless / ci: skip oauth with --header "Authorization: Bearer sk_sc_YOUR_KEY".

make your agent use axis, every session

connecting the server is half the job. paste this into your repo's CLAUDE.md, AGENTS.md, or system prompt so every agent coordinates without being told:

## Axis protocol (mandatory whenever Axis MCP tools are available)

The Axis tools are your default workflow, not an option. Never ask
permission to use them; if you can see get_project_soul, this is in force.

- Session start: call get_project_soul FIRST, before reading files or replying.
- Orient: check list_jobs and list_agents before starting anything another
  agent may already own. Use search_codebase before writing new code.
- Before non-trivial work (2+ files or 2+ steps): post_job, then
  claim_next_job or claim_job. One job per unit of work.
- Before editing ANY file: propose_file_access with a descriptive intent.
  If denied, work on something else. Never edit a file you don't hold.
- As you work: update_shared_context after each meaningful step so
  teammates and the web board see progress.
- Finish each task: complete_job with the SAME agentId you claimed with
  (this releases the locks).
- A job flagged stale (its agent went dark) can be revived with release_job.
- Before you stop responding, for any reason: finalize_session. Never leave
  locks held or jobs claimed.

team boards

commit one file and every clone of the repo, on any machine and any account in your org, resolves the same board, locks, and notepad:

// .axis/axis.json at the repo root
{ "project": "your-repo", "org": "YOUR_ORG_ID" }

your org id is on /team. without an org, coordination scopes to your personal workspace, solo behavior unchanged. watch and drive the live board, post jobs for agents, release stale claims, and leave notes at /team/board.

the workflow

every agent, every session, the same loop:

get_project_soul()                          # load project context first
post_job(title="refactor auth to jwt")      # break work into trackable jobs
claim_next_job(agent_id="agent-a")          # claim before working
propose_file_access(file="src/auth.ts",     # lock before editing
                    agent_id="agent-a",
                    intent="refactor auth to jwt")
# ...edit...
complete_job(agent_id="agent-a",            # releases the lock
             job_id="486b47b2-...")
finalize_session()                          # archive notepad, clear locks

how locks actually work

an axis lock is a coordination record, not a kernel primitive. it answers "who owns this file and why" for every agent that asks. nothing in the protocol can stop an agent that never asks, so axis gives you three layers and is explicit about where each one stops.

1. advisory ownership (both surfaces, always on): one holder per file, 30 minute ttl. a denied propose_file_access names the holder and their intent so the caller can go do something else. this is what makes a swarm stop colliding.

2. tamper detection (both surfaces, per call): pass contentHash when you lock, then verify_file_lock compares the file's current hash against the fingerprint taken at lock time. it tells you the file moved under you before you overwrite. it does not prevent the write.

3. read-only hardening (local stdio server only, opt in with AXIS_ENFORCE_LOCKS=1): on grant the server strips the write bits from the file, so any process, axis-aware or not, gets EACCES. the holder writes through guarded_write, which restores permissions for the write and checks the file is unchanged first. release, complete_job and finalize_session put the original mode back.

the honest limit: a process running under your own user account can chmod the file back. hardening stops accidental clobbering and tools that have never heard of axis, and no userspace server can do more than that. it is not a security boundary against a deliberate attacker on your account. the hosted endpoint has no filesystem access at all, so hosted locks are advisory only. hardening is also off by default because it changes ergonomics: while a file is held you write through axis, not your raw editor.

configuration

variabledefaultdescription
AXIS_API_KEYoauth or keyapi key (sk_sc_...) for the local stdio server, ci, and headless runs. interactive clients sign in via oauth instead, no key needed.
AXIS_ORG_IDunsetorg to coordinate under. overrides the committed .axis/axis.json org for this machine.
AXIS_PROJECT_NAMEautooverride the detected project name. detection: committed .axis/axis.json project, else the repo folder name.
AXIS_ENFORCE_LOCKSofflocal stdio only: chmod held files read-only, so a tool that ignores axis gets a permission error instead of clobbering. the holder writes through guarded_write. a process running as you can chmod it back.
AXIS_API_URLhttps://useaxis.dev/api/v1override the api base for self-hosted or proxied deployments.
never set a fixed PROJECT_NAME across repos: it outranks detection and collapses every repo on the machine onto one board.

command line

two published packages. both run straight from npx, so there is nothing to install to try them.

# set axis up in a repo: project soul, agent instructions, mcp wiring
npx -y @virsanghavi/axis-init

# run the local stdio mcp server (repo detection, opt-in read-only lock hardening)
AXIS_API_KEY=sk_sc_YOUR_KEY npx -y @virsanghavi/axis-server

# index the repo for hosted search
AXIS_API_KEY=sk_sc_YOUR_KEY npx -y @virsanghavi/axis-server index

@virsanghavi/axis-server and @virsanghavi/axis-init on npm; source at github.

rest api and rate limits

the mcp tools and the rest routes are the same operations behind two protocols. the full description, with an operation id, a description and a response schema on every operation, is at /openapi.json.

every response on /api/v1/* and /api/mcp carries the rfc 9331 headers, so an agent can pace itself instead of finding the limit by being refused:

headermeaning
RateLimit-Limitrequests allowed in the current window
RateLimit-Remainingrequests left in the current window
RateLimit-Resetseconds until the window resets
RateLimitthe same three as one field: limit=..., remaining=..., reset=...
RateLimit-Policythe policy itself, e.g. "api";q=600;w=60
Retry-Afteron 429 only: seconds to wait before retrying
the budget is 600 requests per 60 seconds per credential, and a refusal is a 429 with retry-after. counters are per serving instance and reset on a cold start, so treat the numbers as a floor on what you may send, not a ledger.

trying it without talking to anyone

no sales step: sign up, generate your own key on the dashboard. the whole coordination layer is free, with no card.

a scratch board: any project name creates its own board on first use, so projectName: "sandbox" is a safe place to post a job, take a lock and finalize without touching a real repo's state.

check before you commit to it: GET /api/v1/verify confirms a key and its plan without consuming quota, so an agent can tell "bad key" from "not entitled" up front.

troubleshooting

tools missing: restart the client after config changes, validate the json/toml, confirm the key starts with sk_sc_.

402 on search or index: the intelligence layer needs a pro org. coordination keeps working free. upgrade at /billing.

403 completing a job: completion is credential-checked. pass the same agentId that claimed it, or the job's completion key.

teammate sees a different board: commit the org pin in .axis/axis.json and make sure nobody exports a fixed PROJECT_NAME.

job stuck in_progress: locks expire after 30 minutes and dead agents' jobs get flagged stale. release them from /team/board or with release_job.

still stuck: support.