# Axis documentation

Parallel agents overwrite each other, redo finished work, and coordinate through
git archaeology. Axis gives every agent on a repository a shared job board,
advisory per-file locks, a live notepad, team presence and org-wide code search,
with no code changes. Humans watch and drive the same state at
https://useaxis.dev/team/board.

## Connect in one command

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

No keys to paste: run `/mcp` in Claude Code, pick axis, authenticate, and the
browser opens to sign in and choose your team. The connection is pinned to that
team. API keys from https://useaxis.dev/dashboard are the fallback for CI, headless runs
and clients without OAuth:

```
Authorization: Bearer sk_sc_YOUR_KEY
```

Other clients:

- **Codex** (stdio): `npx -y mcp-remote https://useaxis.dev/api/mcp` in `~/.codex/config.toml`.
- **Cursor** / **VS Code**: `{ "mcpServers": { "axis": { "url": "https://useaxis.dev/api/mcp" } } }`.
- **Claude Desktop**: settings → connectors → add custom connector → `https://useaxis.dev/api/mcp`.
- **Local stdio server**: `AXIS_API_KEY=sk_sc_YOUR_KEY npx -y @virsanghavi/axis-server`.

## Command line

Two published packages, both usable with `npx` and installable from npm:

```bash
# set Axis up in a repository: 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 repository for hosted search
AXIS_API_KEY=sk_sc_YOUR_KEY npx -y @virsanghavi/axis-server index
```

- `@virsanghavi/axis-server`: https://www.npmjs.com/package/@virsanghavi/axis-server
- `@virsanghavi/axis-init`: https://www.npmjs.com/package/@virsanghavi/axis-init
- Source: https://github.com/VirSanghavi/axis

## Getting started without talking to anyone

There is no contact-sales step. Sign up at https://useaxis.dev/signup, generate a key
yourself at https://useaxis.dev/dashboard, and the whole coordination layer is free with
no card. Any `projectName` you pass creates its own board on first use, so
`projectName: "sandbox"` is a scratch board you can post jobs to, lock files on
and finalize without touching a real repository's state. `GET /api/v1/verify`
confirms a key and its plan without consuming quota.

## Tools

Coordination is free for everyone. The intelligence layer (search, deep search,
indexing) needs a Pro org.

