AI builder operating system. Turn Claude Code from a per-session tool into a workspace that remembers, maintains itself, and never goes stale.
$ npx -y skills add ChristopherKahler/base --agent claude-code
curl -fsSL https://raw.githubusercontent.com/ChristopherKahler/base/main/install.sh | sh
Your agent is a genius with amnesia. Every session it meets your codebase for the first time and pretends otherwise. basemode gives it one memory that actually knows what things are — your code structure, your projects, your decisions, your rules, what it all means and how it connects — and puts the right slice of it in front of the model the second it's needed. No prompt to paste. No document to maintain. Same agent, briefed.
This repo is the basemode engine: one Rust binary, base, that maps your workspace into a knowledge graph and wires it into Claude Code's hook pipeline.
Ask an un-briefed agent where a function is used and it greps. Twelve files later it has a guess, delivered in complete sentences with excellent grammar. Ask an agent running on basemode and the answer was already in front of it before it started looking — the graph mapped every function, caller, and import ahead of time, and the hook placed the relevant slice into the turn.
The difference isn't the model. It's whether anything put the answer in front of it before it started guessing.
basemode wires into every hook Claude Code exposes. Each injection is a query against the moment — opening an auth file returns the auth rules, the decision that governs them, and nothing else. Targeted, never a dump.
| Moment | What lands |
|---|---|
| Session start | Everything standing that governs where the agent is about to work — active projects, open handoffs, stale files, signals |
| At the prompt | Whatever bears on the thing just asked for — matching domain rules, prior decisions, notes |
| Before a tool runs | The shape of the file about to be touched — its entities, imports, and dependents — placed before it gets read |
| After it returns | What the result means here — the call chain for the exact lines just read, while it still matters |
Every agent inherits this. Main session, subagents, explore agents — same hooks, same graph, same briefing.
macOS and Linux
curl -fsSL https://raw.githubusercontent.com/ChristopherKahler/base/main/install.sh | sh
Windows
irm https://raw.githubusercontent.com/ChristopherKahler/base/main/install.ps1 | iex
Then point it at a workspace:
cd ~/my-workspace
base scaffold
The installer downloads the release binary for your platform and hands off to base install, which puts the binary in ~/.local/bin/base, writes global config to ~/.base-gbl/, installs the AST extraction scripts, and wires the hooks into ~/.claude/settings.json. It also offers the starter star commands — *handoff, *fork, *base, *end — so a fresh install has something to type on day one (--starter-commands / --no-starter-commands to answer without the prompt). base scaffold creates .base/ in your workspace.
Install Claude Code first. The hooks are what make base do anything, and they are only written into an existing ~/.claude — install base before it and you get an inert binary, so the installer says so and you rerun base install afterwards.
Pin a version with BASE_VERSION=v0.14.1, and pass arguments straight through: ... | sh -s -- --no-starter-commands.
Needs a Rust toolchain. The release binaries above need nothing.
cargo build --release
./target/release/base install
On Windows, run the helper from a normal PowerShell window instead:
powershell -ExecutionPolicy Bypass -File scripts\build-base-windows.ps1
It imports the MSVC developer environment, resolves LLVM/libclang (bindgen needs it for the vendored RocksDB), and runs cargo install. AST extraction resolves the Python interpreter automatically on install.
base keeps itself up to date. Session start checks for a new release and, when there is one, installs it in a detached background process — no download in your way, no output, nothing to run. The swap is an atomic rename, so the session you are in keeps the binary it started with and the next one comes up new.
base config set update.auto false # pin this machine instead
base update # or drive it by hand any time
# 1. register a project
base p a -n "My App" -p "src"
# 2. map the codebase — tree-sitter across 35+ languages
# (you never have to: every app maps itself — see below. This is the by-hand form.)
base sync --ast --target src
# 3. ask the graph instead of grepping
base a q -c "auth" # find any entity named "auth"
base a q --calls "validate" # who calls this function?
base a q -f "main.rs" # what's in this file?
# 4. teach it one rule
base rule add --domain myapp --text "Migrations always run through the CLI, never raw SQL"
The code map is automatic. The first session opened in an app builds its
map in the background — a repo, or a bare folder of source files nobody has
git inited yet — the first Read of a file inside an app that has no map
builds that app's, and every turn that edits an app refreshes it. .gitignore
is honoured, an unattended build never stops to ask about the file count, and
a build that fails says why at the next session start (.base-ast/.last-error).
Never mapped by a hook: your home directory, Desktop / Documents / Downloads, a
cloud-drive root, or a workspace folder that only holds other apps.
Then open Claude Code and touch a mapped file. The file's shape arrives in the turn before its content does. Type a prompt that matches the domain and the rule arrives with it. That loop — teach the graph, watch it come back on its own — is the whole product.
Your code. Every function, struct, class, import, and call relationship, extracted by tree-sitter and queryable through SPARQL. "What calls this?" is a graph query, not a grep.
Your business. Projects with milestones and tasks. Decisions and the rationale behind them. Domain rules that fire when the context matches. The stuff that otherwise lives in your head or in a wiki that was last accurate in March.
Your documents. Markdown with frontmatter becomes connected graph nodes — headings, links, [[wikilinks]], tags, all edges. When an agent writes markdown, the hook teaches it the extraction contract at the moment of writing, so docs are born graph-aware.
Your operations. Which domains are active, what changed since last session, what's stale, what's open. Signals that orient the agent before you type a word.
All of it relational, all of it in plain-text NQuads files that live in your repo and diff in git.
The graph remembers between sessions — and between agents.
*handoff # end a session so the next one resumes where you left off
*fork # park side-work that came up, without derailing what you're doing
*base # sweep this session's decisions, tasks, and learnings into the graph
*end # all three at once, to close out cleanly
These are star commands — typed straight into the chat, defined in commands.toml, fully customizable (base commands list shows what's loaded). Open handoffs resurface automatically at the next session start.
Multiple live sessions coordinate through the relay: base relay gives titled sessions, instant pings, briefed task hand-offs that fire inside the receiving session's hooks, and an operator board of who's alive and what's pending.
base updates itself at session start from the GitHub releases of this repo (pin a machine with base config set update.auto false). Every swap or failure is appended to ~/.base-gbl/update.log; an up-to-date no-op is not. A Windows install older than 0.13.4 cannot replace its own running binary: bootstrap it once with the release zip or npx chrisai, after which it updates in place.
The relay is on by default and entirely local. Each session gets a codename, and the hooks ask it to keep a Monitor on its own inbox folder under ~/.base-gbl/.base/relay-inbox/<title>/, plus a one-line .status file the board reads. Nothing leaves the machine. base config set relay.enabled false turns it off; base config set relay.wake_nudge false keeps titles and pings but drops the arming block.
base recall --keyword "auth" # search everything remembered
base decision search --keyword "database" # find prior decisions with rationale
base context "touching the billing module" # preview exactly what would inject
# GraphRAG over your documents
base graph extract --target docs/ # LLM pass: markdown -> concepts + edges
base graph query "why did we drop Vercel?" # retrieve + synthesize from the graph
base graph analyze # god nodes, communities, bridges
And base dashboard opens the Command Center — the embedded web UI over the same graph.
# projects / milestones / tasks
base project add -n "..." -p "src/x" base p l
base milestone add -p <project> -n "..." base task add -p <project> -n "..."
base task done <slug>
# memory
base learn --text "..." --domain X --type insight|correction|decision
base decision log --domain X --decision "..." --rationale "..."
base rule add --domain X --text "..."
# code graph
base ast query -c "<name>" | -f "<file>" | --calls "<fn>" | -i "<file>"
base ast query -t apps/X -c "<name>" # another app's map, no cd
base sync --ast --target apps/X
# sessions
base handoff create|list|archive|snooze base fork create|list|archive
base relay register|send|ping|task|board|wait
# health
base doctor # graph health across tiers; fail-open by design
Every command has a short alias (base p a, base a q, base d log). base help <sub> for the rest.
A CLAUDE.md is a static document you wrote once. It doesn't know what you're touching right now, doesn't adapt, and doesn't suppress itself when irrelevant. basemode queries the moment.
LSP answers "where is this symbol" for one language at a time, with no project context and no memory. basemode holds code, projects, and decisions in one graph, across 35+ languages, and volunteers what's relevant.
Vector-store memory is a heap of passages with similarity search bolted on — you get the closest-looking paragraph. basemode stores what things mean and what they connect to: the decision, its rationale, the files it governs, the tasks it spawned.
base is a Claude Code plugin with 1 hand-picked skill, indexed on Flowy in the Agent Memory category. Install it with the command on its page. It includes base-help. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it