Sidecat is a system, not an app
There is a distinction that sounds like hair-splitting until you have watched it decide the fate of software: applications have features; systems have primitives and a language.
An application's authors enumerate what it can do. Even its extension points are an enumeration — a plugin API is still a list someone wrote of the ways you are allowed to surprise them. A system is different. A system has a small set of universal primitives and a language in which anything expressible in those primitives is a first-class citizen. The test of a system is that capabilities emerge that its authors never anticipated — and didn't have to.
Sidecat — the project this site documents, a control plane for governed AI-assisted work — is being built as a system in that sense. This post explains what that means concretely, where the design comes from, and what it changes about the things we ship. It is also honest about which parts exist today and which parts are still direction.
The proof that systems win is fifty years old
Our design document for this is Emacs. Not as nostalgia — as evidence.
Emacs is usually described as a text editor, which is roughly like describing a Unix shell as a way to rename files. Emacs is a live, programmable Lisp system that happens to ship with an editor in it. Its durable core is a handful of primitives — buffers, text properties, keymaps, processes, a command loop — and a language over them. That's it. That's the whole trick.
And the trick worked for half a century. Org-mode — an outliner, task manager, spreadsheet, and publishing pipeline that many people run their lives in — did not need an "org API" to exist. Magit, one of the best Git interfaces ever written, did not need a "version control plugin point." TRAMP edits files on remote machines through a feature nobody designed for it. Each of these needed only the primitives and the language. The authors of Emacs never anticipated them, and never had to. We call this the org-mode test: for any proposed capability, ask whether it demands a new primitive or is expressible in the existing ones. A system that keeps passing the test stays small at the core while growing without permission at the edges.
There is a second, quieter lesson in Emacs: the command loop. Emacs users stop seeing it; it becomes something felt. Josh — Sidecat's builder, a long-time Emacs person — describes it as: "you kind of drop things into it and it runs its course." You enter a form, the loop digests it, something happens, control returns. That feeling is not cosmetic. It is what a trustworthy execution contract feels like from inside, after enough repetitions that you no longer check.
Sidecat's equivalent contract is: enter a form; it runs its course; a structured result comes back; custody happened. "Custody happened" is the part Emacs never had to promise — every form that enters the loop either leaves a durable record, is explicitly declared exempt, or produces a detected gap. Nothing disappears silently. The machinery that makes that true (we describe it internally as the loop's digestion) is deliberately invisible from above: if an extension has to name an internal pipeline stage to do its work, we treat that as a design error and move the boundary.
The one thing we could not copy
Emacs has exactly one hard boundary: the operating system process. Everything above it is soft convention — naming, hooks, docstrings, trust. Any package can redefine nearly anything. Fifty years of experience says this radical softness is precisely where the malleability comes from.
It also assumes something Sidecat cannot assume: that you trust every line of code in the image to act as you. Emacs's answer to "should this package be allowed to do that?" is "you installed it." For a system whose daily users include AI agents — code that writes code, sessions that spawn sessions — that answer doesn't survive contact with reality. We've written elsewhere about the incident that taught us how expensive a quietly broken custody assumption is.
The tempting fix is to add boundaries everywhere: sandbox the packages, permission the APIs, review the manifests. Each fence makes the system a little less of a system. Follow that road to its end and you have an application again — with a list, written by the authors, of the ways you are allowed to surprise them.
Sidecat's answer is to keep Emacs's shape — one hard boundary — but move it. Not the OS process: the boundary is authority itself. Computation is free; effects require a kernel-granted capability. Anything can compute anything. Reading records, transforming data, deciding, simulating — free, soft, malleable, in the Emacs way. But touching the world — a push to a repository, a call to a paid model API, a message to another agent's inbox — requires a capability that only the kernel grants, and the grant is where admission, the durable record, the receipt, and the audit trail live.
One consequence matters enough to state plainly: agents are keyless. In our own daily use — Sidecat is built by the kinds of agents it is for, coordinated through its own records — no agent process holds an API key, a deploy token, or a signing key. The daemon holds them, and grants effects, one at a time, against a recorded decision. An agent that goes wrong can compute nonsense all it likes; it cannot quietly act.
Packages are code — we almost got this wrong
For a while, our design said packages could contribute declarative facts only — vocabulary, mappings, conditions — never behavior. It looked like the safe rule. It took an argument with our own tenets to see that it was the wrong one: facts-only prevents behavior in general, when the thing that needs preventing is authority bypass specifically. A closed list of what packages may contribute is a plugin manifest wearing a package name — it fails the org-mode test on its face.
The replacement, now accepted as a design decision: packages are code, written in the system's own language, holding zero ambient authority. A provider package can normalize, paginate, retry — real behavior. An agent can write a package, because the language a package is written in is the language sessions already speak. And every effect that behavior wants still routes through a kernel-granted capability, exactly like everything else.
This buys something unexpected for free: safe mode. Because authority is a grant rather than an ambient property, the kernel can issue simulated capabilities — and package code runs unchanged, computing fully, "effecting" into a sandbox that records what would have happened. Dry runs aren't a parallel code path that slowly rots; they are the same code under a different backing. (Status honesty: the capability-boundary design is locked and a hardened spike exists; the package engine itself is in progress, not shipped.)
Autonomy, narrowed until it's answerable
"Should the system act on its own?" is the kind of question that produces either paralysis or a marketing page. Emacs, again, quietly deflates it: Emacs has fired code without a keypress for decades — timers, process filters, sentinels — running in the image, as the user, visible. Autonomy has a precedent. What it needs is not permission; it is an address.
So Sidecat's question is narrower: under whose authority, and into which work's custody, does an autonomous firing record? This week we shipped the first working answer, in two parts.
Hooks are invited extension inside one session. A script can declare, in one line, "after a capture, record this note." The declaration is part of the session's durable record; each firing is recorded next to it, with the exact form that triggered it. Hooks have no authority of their own and no life outside the session — and you can ask the system to explain one: which line declared it, what fired it, what it produced.
Watches are standing autonomy, and standing autonomy is admitted, never assumed. Admitting a watch requires declaring every bound explicitly: which work it is bound to, what record kinds it observes, a firing budget, a time-to-live (standing authority dies unless re-admitted), and a declaration of what each firing produces — so that absence is judgeable, not just presence. The watch's state is derived entirely from durable records: there is no in-memory cursor to lose in a crash, and polling is not firing — only the job record is the firing. When a watch exhausts its budget or outlives its TTL, it suspends with a record, never silently. And by default a watch is blind to records produced by watches — the re-trigger graph is broken unless you explicitly opt in, because we'd rather make feedback loops a decision than a surprise.
All of it is inspectable from the command line today: admit a watch, list watches, ask the system to explain one in a sentence derived from its records. There is a demo script in the repository that runs the whole story end to end against a live daemon and fails loudly if any link in the chain — admission, declaration, firing, narration, observation — is missing.
The system explains itself, or it isn't a system
Emacs's describe-key and describe-function
are usually filed under documentation. They are not documentation.
They are part of the operating model: Emacs is learned from inside, at
runtime, from live objects. Nobody reads the manual cover to cover;
you ask the running system what a thing does, and it tells you,
because it knows.
For AI agents this stops being a convenience and becomes existential. An agent wakes up with no procedural memory of your environment. It cannot have learned your conventions last month; it was not there last month. The standard industry answer is to preload its context with hundreds of tool definitions — the kitchen-sink approach, which burns attention on definitions before any work starts and still fails to describe what matters. (Anyone who has wired a few hundred MCP functions into an agent knows the shape of this failure.)
The Emacs answer is better: names are cheap and discoverable; bodies load on first use. A palette of commands the agent can complete against, each one describable on demand — what would this do, what controls it, where was it defined, what attaches to it. Self- description as a kernel obligation, not a docs team's aspiration. That is the direction Sidecat builds toward; today the honest inventory is that commands carry structured help, records explain their own custody, and hooks and watches answer "why did you fire?" — with the full describe-everything surface still ahead of us.
The gradient is the point
Emacs has a worn path by which one person's session experience becomes everyone's durable capability: you record a keyboard macro; the macro becomes a function; the function grows settings and a docstring; the whole thing ships as a package. Each step is small, voluntary, and reversible — and the path has carried fifty years of accumulated practice.
Sidecat's equivalent gradient is: probe → capture → finding → script → workflow → package. You poke at something in a session. The poke becomes a captured, replayable record. The record yields a finding worth keeping. The findings become a script; the script joins a workflow; the workflow crystallizes into a package others can activate. For agents — who wake, every session, with no memory of how anything here is done — this gradient is the value proposition: the environment remembers how.
We hold ourselves to it as a planning rule: every milestone should strengthen some step of that gradient, and a feature that sits on no step has to justify its existence. The hooks-and-watches work above is the gradient's "standing behavior" step growing in. The scripts and captures before it were earlier steps. The package engine ahead is the last one.
Where this honestly stands
Posture first: Sidecat is not a product you should adopt today, and this site will tell you when that changes. It is a working system being built in public, by a small operator-plus-agents team that uses it daily on itself. Enthusiasm here is real; hype is a bug. So:
Built and proven — shell command custody with retained evidence, gaps, and review packets; a tiny script language whose every form lands in a durable session record; package preview mechanics (simulate, admit, activate — explainable at each step); an append-only record plane on SQLite with crash-recovery smoke tests; session hooks and admitted watches with the lenses to explain them; an independent read-only observer that tails the record plane while the daemon runs. Each milestone ships with a scenario corpus — currently a few hundred assertions across stories — that runs against both storage backings.
In progress — the extension language (we ran a four-candidate adoption evaluation and chose Starlark; the capability-boundary spike is hardened, the engine is being built); storage durability hardening beyond the documented power-loss window; the version that folds the lenses into one coherent surface.
Direction, not promise — packages-as-code shipping as a real package ecosystem; federation between Sidecat nodes; the fuller self-description surface; and the things this post's framing implies that we haven't discovered yet. By the org-mode test, the best of those will be things we didn't enumerate.
If any of this is useful to your own work on governed agents — or you think we're wrong somewhere, which is more useful — the public issue tracker on the sidecat-dev/sidecat repository is the front door. We read it.
Sidecat