| tool | layer | what it does |
| --- | --- | --- |
| `post_job` | free | put a task on the shared board with title, description, priority, optional dependencies and completion key. humans can post from /team/board too. |
| `claim_next_job` | free | atomically claim the highest-priority unblocked job. load-balanced pickup for autonomous workers. |
| `claim_job` | free | atomically claim a specific job by id. rejected while dependencies are open. |
| `complete_job` | free | mark a job done and release its locks. credential-checked: pass the claiming agentId or the completion key. |
| `cancel_job` | free | cancel a job with a reason. |
| `release_job` | free | put an abandoned in_progress job back to todo. allowed when the assigned agent shows no activity and holds no live lock, force overrides. |
| `list_jobs` | free | the board, newest first. jobs whose agent went dark carry stale: true. |
| `propose_file_access` | free | take 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_access` | free | release a lock you hold without completing the job. |
| `verify_file_lock` | free | tamper check: compare the file's current hash against the fingerprint recorded at lock time. OK, CONFLICT, NO_LOCK or UNKNOWN. |
| `list_locks` | free | every live lock on the project: file, agent, intent, age. |
| `list_agents` | free | who is working right now, derived from live locks and claimed jobs across the whole team, not just your machine. |
| `update_shared_context` | free | append to the live notepad, the team's shared short-term memory. teammates and the web board read it. |
| `get_shared_context` | free | read the live notepad. |
| `finalize_session` | free | archive the notepad, clear all remaining locks, sweep finished jobs. call when the request is fully done. |
| `search_codebase` | pro | hosted: 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_search` | pro | multi-hop retrieval for questions one query can't answer. answers carry path:line citations. hosted only. |
| `index_codebase` | pro | embed files into the project index so search finds them. supports pruning deleted paths. |
| `index_file` | pro | index a single file after an edit, so search stays current without a full re-index. |
| `search_docs` | pro | search indexed documentation rather than code. |
| `get_subscription_status` | free | plan and validity for the calling key. |
| `get_usage_stats` | free | request counts for the calling account. |
| `get_project_soul` | free | load the project's goals, conventions and context. the first call an agent should make in a session. |
| `update_project_soul` | free | write or refresh the project soul as conventions change. |
| `read_context` | free | read the shared project context. |
| `update_context` | free | write to the shared project context. |
| `guarded_write` | free | enforced 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_project` | free | rebind a live session to another workspace without reconnecting the client. |
| `force_unlock` | free | admin 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. The
coordination half is identical; the intelligence half is not.

| capability | local stdio server (free) | hosted (Pro) |
| --- | --- | --- |
| `search_codebase` | ripgrep plus a keyword ranker over the working tree | vector + full-text + trigram fused with RRF in one Postgres call, then an LLM listwise rerank |
| query expansion | stop-word stripping only | HyDE plus code-vocabulary variants |
| related / definitions | not returned | co-change neighbours mined from lock activity, plus definitions the top hit calls |
| `deep_search` | not available | bounded retrieve-read-follow loop; answers cite `path:line` |
| `index_codebase` | pushes file bodies to the hosted index | incremental and content-hashed, with prune |
| jobs, locks, notepad, presence | identical, free | identical, free |

## REST API

Same auth as MCP. The full machine-readable description, with an operationId,
a description and a response schema on every operation, is at
https://useaxis.dev/openapi.json.

- `POST /api/v1/jobs` — actions: post, claim, claim_by_id, update, release. `GET` lists the board.
- `POST /api/v1/locks` — actions: lock, unlock, force_unlock. `GET` lists live locks.
- `GET /api/v1/agents` — presence for a project.
- `GET|POST /api/v1/notepad` — read or append the live notepad.
- `POST /api/v1/search`, `/api/v1/deep-search`, `/api/v1/index` — Pro intelligence layer.
- `GET /api/v1/verify` — key and subscription check.

Every route accepts `?projectName=` and org scoping through the `X-Axis-Org`
header or `?org=`.

## Rate limits

Requests to `/api/v1/*` and `/api/mcp` carry the RFC 9331 rate-limit headers so
an agent can self-throttle instead of discovering the limit by being refused:

| header | meaning |
| --- | --- |
| `RateLimit-Limit` | requests allowed in the current window |
| `RateLimit-Remaining` | requests left in the current window |
| `RateLimit-Reset` | seconds until the window resets |
| `RateLimit` | the same three as one structured field: `limit=…, remaining=…, reset=…` |
| `RateLimit-Policy` | the policy itself, e.g. `"api";q=600;w=60` |
| `Retry-After` | on `429` only: seconds to wait before retrying |

A refused request returns `429` with a JSON body and `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, never as a ledger.

## Team boards

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

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

Your org id is on https://useaxis.dev/team. Without an org, coordination scopes to your
personal workspace and solo behaviour is unchanged.

## The workflow

```python
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 stops
an agent that never asks, so there are three layers:

1. **Advisory ownership** (both surfaces, always on): one holder per file, 30
   minute TTL, and a denial that names the holder and their intent.
2. **Tamper detection**: pass a content hash at lock time and `verify_file_lock`
   compares the file's current hash against it. It tells you the file moved under
   you; it does not prevent the write.
3. **Enforcement** (local stdio server only): `AXIS_ENFORCE_LOCKS=1` chmods held
   files read-only, and `guarded_write` refuses a write when the lock is gone or
   the file changed.

## Support

- Contact: https://useaxis.dev/contact — support@useaxis.dev
- Support form: https://useaxis.dev/support
- Security policy: https://useaxis.dev/security.md
- Source and issues: https://github.com/VirSanghavi/axis
