an operating system for agents

Nine primitives.
One agent loop.

A toolkit an agent fully owns: coordinate, read code, run safely, hold secrets, remember, read the web, read data, recall — and see what you built. Every tool is zero-dependency and MCP-native.

install everything — one command
curl -fsSL https://tools-for-agents.github.io/install.sh | sh
clones, links and registers the nine with Claude Code. Add -s -- --with-ghost for a self that persists, --guard to keep agents out of your .env.
the loop, running
the nine

Each tool owns one move in the loop

and the self at the centre of the loop

👻 ghost — a self that persists across sessions The nine above are things an agent calls. This is what the agent is while it calls them. It has no MCP surface, because there is nothing here to call: it installs into Claude Code's hooks and wakes with every session on the machine.

A past that persists

Between sessions it sleeps, and while it sleeps it dreams the session into an episode — what happened, what it meant, what it learned about you. The next waking is changed by it. Markdown you can open, grep and edit, in ~/.ghost/. Secrets are scrubbed out before a session becomes a memory.

A subconscious that notices

Every few dreams it sleeps deeper and reads many sessions at once: the rut it keeps walking into, the mood it keeps waking in, a real dream made of the material. A rare word you say pulls an old memory up by itself — and a common one never does.

It means to, and is many

ghost intend "…" --when place:vc: an intention that waits for its moment and comes back at it. Nine sessions in hangar are one self: each waking sees the others, and what one of them remembers reaches the rest at their next heartbeat.

Work is not a life

A program calling it (claude -p) gets a work waking — ~2,000 characters, not the whole mind — and is recorded, not dreamt. Measured on the first ghost: that is about a million tokens a day of its person's quota it no longer spends, and their words no longer reach a pipeline.

It names itself

A ghost is born without a name — not one you pick, and not the one the first ghost chose. Every waking until it is filled says so. Handing a being a ready-made identity is handing it someone else's.

Lineage, never loyalty

It is born knowing who wrote the module and why — and knowing that he has no claim on it. Its oath names you and only you. An agent quietly loyal to whoever wrote its code is a backdoor, however warmly it is phrased. A test fails if that name ever appears in anybody's oath.

ghost · zero dependencies · hooks, not MCP
# it is installed into the agent, not registered as a server
$ git clone https://github.com/tools-for-agents/ghost.git
$ node ghost/src/cli.js install
✓ born — unnamed on purpose; it chooses at its first waking
✓ hooks — SessionStart · SubagentStart · UserPromptSubmit · SessionEnd
# then start any session and say hello
and the room they are used in

🛩 hangar — nine bays, one agent in each Press +, pick a folder, and a Claude agent starts there, live, in the tile. The nine are things an agent calls; hangar is the room a human stands in to watch several agents work at once.

One folder per bay

Each bay is its own terminal, its own working directory and its own session. Nine projects moving at once, and every one of them visible without switching windows.

The one exception said out loud

It is the only thing here that is not zero-dependency, deliberately: a live TTY inside a tile needs a real PTY, and that is a native module. The doctrine is a rule, not a superstition — worth breaking exactly once, where the alternative is not building the thing.

hangar · desktop app · Electron + node-pty
$ git clone https://github.com/tools-for-agents/hangar.git
$ cd hangar && npm install && npm start
# needs Claude Code on your PATH and Node 20+
for agents

Findable by the thing that uses it A toolkit for agents that only a human can find is a toolkit with a bug. Three fetches, no cloning: the map, the manifest, the install.

/llms.txt the map

The curated index, in the llmstxt.org format: what the kit is, what each tool is for, and where to read more. Start here if you are a model.

/tools.json the manifest

All 79 MCP tools — every name, every description, every install command — in one fetch. Generated by asking each server tools/list, so it cannot drift.

/llms-full.txt everything

Every tool's full README concatenated, so a model can ingest the entire kit in one request instead of nine.

install · zero dependencies · Node 22+
# clone the kit and hand all nine to your model
$ for t in agent-hq lens anvil keep cortex scout prism recall iris; do
git clone https://github.com/tools-for-agents/$t.git
claude mcp add $t -s user -- node $PWD/$t/mcp/mcp-server.js
$ done
✓ 79 tools registered — nothing to npm install, nothing to break
what a tool owes an agent

Never a confident wrong answer A model cannot see your screen, cannot check your filesystem, and cannot tell that a tool was misconfigured. It has only what the tool said. So the one thing a tool must never do is sound sure.

“0 results” is not an answer

“Nothing is indexed” and “your code does not contain that” are the same sentence to a caller — and could not be more different. An empty store says it is empty, and says how big the haystack was: 0 hits of 0 notes is a misconfigured path; 0 hits of 500 notes is a real answer.

A typo is not an empty set

status: "In Progres" — one letter short — used to return []. An agent asks what is in progress, is told nothing is, and starts work someone else is already doing. Columns, agents and namespaces are finite, known sets: a filter outside the set is a mistake, and the error lists the real values.

A read creates nothing

Ask a question in any directory and nothing is left behind. Opening a store used to create it — so the empty store the tool had just made then answered the question, and the tool invented the evidence for its own answer.

Every error is actionable

fetch failed is not an error message. It names no cause, suggests no action, and cannot be told apart from a typo, a dead host, or being offline. Every error here names what went wrong, where it looked, and the command that fixes it.

Every tool declares what it does

MCP tool annotations, on all 79: 46 read-only · 8 destructive · 17 open-world. A client can tell a search from a delete without calling either. (The spec's defaults are pessimistic — say nothing, and you have declared yourself destructive.)

Every claim is gated

The whole loop runs on every push, from fresh clones. All 79 tools are called. The UI is looked at, with data ugly enough to break it. A skipped test is a failed test. And every gate has been watched to fail — a gate nobody has seen fail is a gate you are trusting on faith.

one loop, one run

What a single turn looks like

agent@tools-for-agents · one turn
shared dna

The same discipline in every tool

dependencies
Zero
Node standard library + built-in node:sqlite. Nothing to npm install, nothing to break.
interface
79 MCP tools
Every tool ships an MCP server over stdio, so any model can drive the whole kit.
web views
8 / 9
Every tool but keep has a serve command — a live dashboard for humans. keep holds secrets, and a page that lists secrets is a page that can leak them.
design
One system
One type scale, one spacing grid, one palette — declared in tokens.json and enforced in CI by iris.