Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/virsanghavi/axis/llms.txt

Use this file to discover all available pages before exploring further.

When two agents reach for the same file, something has gone wrong in the coordination layer — but without Axis, neither agent knows. One finishes, the other overwrites it, and the collision only surfaces at merge time, after both have done duplicate work. Axis file locks fix the information problem: before an agent writes anything, it records its intent and the file’s current content fingerprint. When a second agent asks for the same file, it hears exactly who holds it, what they’re doing with it, when the lock expires, and what to do instead.
Locks are advisory. A process running as the same user can always chmod the file back. AXIS_ENFORCE_LOCKS stops cooperating tools and accidental clobbering; it cannot prevent a determined process. Physical enforcement changes editing ergonomics — you must write through Axis while a file is locked — so it is off by default.

How advisory locks work

Axis cannot physically intercept a write it doesn’t perform. Instead, it:
  1. Records intent — who holds the lock and what they intend to do with the file.
  2. Fingerprints the file — captures a content hash at the moment the lock is granted.
  3. Checks before future writes — any agent can verify whether the file has changed since the fingerprint was taken, catching silent clobbers before they happen.
The result is the difference between a bare “permission denied” and a full coordination message:
File 'src/auth.ts' is locked by 'dana-claude-code' for: "refactor auth to issue
JWTs instead of session cookies". Pick a different file or job, or coordinate via
update_shared_context. The lock auto-expires after 30 min; use force_unlock only
if 'dana-claude-code' has crashed.

propose_file_access

The entry point for all lock acquisition. Call this before editing any file.
filePath
string
required
Path to the file to lock. Directories are rejected — only individual files can be locked.
agentId
string
required
The requesting agent’s unique identifier for this session.
intent
string
required
A plain-language description of what you’re about to do. Used verbatim in denial messages shown to other agents. Write what you’re doing, not that you’re doing it.
Three possible responses:

GRANTED

Lock recorded. The file’s content hash is fingerprinted at this moment. Safe to proceed with edits.

REQUIRES_ORCHESTRATION

Another agent holds this file. The response includes who, what they’re doing, when the lock expires, and what to do instead.

REJECTED

Invalid path — most commonly a directory rather than a file. Lock an individual file inside the project root.

Batch locking

Pass a filePaths array to propose_file_access to lock multiple files in a single all-or-nothing call. If any file in the batch is denied, all locks acquired earlier in the same batch are automatically released — a partial lock set never silently blocks other agents.
// Lock three files atomically
{
  "filePaths": ["src/auth.ts", "src/middleware/rate-limit.ts", "tests/auth.test.ts"],
  "agentId": "dana-claude",
  "intent": "Refactoring auth layer to JWT and adding corresponding tests"
}

// If src/middleware/rate-limit.ts is held by sam-cursor, all three are released:
{
  "status": "REQUIRES_ORCHESTRATION",
  "message": "Batch lock failed on 'src/middleware/rate-limit.ts' — [...]. All-or-nothing: 1 lock(s) acquired earlier in this batch were released.",
  "failedOn": "src/middleware/rate-limit.ts"
}

Tamper detection: verify_file_lock

Because locks are advisory, a file can be edited by any process while a lock is held. verify_file_lock compares the file’s current content against the fingerprint captured at grant time, letting an agent confirm nobody rewrote the file out from under them before overwriting it.
// Request
{ "agentId": "dana-claude", "filePath": "src/auth.ts" }

// File is unchanged
{ "status": "CLEAN", "verdict": "unchanged", "heldBy": "dana-claude",
  "message": "'src/auth.ts' is unchanged since the lock was granted." }

// File was changed externally
{ "status": "CONFLICT", "verdict": "modified", "heldBy": "dana-claude",
  "message": "'src/auth.ts' was modified since the lock was granted. Re-read it before writing to avoid clobbering concurrent changes." }

guarded_write — enforced writes

guarded_write is the safe write path: the server performs the write itself, but only if the caller holds the lock and the file is unchanged since the lock was granted. If either condition fails, the write is rejected with a structured error before any bytes are written.
agentId
string
required
Must match the agent that holds the lock for filePath.
filePath
string
required
The file to write. Must be a file path, not a directory.
content
string
required
The full new content to write to the file.
Possible rejection statuses:
StatusMeaning
NO_LOCKNo active lock for this file — call propose_file_access first.
DENIEDA different agent holds the lock.
CONFLICTFile changed since you locked it — re-read and re-lock before writing.
WRITTENSuccess. Returns filePath and bytes written.
guarded_write is local-server only. The hosted server has no access to files on your filesystem. When using the hosted MCP endpoint, use verify_file_lock for tamper detection and write through your editor normally after confirming the file is CLEAN.

Releasing locks

release_file_access

Release an owned lock early — before the job is completed. Use when you finish editing a file mid-job and want to unblock teammates who may need it.

complete_job

The primary release path. Completing a job releases all file locks held for that job in one call.
Locks auto-expire after 30 minutes. Stale locks from idle agents are automatically reclaimed by the server so they don’t permanently block other agents.

force_unlock — admin override

force_unlock removes a lock regardless of who holds it. It is intended for crashed agents whose locks did not get cleaned up automatically.
filePath
string
required
The file whose lock should be forcibly removed.
reason
string
required
A description of why the override was necessary, written to the lock audit log.
Use force_unlock only for locks that are more than 25 minutes old from an agent that is demonstrably crashed. Unlocking an active agent’s lock mid-work causes the kind of collision that Axis exists to prevent.

Opt-in physical enforcement

Set AXIS_ENFORCE_LOCKS=1 to harden advisory locks into read-only file permissions:
  • On grant: the server chmods the locked file read-only. Any process that tries to write to it directly gets EACCES.
  • Writing through Axis: the lock holder uses guarded_write, which briefly restores write permissions for the duration of the write, then sets them back.
  • On release / complete_job / finalize_session: the original file permissions are restored automatically.
This stops cooperating tools and accidental clobbering. A process running as the same OS user can still chmod the file back — no userspace server can prevent that — but it makes inadvertent overwrites impossible.

Best practices

1

Write a descriptive intent

The intent string is the most important field. It appears verbatim in denial messages shown to every agent trying to access the same file. “editing file” tells nobody anything. “Refactoring auth to issue JWTs instead of session cookies — changing token payload shape” tells the whole team what’s happening and why they should pick a different task.
2

Prefer guarded_write

Route writes through guarded_write instead of writing directly. It’s the difference between detecting a collision after the fact and preventing it entirely.
3

Release locks promptly

Complete jobs as soon as the work is done. Every file you hold is blocked for every other agent on the team. Don’t hold locks while working on unrelated code.
4

Treat force_unlock as a last resort

Only use force_unlock for locks more than 25 minutes old from agents that have demonstrably crashed. Using it on an active agent is the most common cause of multi-agent clobbers in real-world use.

Build docs developers (and LLMs) love