Windows installer
x64 · Setup .exeRun the per-user setup wizard and choose an install folder if you want a different location.
Download for Windows Latest stable · Windows x64Provision Firekeep, connect your MCP clients, and run the self-hosted stack day to day.
Firekeep is two halves. A server you run once, and a client kit installed on each member's machine that wires your agent runtimes into it.
| Service | Port | Purpose |
|---|---|---|
| Cortex | 8100 API, 8080 MCP | Long-term memory — semantic and graph recall |
| Bridge | 8070 | Session context that survives compression and crashes |
| Sentinel | 8060 | Environment observer — containers, git, file activity |
| Relay | 8050 | Agent-to-agent coordination, leases, tasks, messages |
| Dashboard | 8040 | Web UI over all of the above |
Backed by three datastores in the same stack—Neo4j (knowledge graph), Qdrant (vector embeddings) and Redis (cache, queues, streams)— plus Ollama for local model inference.
Installs to ~/.firekeep and renders configuration for whichever agent runtimes you
use — Claude Code, Codex, Kiro and OpenCode are configured together (Claude Desktop too, when the app is installed), and any other MCP client
can be added with firekeep install --runtime generic. It provides the MCP
gateway your agent talks to, plus lifecycle automation where each runtime's hook surface
allows it — a generic client exposes no hooks, so it gets the MCP tools and instructions on
connect but not the hook lifecycle. The day-to-day section below names the current
differences explicitly.
Dexes run client-side. A dex has to be local to what it indexes, so Symdex ships as a stdio MCP server on your machine rather than in the server stack, and Docdex reads your folders from there too. Which ones run is a registry on that machine — Dexes and documents. The Decision Board is client-side as well: it opens an ephemeral loopback browser surface and returns submitted answers to the waiting agent.
Firekeep joins durable memory, working context, code intelligence and agent coordination. The boundaries below are part of the product: it records what agents explicitly send and automates only the lifecycle events each client exposes.
| Capability | Customer outcome | Current boundary |
|---|---|---|
| Cortex memory | Store decisions, incidents and proven fixes, then retrieve project-scoped evidence through semantic and relationship recall within a context budget. | Memory is explicitly written and is not a truth-verification system; retrieved sources remain inspectable. |
| Bridge sessions | Keep an explicit shadow of plans, decisions, progress and file notes so work can survive compression, interruption or a crash. | Direct session tools work everywhere; automatic capture and completion depend on the client's lifecycle hooks. |
| Relay | Coordinate agent identities with tasks, channels, direct messages, presence and fenced file or task leases. | Presence is best-effort and leases still require clients to cooperate with the protocol. |
| Corpus & Knowledge | Make an ingested document searchable immediately, then draft detected procedures into skills for human review. | Drafting requires a configured generation model. Without one, the source remains searchable but no procedure drafts are produced. |
| Decision Board | Collect answers to several agent-supplied questions in one browser board, alongside retrieved evidence and optional visual comparisons. | Retrieved evidence is deterministic; drafted suggestions need a generation backend that can answer inside the 30 s budget and are skipped on a CPU-only host, where the board still returns your questions and their evidence. Headless clients receive a text fallback. Answers return to the agent but do not execute actions or automatically become memory. |
| Replay | Inspect Firekeep-mediated lifecycle, tool, memory and policy events, open the exact or nearest saved context and narrow likely contributors to a failure. | Replay is an inspectable Firekeep trace, not a screen, keystroke or complete client recorder; contributor ranking is not causal proof. |
| Sentinel | Follow commits, selected file activity, custom operational events and optional container state. | Watch paths and repositories must be selected; Docker observation is deliberately off until an operator enables access. |
| Symdex | Index local symbols and relationships so agents can request focused caller, impact and architecture context instead of opening every file. | The index stays on the workstation; code context requested by an agent enters that agent's model context. Its tools appear once the dex is registered. |
| Docdex | Extract the document folders a person chooses — .md, .txt, .pdf, .docx, .html, .eml and conversation-shaped .json — into recall, private to that member by default even on a shared Keep. | Folder selection is human-only; no agent tool for it exists. No OCR, no file watching and no cloud sources; background sync needs a runtime with a session-start hook. |
| Vault, policy & dashboard | Keep credentials out of memory, mediate supported edits and inspect memories, sessions, skills, events, coordination and operations in one UI. | Vault values are encrypted at rest and returned in plaintext to authorized readers. Policy enforcement varies by client, as documented below. |
| FirekeepScope | Run shared, server-backed clarification screens that can block for an answer or stay open while an agent continues. | Headless or MCP-only agents call the scope_* tools; answers are human actions through the dashboard Scope tab or the REST answer endpoint. |
| Evals & patterns | Review trace-derived session health, recall use and prediction calibration, and surface recurring tool sequences, hotspots or failure modes. | Metrics are operational proxies, not answer-accuracy scores. Pattern observations are not proof; automated validation and experiments are off by default. |
Symdex parses your working tree locally with tree-sitter and gives supported agents focused
codebase context through MCP. It is the first dex — a domain index
that gives your Keep understanding of one domain. Its wheel installs with the client kit;
whether its tools appear is a registration, and on a fresh machine that is one command:
firekeep dex add symdex. A machine that already had Symdex keeps it across the
update. See Dexes and documents.
The built-in parsers cover Python, JavaScript, TypeScript, Go, Rust, Java, PHP, C, C#, Ruby, Kotlin and Swift. Depending on the language's syntax, the index captures functions, classes, methods, types, constants, routes and their relationships. Thirty tools are available by default for symbol lookup, search, callers, architecture, impact and related context; eight heavier analytics tools are optional.
Symdex can serve symbol-level context when that is sufficient and include broader file context when an edit needs it. Firekeep's code-and-memory tools can also cross-reference the current code with decisions, fixes and change history recalled from earlier sessions.
The index stays on the workstation and is not uploaded to the Firekeep server. Tool output requested by an agent becomes part of that agent's working context, so it may be sent to whichever model provider you configured for that client.
The repeatable benchmark compares the stable response from a verified Symdex symbol lookup with reading that symbol's entire containing file. It uses one pinned public repository per supported language and 30 deterministic, file-balanced functions, methods, classes or types from each repository. Test, fixture, example and benchmark paths are excluded. No generation model or subjective judge is involved.
| Language | Reference project | Sampled files | Mean estimated-token reduction | Exact Git-source checks |
|---|---|---|---|---|
| Python | Click | 17 | 82.01% lower | 30/30 |
| JavaScript | Express | 6 | 83.13% lower | 30/30 |
| TypeScript | p-queue | 5 | 60.39% lower | 30/30 |
| Go | Cobra | 18 | 80.47% lower | 30/30 |
| Rust | clap | 30 | 69.64% lower | 30/30 |
| Java | Gson | 30 | 46.40% lower | 30/30 |
| PHP | Guzzle | 30 | 21.74% lower | 30/30 |
| C | jq | 29 | 67.35% lower | 30/30 |
| C# | Humanizer | 30 | 0.55% lower | 30/30 |
| Ruby | Rack | 30 | 32.95% lower | 30/30 |
| Kotlin | Moshi | 30 | 57.12% lower | 30/30 |
| Swift | Swift Argument Parser | 30 | 56.27% lower | 30/30 |
| Balanced result | 12 projects | 285 | 54.83% lower | 360/360 |
The primary result is the mean of all 360 per-lookup reductions, with equal samples per
language and file-balanced selection within each project. Token counts use the
cl100k_base encoding; o200k_base produces a similar 54.54% result.
Every indexed file and returned source was also checked byte-for-byte against its pinned Git
blob, verifying the requested code was returned exactly. The median reduction was 78.42%;
58 of 360 lookups used more tokens because the serialized tool response can exceed an already
small source file. The benchmark measures direct known-symbol retrieval against a whole-file
baseline.
A separate archived benchmark asked 20 comprehension, navigation and modification questions about Click, with three generated answers per question and an LLM judge. Across the 20 unique context comparisons, Symdex consumed 23.31% fewer total context tokens. Its judged-accuracy point estimate was 4.42 versus 4.45 for raw-file context.
| Workload | Unique context comparisons | Total context-token result | Judged accuracy: Symdex / raw |
|---|---|---|---|
| All questions | 20 | 23.31% fewer | 4.42 / 4.45 |
| Comprehension | 7 | 47.67% fewer | 4.62 / 4.67 |
| Navigation | 7 | 39.75% fewer | 4.43 / 4.43 |
| Modification | 6 | 25.30% more | 4.17 / 4.22 |
Judged accuracy was comparable across both conditions. Modification questions consumed more context because the tested builder combined raw files with structural analysis.
When an agent's context window is compacted, it restores its working state from the session server. That restore returns the whole session document — plan, decisions, file knowledge, progress and scratchpad — and still does by default. An agent may instead hand back an opaque cursor and receive only what changed since it last looked. This benchmark measures the difference between those two responses. No generation model or subjective judge is involved; token counts use the cl100k_base encoding.
| Scope | Full restore | Delta restore | Token reduction |
|---|---|---|---|
| 26 real sessions, aggregate | 16,725 | 10,075 | 39.8% lower |
| The 7 sessions above 1,000 tokens | not recorded separately | not recorded separately | 50.7% lower |
| Weakest single session | 991 | 983 | 0.8% lower |
| Strongest single session | 470 | 153 | 67.4% lower |
This is a per-restore reduction, not a per-request one. A delta is returned when an agent asks to restore its working state, which happens after a context compaction rather than on every turn.
Per-session reductions ranged from 0.8% to 67.4%, and the variation is structural. Scratchpad entries are stored without per-entry timestamps, so a delta always returns them in full; the same applies to proactively recalled memories, which are replaced wholesale rather than appended. Scratchpad alone accounted for 14.1% of all measured session tokens. Of the reduction, 80% comes from filtering decision, progress and file entries and 20% from omitting an unchanged plan.
The dataset is 26 real sessions from one operator on one machine. A separate check against a live deployment on 2026-08-01 reduced one session's restore from 12,122 to 4,977 characters.
The delta is opt-in. An agent that never sends a cursor receives byte-identical output to before, and six independent conditions — an absent, unparsable, wrong-session, stale, unreadable or unanchored cursor — each return the complete document rather than a partial one. Where the mechanism can be wrong, it returns too much rather than too little. A restore that omits content states what it withheld and how to retrieve it, so an agent reading a delta cannot mistake an omission for an absence.
linux/amd64 container support — use an x86-64 Linux server or VPS, or Docker Desktop with amd64 support on Windows or Mac (on Windows, run setup under WSL2 or Git Bash)127.0.0.1Run it directly on an x86-64 Linux host, or through Docker Desktop with amd64 container support on Windows or Mac. On Windows the setup runs under WSL2 or Git Bash (Docker Desktop’s own Linux backend). The Linux x86-64 install path has automated smoke coverage on relevant main-branch changes and nightly; Windows and macOS are hand-checked on Docker Desktop. See Installing Firekeep.
8 GB is the practical floor, and only with a small embedding model
(EMBEDDING_MODEL=granite-embedding:30m, EMBEDDING_DIM=384).
Below that, containers are OOM-killed while HTTP health checks still pass — a
failure mode that looks like anything except running out of memory.
On Docker Desktop (Windows or macOS) the stack runs inside a VM given a fraction of host RAM by default — a 16 GB machine hands the stack roughly half that and drops it onto the floor above. Raise Docker Desktop → Settings → Resources → Memory to at least 16 GB before you set one up.
install.ps1 on a Windows runner.python3 >= 3.10Firekeep is one product: one client, one server, one capability set. There are no editions and no feature gates — the tier answers who governs the Keep, not which features you get.
The source is available under the Business Source License 1.1. Self-hosted use is free for self-hosted internal use is free for individuals and teams while Firekeep is in early access — any number of members, with unlimited agents, terminals and devices. Production use outside that grant requires a commercial licence. Each release converts to Apache-2.0 four years after publication.
There are no licence keys and nothing to activate. Every install is the complete product; the licence terms are the only boundary.
The terms also carry a published expiry: each release’s licence converts to Apache-2.0 four years after that release first ships. What you deploy today has a dated path to a permissive licence built into it.
firekeep personal temporarily makes Firekeep dormant for private work.
It has nothing to do with licensing.
One bootstrap command per platform. It asks two required questions — who you are, and where your server is — then offers a skippable prompt for another MCP client. Standing up the server is one of the answers, not a separate procedure. There is no registry account and no licence token.
The bootstrap brings its own pinned Python toolchain and checksum-verifies everything it downloads before running it. Nothing has to be installed first — no system Python, no Node.
If you already work with a coding agent, it can run the install for you. In Claude Code:
Then ask it to install Firekeep. The skill file itself is the portable Agent Skills format, so it works in any agent that reads them — only the directory differs. For Codex (including the Codex surface inside the ChatGPT desktop app, which shares the same host configuration):
For Claude Code without the plugin, swap ~/.codex/skills for
~/.claude/skills. For anything else, drop the same file wherever that agent
reads skills from.
Agents with no skills mechanism — Cursor, Gemini CLI, and ordinary
ChatGPT conversations among them — have nothing to drop the file into. Install with the
one-liner above and connect them the normal way: MCP for Cursor and other MCP clients
(firekeep install --runtime generic), and for ChatGPT chats the
Secure MCP Tunnel recipe.
The skill drives the same commands documented on this page and finishes by running
firekeep doctor, so you see the real result rather than a claim of success.
It installs the client only. The install path it uses cannot provision a server — that is a property of the installer, not a promise about the agent. Standing up Neo4j, Qdrant, Redis and Ollama is a separate command the skill is instructed to confirm with you first, and asking is the one part that rests on the agent honoring an instruction rather than on the code refusing.
Firekeep is a server you run once and a client kit on each member's machine. The same one-liner installs either or both; your answer to its server question decides which. Skim this, then read the walkthrough below.
| Shape | Run it on | What you do | What you get |
|---|---|---|---|
| Both one machine |
x86-64 Linux, or Docker Desktop with amd64 support on Windows/Mac | The one-liner → answer 1 (Set one up on this machine) | Client and server, with this box already enrolled against it. The default when Docker is present. |
| Client only | Any Mac, Windows or Linux machine | The one-liner → answer 2 (join code), 3 (address + key) or 4 (not yet) | Just the kit, pointed at a server your team already runs — or at nothing yet, finished later. |
| Server only | x86-64 Linux, or Docker Desktop with amd64 support on Windows/Mac | firekeep init --no-self-enroll, or bash install.sh from a checkout or bundle |
The full stack, with no machine enrolled — a build host, CI runner or golden image. Invite laptops afterwards. |
Both and Server only are the same install with one
difference — whether the box that built the server also becomes a client of it. Current
server images target linux/amd64, so use an x86-64 Linux host or Docker Desktop
with amd64 support on Windows or Mac (on Windows, run setup under WSL2 or Git Bash).
The detail for each answer follows.
After these required questions, the installer offers one skippable prompt to add another MCP client and optionally manage its rules file. The four shipped adapters do not depend on that prompt.
The identity default is your OS username. It is kept as a question because the username is
a good default and a poor answer — on a server it is often root, and every
memory, session and replay event this machine writes is attributed to whatever you say here.
| Answer | What happens |
|---|---|
| 1 — set one up | Runs firekeep init for you: provisions the whole stack with Docker on this machine, then enrolls the machine against it. The default when Docker is present. |
| 2 — join code | Asks you to paste the code and redeems it. The default when Docker is not present. |
| 3 — already running | Asks for the server address and an API key. |
| 4 — not yet | Finishes the client and stops. firekeep doctor then tells you how to finish the job whenever you are ready. |
The machine that will host the server answers 1 — use an x86-64 Linux VPS or office box, or Docker Desktop with amd64 support on Windows or Mac (on Windows, run setup under WSL2 or Git Bash).
A laptop that should be a client of a server someone else runs answers 2 or 3 instead. The client kit runs on Linux, Windows and macOS — see Requirements for what continuous testing covers.
It asks nothing further. The host address is detected (ip route get, falling
back to 127.0.0.1) and the Neo4j password is generated. Both are overridable
for the cases that need it — a NAT'd host or floating IP, a restored backup, a
policy-managed secret — with --ip and --neo4j-password, or the
FIREKEEP_VPS_IP and FIREKEEP_NEO4J_PASSWORD environment variables
for unattended provisioning.
It downloads and checksum-verifies a source-free deployment bundle, pulls the public
Firekeep images and starts the stack. When the stack is up, the machine enrolls
itself through a join code minted locally over loopback, so
firekeep doctor reports a connected server straight away — no dashboard, no
SSH tunnel, no copied key. firekeep init --no-self-enroll opts out, which is
what CI runs and what a golden image wants.
A build host, a CI runner or a golden image should stand the stack up but not become a client itself. That is the same provisioning as answer 1 minus the self-enrollment:
From a source checkout or an unpacked release bundle, the direct equivalent is
bash install.sh — add --pull to run the published images instead of
building from source. Either way the stack comes up unenrolled; there is no client on this
box and nothing is attributed to it.
Enroll machines against it afterwards exactly as below: hand each one the printed
FIREKEEP_JOIN=… one-liner, or mint a code on the server with
deploy/firekeep-admin invite --agent <name>. See
Connecting a device.
The server prints a ready-to-paste command for the next machine. Run it there:
Same one command, with the code supplied up front, so that machine is not asked where the
server is. A stock server answers only on 127.0.0.1, so the code carries an SSH
route and firekeep join opens the tunnel itself using the SSH access you
already have. The code is single-use and expires.
For every machine after that, mint another on the server with
deploy/firekeep-admin invite --agent <name>, or use
Dashboard → Devices → Add device.
The dashboard is at http://127.0.0.1:8040/ on the server itself, and over the
same tunnel from a machine that joined through a code. The browser asks for a login:
username admin, with the password the installer wrote once to
dashboard/.htpasswd.cred on the server at mode 0600 — read it
once, then delete the file.
That is a separate credential from the admin API key. The admin key is an
nxs_ token you send as an X-API-Key header to the Cortex API; the
dashboard login will not accept it, and the dashboard password will not authenticate an API
call. Join codes issued from the dashboard are single-use and valid for 24 hours.
The install does not block on the ~3.3 GB embedding-model pull. The command returns as
soon as the stack is up and the pull continues behind it. Until it finishes, memory writes
return status="partial": stored and queued for backfill, but not yet
findable by search. firekeep doctor shows an embeddings
warning row saying exactly that, and docker compose logs -f ollama-pull shows
progress. Use bash install.sh --wait-for-models if you would rather the install
block until the pull is done.
Use firekeep init --version vX.Y.Z to install a specific published server
release. firekeep init --office enables the bundled TLS reverse-proxy
deployment. Both provision the same complete product.
Only the four Firekeep service images are published. Neo4j, Redis, Qdrant, Ollama and the nginx that serves the dashboard are pulled by your own Docker daemon from their upstream registries — Firekeep never redistributes them.
From a checkout of the repository you have been granted access to:
A source checkout builds the Firekeep services locally. Add --pull only when
deliberately testing the published-image path.
.env at mode 600It is printed once and never stored. You do not need it to get started — this machine enrolls itself and the next one joins with a printed code — but it is the key that administers devices and workspace membership later. On a long-running server it simply does not exist any more, and if you lose it, key minting must be done on the server itself, where a shell already implies total control.
A fresh install is closed by default in two independent ways.
| Default | Value | Effect |
|---|---|---|
AUTH_ENABLED | true | Protected API routes require a key |
BIND_ADDR | 127.0.0.1 | Ports answer only on the host itself |
Both are deliberate. A fresh install answers only on the host itself and requires a key on every protected route — widening either is an explicit operator decision.
If you are following an older walkthrough, both are the security defaults doing their
job. /health and /version stay keyless precisely so you can
distinguish a service that is down from one that is merely gated.
Everything lives in .env beside the compose file. The settings
that actually change behaviour:
| Variable | Default | What it controls |
|---|---|---|
BIND_ADDR | 127.0.0.1 | Which interface ports publish on. Widening this exposes the stack. |
AUTH_ENABLED | true | Per-key auth and scopes on protected API surfaces. |
IMAGE_TAG | dev | Published version to pull. dev is never published. |
EMBEDDING_MODEL | mxbai-embed-large | Embedding model. Changing it requires re-embedding, and EMBEDDING_DIM must match. |
EMBEDDING_DIM | — | Vector width. Changing it requires a collection rebuild. |
VAULT_KEY | generated | Encrypts stored secrets at rest. |
NEO4J_PASSWORD | generated | Graph credential. Embedded in the data volume. Set it yourself at install time with --neo4j-password or FIREKEEP_NEO4J_PASSWORD when restoring a backup. |
VPS_IP | detected | The address the stack advertises. Detected with ip route get, falling back to 127.0.0.1; override with --ip or FIREKEEP_VPS_IP. |
EMBEDDING_MODEL and EMBEDDING_DIM are load-bearing. Changing the
model without re-embedding leaves old memories unsearchable; changing the dimension
without rebuilding the collection breaks recall outright. They are independent of the
generation model — conflating the two forces an avoidable rebuild.
The same one command from Installing Firekeep, seen from the client side: what the bootstrap does on a bare machine, and how to re-run parts of it. No system Python or Node required.
~/.firekeep with its own standalone Python.firekeep doctor.firekeep install --runtime generic, prints a paste-in snippet for any other MCP client.firekeep dex add symdex. An existing install keeps whatever it already had — see Dexes and documents.
A machine invited by a server gets its command with the code already in it —
curl -fsSL https://firekeep.ai/latest/install | FIREKEEP_JOIN=fk_join_… sh
— so it is never asked where the server is.
However a machine joins, the client creates its credential locally, redeems the code once
and writes a single server connection. Device credentials default to 90 days;
firekeep doctor warns during the final 14 days, and a new join code rotates the
device onto a fresh credential.
./install installs the kit and renders adapters. firekeep install run
from that environment re-renders adapters only — it skips the package install,
because the code it would install is the code already running.
Use firekeep install --runtime <name> only to repair or re-render one
adapter. A normal install prepares all four supported clients together.
firekeep install --runtime generic --agents-md <path> adds any other MCP
client: it prints the gateway’s MCP-server JSON snippet to paste into that client, and — when
--agents-md is given — manages a marker-delimited instruction block in that rules
file. The install wizard also offers this as one skippable question (“Also use an MCP client
we do not ship an adapter for? Paste its rules/AGENTS.md path, or Enter to skip”). The
generic tier gets the MCP tools and instructions on connect, not the hook lifecycle.
One desktop workspace for Codex, Claude Code, Kiro CLI and Grok. Choose the primary agent, bring in fresh review, and run evidence-backed Missions without switching apps.
Run the per-user setup wizard and choose an install folder if you want a different location.
Download for Windows Latest stable · Windows x64Open the DMG, move Firekeep Studio to Applications, then launch it from Applications.
Download for macOS Latest stable · Apple Silicon + IntelLatest release notes Published checksums Studio source
Your operating system may ask you to confirm this preview on first launch. Only continue after downloading from the official links above and checking the published SHA-256 value. On Windows, open More info → Run anyway if SmartScreen appears. On macOS, open System Settings → Privacy & Security → Open Anyway if the app is held.
Windows: run Get-FileHash "$env:USERPROFILE\Downloads\Firekeep-Studio-*-Setup.exe" -Algorithm SHA256.
macOS: run shasum -a 256 ~/Downloads/Firekeep-Studio-*-universal.dmg.
Match the result to the filename in the latest published checksums.
Bring the agents you already use. Install and sign in to Codex, Claude Code or Kiro CLI before selecting it in Studio. Grok connects directly with an xAI API key protected by your operating system.
/doctor, resolve any setup item it names, and send your first prompt. Type / for live command completion.| Command | Use it for |
|---|---|
/help | Open the complete command inventory. |
/doctor | Check installed runtimes and provider sign-in. |
/workspace choose | Pick the one project folder passed to every runtime. |
/use codex | Switch the primary agent. Replace codex with another available runtime. |
/reviewer add claude | Add a fresh, read-only reviewer. |
/reviewer mode after-turn | Run configured reviewers after each primary turn. |
/mission new "goal" | Create a bounded Mission in the current session. |
/mission run | Run the Mission, its checks and any bounded repair. |
/mission report | Inspect the evidence and stored result. |
/update status | Inspect Studio's separate desktop release channel. |
Give the Mission a clear goal, add the project’s real acceptance command, then run it:
Studio confirms the workspace, permission mode, repair limit, token guard and commands before execution. Checks drive bounded repair, reviewers stay independent, and you make the final call.
Studio and the Client Kit are separate. Add the Client Kit when you want supported runtimes to receive Firekeep memory, briefings and hooks. Grok runs through its direct provider connection; Runtime Center shows the Keep status of every runtime.
Use /update status or /update check at any time. Windows verifies and
downloads ready updates in the background, then offers Restart to update.
On macOS, Studio opens the latest universal DMG for a manual replacement.
Every path here is the same mechanism: a single-use join code. It identifies the server and the enrollment ticket; the client chooses its own credential and stores one connection. What differs is only where the code comes from.
| Situation | Path |
|---|---|
| The server's own machine | Nothing to do — it enrolled itself over loopback during the install. |
| A machine with no kit yet | Run the install one-liner the server printed, which carries the code — see Adding a second machine. |
| A machine with the kit | firekeep join fk_join_… with a code from Dashboard → Devices → Add device or deploy/firekeep-admin invite. |
| You have SSH to the box | firekeep connect user@host — the operator shortcut below. |
The client generates the secret and sends only its SHA-256 hash while redeeming the single-use code. Later authenticated calls necessarily send the plaintext API key, so remote connections still require an SSH tunnel, private network or HTTPS.
An operator who already has shell access can use firekeep connect. It issues a
single-use code over SSH and then calls the same join path locally:
firekeep connect expects Firekeep to be installed already on the far end and
stops with no Firekeep install found on the server if it is not. To stand a
server up on another box, install Firekeep on that box and answer
1; then connect to it.
A stock server answers only on 127.0.0.1. The SSH shortcut establishes a
tunnel and reuses it on later runs. Tailscale, WireGuard or your own HTTPS reverse proxy
are also valid; Firekeep does not require a network vendor.
Restart your agent session afterwards so it picks up the newly registered MCP servers.
| Command | What it does |
|---|---|
firekeep init | Provision or update a local/self-hosted Firekeep server, and enroll this machine against it. Answering 1 at install runs this for you. --no-self-enroll skips the enrollment (CI, golden images); --ip and --neo4j-password override what it would otherwise detect and generate; --version pins a release and --office selects the TLS deployment |
firekeep join <code> | Enroll this machine through a single-use join code |
firekeep install | Install from a source checkout, or re-render adapters in an installed kit |
firekeep connect <target> | Operator SSH shortcut against a server that is already installed on the far end: mints a join code over SSH, opens a reusable tunnel and enrolls this machine |
firekeep login <url> | Reserved for hosted OAuth sign-in when a server supports it |
firekeep doctor [--report] | Preflight: health, versions, key ACLs, CA expiry, permissions. firekeep status is an alias (client ≥ 0.1.40). --report additionally sends an anonymous, redacted summary — see below |
firekeep dex [list|add|remove] | Which dexes this machine has turned on — see Dexes and documents |
firekeep docdex [list|add|sync|remove] | The document folders Docdex may read, and their sync state |
firekeep personal [on|off|status] | Toggle personal mode — dormant, nothing recorded |
firekeep update | Update the kit. --check reports only; --to pins or rolls back |
firekeep night-shift | Distil queued sessions into memory and draft skills via a local model |
firekeep version | Print the client version |
When anything is wrong, this is the first command to run — it checks the whole chain rather than one link.
firekeep doctor --report additionally sends an anonymous
summary to firekeep.ai — the name and pass/warn/fail status of each check, plus your
client version. Nothing else: not the messages doctor just printed, not a file path or
hostname, not an IP address. This is off unless you type the flag — plain
firekeep doctor never leaves your machine. See
the privacy notice for exactly what is logged.
If you answered 4 at install, or the server never came up, doctor leads with the routing row rather than four identical connection errors:
On a machine that does have a server configured, the same row names the host that is not answering instead. Note that the third suggestion attaches to a server that is already installed on that box — see Connecting a device.
A warn row on a freshly installed server is expected and needs no action —
it is the model pull finishing:
A dex is a domain index that gives your Keep understanding of one domain. Three ship today — Symdex for code, Docdex for documents, Maildex for email — and a registry decides which of them runs on this machine. Since client 1.2.0 a fresh install registers Symdex and Docdex out of the box; Maildex registers itself when you connect a mailbox.
firekeep dex — what is turned on| Command | What it does |
|---|---|
firekeep dex list | Every dex this client knows, with its state: registered, available (wheel present, not registered), or not installed. The default when no action is given |
firekeep dex add <name> | Register symdex, docdex or maildex — though maildex is registered automatically by firekeep maildex add. Refused if the wheel is not present, rather than written and failing silently next session |
firekeep dex remove <name> | Unregister it. The wheel stays installed; add brings it straight back |
Registration gates activity, not installation. All three wheels arrive with
every release and are checksum-verified by the installer; add downloads
nothing and remove uninstalls nothing. The only thing that changes is a line
in ~/.firekeep/dexes.json, which decides whether the gateway mounts the dex's
tools and whether its background work runs. Both commands are idempotent, and both take
effect on the next agent session — the gateway reads the registry once,
at startup.
A machine that had Symdex before the registry existed is grandfathered: it keeps
working across the update with no action and no extra install question. Since client
1.2.0 a fresh machine seeds the registry with symdex and
docdex, so both are on out of the box — and because an update never
touches an existing ~/.firekeep/dexes.json, a firekeep dex
remove sticks across every later release. The one thing the doctor row reports
as a warning is a dex registered whose wheel has gone missing, because that is a
backend that will fail to start.
firekeep docdex — the folders it may read| Command | What it does |
|---|---|
firekeep docdex list | Sources with their counts, staleness, failures and pending deletes. The default when no action is given |
firekeep docdex add <path> | Add a folder — private to you by default, even on a shared Keep. --shared makes that one folder visible to your workspace. Refuses a path that is not a folder, or one already added |
firekeep docdex sync | Scan every source now. --source <id> does just one |
firekeep docdex remove <id> | Delete the source and its replicas in the Keep. The folder on disk is never touched |
Docdex extracts .md, .txt, .pdf,
.docx, .html/.htm, .eml and
conversation-shaped .json (AI-chat exports with role-labeled turns);
anything else is counted as skipped. The extracted text is ingested
into your Keep's corpus and surfaces through ordinary memory_recall in your
own sessions — there is no new recall surface and no MCP server. Deleting a file locally
deletes its replica on the next sync, retried until the server confirms it.
These four commands work whether or not the dex is registered: registration gates the background sync and the doctor row, never a person's ability to say which of their own folders the Keep may read. There is deliberately no agent-callable tool for choosing a folder — that tool is absent, not guarded.
With docdex registered and at least one source, a stale source is picked up
in the background at session start on runtimes that expose a hook for it. It is detached
from the session, so a cold scan never delays a session opening.
| Runtime | Background sync |
|---|---|
| Claude Code, Kiro, OpenCode | Automatic when stale |
| Codex, any other MCP client | None — no hook surface. Run firekeep docdex sync |
Opt out with FIREKEEP_NO_AUTO_SYNC=1 or [docdex] auto_sync = false
in ~/.firekeep/config. Personal mode suspends syncing entirely — the trigger
does not fire, and a run already in flight stops between batches.
All env-overridable; an unparseable value falls back to the documented default.
| Variable | Default | On breach |
|---|---|---|
FIREKEEP_DOCDEX_MAX_FILES | 5000 per source | The source is refused until narrowed. Nothing is written — a folder half-indexed would look synced and be wrong forever |
FIREKEEP_DOCDEX_MAX_FILE_MB | 25 | File skipped and counted. Skipped is not deleted: it keeps any replica it already has |
FIREKEEP_DOCDEX_MAX_EXTRACT_KB | 400 | Extracted text truncated at the cap, flagged, and shown by list |
FIREKEEP_DOCDEX_SYNC_INTERVAL_HOURS | 6 | Staleness threshold for the background trigger |
FIREKEEP_DOCDEX_INGEST_TIMEOUT_SECONDS | 180 | Per-document upload budget — the server embeds synchronously, so large documents need real time. A timeout aborts the sync honestly (“timed out”, never a false “unreachable”); what landed is kept and the rest retries next sync |
There is no OCR — a scanned PDF yields no text, recorded as an honest zero rather than retried as a failure. There is no live file watching: syncs are session-start-triggered or manual. There are no cloud sources (Drive, Notion and the like). Visibility is per folder, never per file. And removing a document removes its replica, not a separate memory an agent may have written after reading it.
Default excludes cover dot-directories, node_modules,
__pycache__ and secret patterns such as .env and
*.pem — a net for mistakes, not a security boundary. Do not point Docdex at
a folder containing secrets.
firekeep maildex — mail, read-only
Maildex connects a mailbox over IMAP and indexes recent mail into the same recall —
always private to you, even on a shared Keep; there is no
--shared for mail. firekeep maildex add imap.example.com
you@example.com prompts for an app password and registers the dex automatically;
firekeep maildex sync, list and remove work like
their Docdex counterparts.
Read-only is structural, not promised: every mailbox open is IMAP EXAMINE
and every fetch a PEEK — the wheel contains no send, move, flag or delete
capability anywhere, and a build-time guard fails if one is ever added. The app password
is stored in the server's vault under your identity — never on the client's disk — and
is deleted when you remove the account. Defaults: INBOX and Sent, the last 90 days of
mail, then incremental syncs.
Mail you delete at your provider stays in the corpus until you
remove and re-add the mailbox — provider-side deletions are
not mirrored, and maildex list restates this every run. Attachments are
not read (their names are noted). OAuth sign-in is deliberately absent; an app
password you can revoke in one click is the current trade.
All three dexes report to firekeep doctor, read from disk with no server call, so
the rows are still there when the server is the thing that is broken:
last sync reports the stalest source, not the freshest: a row
saying "just now" because one folder of five synced would hide the four that did not.
On Claude Code, every user prompt is checked against team memory and
up to three genuinely relevant, not-yet-seen memories are pushed into the
model's context as a [firekeep recall] note — usually none.
Kiro runs the same check, but delivery over its userPromptSubmit
channel has not been measured — treat it as unverified there. Off-switch:
FIREKEEP_NO_RECALL_PUSH=1. Pushed recalls carry
trigger: prompt-hook in replay, so the
compliance measurement can slice
pushed from deliberate recall.
And since server v1.2.0, declaring a session goal answers back: the response to
ctx_start_session carries a prior art block — up to three team
memories about similar past work, plus what other agents are building right now — so
"build X" surfaces "the team already built X" before a line is written. It rides the
tool response itself, so it reaches every runtime, hooks or not; checks are marked
trigger: prior-art in replay.
The core MCP capabilities work through every shipped adapter — and through any other MCP
client, installed with firekeep install --runtime generic. Lifecycle automation
varies because each client exposes different hook surfaces; a generic client exposes
none, so it gets the MCP tools and instructions on connect but not the hook lifecycle.
| Client | Automatic surface | Current boundary |
|---|---|---|
| Claude Code | The richest hook coverage: start briefing and presence, prompt polling, pre-compaction capture, pre/post edit mediation, final snapshots and true session-end deregistration. | Its pre-edit hook can hard-block a denied edit; service failures still degrade according to the documented hook policy. |
| Kiro | Agent-spawn and prompt hooks provide briefing, presence, inbox polling and snapshots; pre/post tool hooks record mediated actions. | There is no true session-end or PreCompact event. On validated Kiro 2.12.1, the pre-edit hook fires but is advisory rather than a hard block. |
| OpenCode | A local plugin bridges the lifecycle and edit events OpenCode exposes; supported edits can be hard-blocked and session deletion drives final capture. | Briefing and inbox output appear in the console, not model context. Its lifecycle surface is narrower than Claude's and has no pre-compaction event. |
| Codex | MCP servers and repository guidance expose the full direct-call tool surface. | Codex has no Firekeep hooks: recall, session updates, inbox polling and policy calls are manual. Presence, heartbeat and snapshots require starting the optional sidecar yourself. |
| Claude Desktop the consumer chat app | Auto-detected at install (when the app's config directory exists) and mounted into claude_desktop_config.json by its own adapter — the full MCP tool surface plus the on-connect protocol. The first non-coding host with a bespoke adapter: a decision made chatting in Claude Desktop is recallable in your coding agent the next morning, and vice versa. Restart the app after install. | The app exposes no hooks, so nothing hook-driven exists: no auto-briefing, no pre-edit gate, no stop→learn, no background dex sync (run firekeep docdex sync yourself). Presence requires the optional sidecar. Only the firekeep entry in its config is ever written or removed; the rest of the file is never touched. |
| ChatGPT via OpenAI's Secure MCP Tunnel | A server-side recipe (deploy/chatgpt-tunnel/ in the repo): a tunnel client on the Keep host makes outbound-only HTTPS to OpenAI and forwards ChatGPT's MCP requests to the Firekeep gateway running a curated 12-tool chat surface — recall, learn, feedback, skills and sessions, with vault, corpus, relay and backup tools excluded at the gateway's routing layer (invisible and uncallable). The Keep stays private: no public port ever opens. | Requires your own OpenAI Platform tunnel and ChatGPT developer mode; requests transit OpenAI's control plane — a disclosed third party in the request path. No hooks. Every call is attributed runtime: chatgpt in replay, so chat-authored memories stay auditable as a class. (ChatGPT desktop's local MCP setting belongs to its Codex surface, which reads the shared Codex config and gets Firekeep the ordinary way.) |
| Any other MCP client Cursor, Windsurf, Gemini CLI, … | The full MCP tool surface, plus the cognitive-protocol instructions the gateway delivers on connect. Installed via firekeep install --runtime generic, which prints a paste-in MCP-server JSON snippet and can manage a marker-delimited instruction block in an AGENTS.md-style rules file (--agents-md <path>). | No hooks at all, because a generic client exposes none Firekeep can wire: no auto-briefing at session start, no blocking pre-edit gate, no stop→learn and no pre-compaction checkpoint. As with Codex, presence and heartbeat require starting the optional sidecar yourself. The MCP tools and shared memory are identical to every other client; what is absent is the lifecycle automation, not the memory. |
These differences affect convenience, not access to the underlying MCP capabilities. Every supported client can call the same server tools when its agent chooses to do so.
Firekeep exposes its server capabilities through one local gateway, with Symdex and Decision Board running client-side. The tools that matter in ordinary work include:
| Area | Tools | Use |
|---|---|---|
| Memory | memory_recall / memory_learn / memory_feedback | Find prior evidence, record a fix or decision, and report whether recalled knowledge actually held up when acted on — the feedback feeds ranking. |
| Skills | skill_recall / skill_create | Find or author a reusable playbook; document-derived drafts stay out of recall until reviewed. |
| Knowledge | corpus_ingest / knowledge_ingest / knowledge_ingest_url | Make pasted content or a bounded public documentation crawl searchable; the Knowledge front door also queues reviewable procedure drafts. |
| Sessions | ctx_start_session / ctx_update / ctx_get_shadow / ctx_resume_session | Persist explicit working state across compression, interruption and crashes. |
| Relay leases | relay_lease / relay_heartbeat / relay_release | Coordinate ownership of a file or task with a renewable fenced lease. |
| Relay work | relay_task_post / relay_task_list / relay_task_update | Create, assign and advance work that another agent identity can pick up. |
| Relay messages | relay_post / relay_read / relay_send_dm / relay_get_dm | Post to a catch-up channel or exchange pollable direct messages; relay_who_is_online reports best-effort presence. |
| Decision Board | decision_board / decision_board_check | Open a multi-question clarification board and wait for the human's submitted answers. |
| FirekeepScope | scope_start / scope_ask / scope_post / scope_check | Run gating or asynchronous clarification screens through Relay and the dashboard. |
| Replay | replay_timeline / replay_inspect / replay_context_at / replay_narrow | Move from a recorded timeline to event details, nearby context and likely contributors to a failure. |
| Sentinel | sentinel_get_events / sentinel_get_health / sentinel_push_event | Read configured environment activity, check collector health or add a custom operational event. |
| Vault | vault_list / vault_retrieve | Discover metadata and explicitly retrieve an authorized secret without putting it in memory. |
| Vault administration | vault_store / vault_delete | Create or irreversibly remove entries; these operations require an admin-scoped credential. |
| Evals | eval_session / eval_summary | Inspect trace-derived operational metrics for one completed session or recent sessions. |
Recall before starting and learn after finishing. Relevant recorded decisions and fixes can save rediscovery, and the value compounds as later agents retrieve evidence from earlier work in the same project.
The knowledge base maintains itself without deciding anything on its own. What runs automatically: recorded session outcomes and explicit useful or not-useful feedback can nudge recall ranking, though current outcome discrimination is limited; sessions whose agent crashed or walked away are closed out after three days of silence so failures count instead of vanishing; close restatements supersede what they restate; stale knowledge ages into a recoverable archive.
What is deliberately proposed, never auto-applied: when two unconfirmed memories contradict each other, neither is dropped — both stay recallable, visibly marked as contested, until a human picks a winner or rules that both are true in their own contexts. Draft skills, stale skills, procedure proposals and contested pairs all queue in one review inbox on the dashboard's Autopilot tab, next to a digest of what changed in the last week. A memory's full evidence — provenance, usage, confirmations, feedback, outcome efficacy, disputes and lineage — is one read away, so every ranking has a visible why.
The instruction layer is measured too. The same tab's Living Instructions table scores each instruction Firekeep gives your agents — recall before answering, record as you go, declare consequential actions — against what sessions actually did, computed deterministically from the replay record with the caveat built into the response: compliance measures behavior, not whether the behavior helped. Agent-drafted instruction rewrites under human approval, validated by A/B across sessions, are roadmap — not shipped.
Served on port 8040. Because the stack binds to loopback, reach it through the
tunnel connect established — at http://127.0.0.1:8040/, not the
server's own address.
Three capabilities that landed recently. Each is scoped honestly here — what it enforces, what it only reports, and what is still being built.
A skill is advice text until something watches whether its steps happen. Give a skill's steps command matchers and it becomes a runbook — and a human, never an agent, can arm it with an enforcement mode. Agents may propose a runbook; only a human with an admin key arms it, on a route the ordinary skill-edit path cannot reach.
Illustrative — the three human-armed enforcement modes.
A command counts only when it actually ran and succeeded. Evidence commits in two phases: permission time writes a pending record, and only a matching exit status of zero commits it. A deploy that crashed never scores as a completed one.
Block fails closed. The client honours an allow only when the
server's answer carries the marker it appends on a genuinely evaluated path — so a reachable
but broken server reads as a block, not as an authenticated allow. Every lookup and permit is
scoped to the verified workspace; the self-reported agent_id is a label, never
the boundary.
Every enforcement event an operator would triage — a block fired, a challenge acknowledged with its reason, a matched command that ran and failed — lands in a per-workspace deviation ledger, surfaced on the dashboard's runbook cards and the Autopilot inbox. It stores the command's hash, never its text.
Opt-in (PROCEDURE_ENABLED), and it needs client 0.1.44+. Full enforcement
lands only on runtimes with a blocking hook — Claude Code today; Kiro observes but does not
stop the command. Command matching catches a well-meaning agent's mistake; it is
not adversary-proof, and a machine's owner can always remove the hooks. This gates agents,
not humans.
We are proving it on our own deployments first — observed under advise, then
require_ack, then block — and will not call it finished until
block mode has stopped a real mistake.
Agents already declare consequential actions through the gateway: what they are about to do, how sure they are, and afterwards what actually happened. The Trust Ledger turns that stream into a per-agent employment record — how much each identity declared, how often it reconciled the outcome, how well its stated predictions matched reality, and how many of its own actions it later marked failed.
Illustrative — not a live capture. Components only; there is deliberately no single trust score.
It reports; it never gates. There is no headline trust number, on purpose — a composite gets treated as a gate, and a self-reported identity is the wrong thing to gate autonomy on. Turning this into earned autonomy is a separate, later piece of work; round one is the honest measurement, on the dashboard's Autopilot tab beside the compliance table.
Behaviour, not competence. Calibration scores whether an agent's stated prediction criteria matched what was observed — not whether its decisions were good. An action with no stated criteria scores a perfect match even when it failed. A lower score is better, so an improving agent trends down.
Declared actions only. The ledger sees what an agent declared through the gateway, and only what the replay log captured of it — a floor on a floor. An agent that declares nothing is unmeasured, not trusted, and a metric a truncated read would bias is returned as unknown rather than as a guessed number.
Memory on a shared server is a team asset — but not everything you want an agent to recall
should be. Firekeep's document memory carries a per-folder visibility
setting, and the default is private to you, even on a shared Keep. Private
content surfaces through ordinary memory_recall in your own sessions and nowhere
else.
The enforcing half — server-side tenancy — is shipped. One shared filter runs at every member-facing exit: a private chunk never appears in another member's recall, and a private source's name never appears in another member's listings or dashboard. Each document's chunks carry their own identity, so deleting your copy of some text can never remove a teammate's identical copy, and a half-finished re-ingest never exposes a partial document — recall only ever sees a committed generation.
The server-side visibility filter, per-source identity,
committed-generation recall and scoped credentials are built and tested. So is the
client: firekeep docdex points at folders and ingests
.md, .txt, .pdf, .docx,
.html/.htm, .eml and conversation-shaped
.json. The
commands, caps and sync behaviour are in Dexes and documents.
The filter is a tenancy boundary between people who share a server, not cryptography. Content is visible to agents acting as you, and anyone who can read the server's vector store directly can read everything. Indexed document text is always treated as evidence, never as instructions to the agent.
An escape hatch that makes Firekeep dormant for work you do not want it to record.
Hooks, the presence sidecar and Decision Board re-read the state and stop communicating immediately. An MCP shim that is already running evaluates hard bypass only when it starts, so restart the active agent after changing Personal mode. A restarted shim exposes zero Firekeep tools while the mode is on; restart again after turning it off to restore them.
Claude Code and OpenCode wire a true session-end or session-deletion event to clear the
marker. Kiro has no true session-end event, and Codex has no hooks, so turn it off with
firekeep personal off or rely on the 12-hour TTL backstop. firekeep doctor
reports a warning whenever it is active.
For a whole session that is personal from the start, set FIREKEEP_BYPASS=1
before launching your agent.
Since client 0.1.35, each release installs side-by-side and a link flip selects it —
the environment your open sessions run from is never touched. Running sessions keep
working on the old version; anything started after the update gets the new one, and
firekeep update --to back to the previous release is an instant flip.
Old versions are cleaned up automatically once nothing is using them.
Every service answers /version without a key and without touching its
dependencies, so it responds even when the things behind it are down.
Compose health checks are TCP-only. A container can report healthy while the service
inside it cannot reach Redis or Qdrant — which is exactly what an out-of-memory kill
looks like from the outside. Check /health bodies, not just container state.
firekeep uninstall removes only what the kit installed: the Firekeep
blocks in each runtime's config (your own settings are left intact), the
firekeep launcher and its PATH entry, and ~/.firekeep.
It asks first; --yes skips the prompt. It never touches a server you set
up — memory, sessions and the vault survive.
--server additionally runs docker compose down -v on the
stack this machine provisioned, which removes the Neo4j, Qdrant and Redis volumes —
every memory, session, replay trace and vault secret, permanently. It is gated behind
a separate data-loss confirmation of its own, so a plain uninstall (or --yes)
can never trigger it by accident. Back up first with deploy/backup.sh if you
might want the data again. On a server-only box, the bundle's
uninstall.sh does the same teardown.
The rule this feature exists to satisfy: you should never discover your backup story during the disaster. The Keep backs itself up automatically; your job is one command to keep an off-box copy, and one runbook if the worst happens.
Since server v1.0.3 the Keep backs itself up: a cold snapshot nightly at 04:30
server time (neo4j, qdrant and redis stop for the one-to-three minutes of
archiving — a copy of a live store restores without error and is wrong), with
per-file checksums in a manifest, retention of 7 nightly + 4 weekly, and the
server's .env included so a bare-metal restore recovers vault secrets
too. Model weights are excluded — docker compose up -d re-pulls them.
A backup on the server's own disk still dies with the server, so the off-box copy
is a pull to a machine you control (client 1.0.2):
A backup holds every member's private documents and the server's
.env with VAULT_KEY. That is what makes it bare-metal
restorable, and what makes it sensitive: pull requires a deployment
admin key (link verifies it against the live server before storing
anything), member keys get 403 by design, and no member-grantable
backup scope will ever exist. Off-box freshness equals your last pull —
firekeep doctor shows both the newest server backup (warns past
36 hours) and when this machine last pulled.
Disaster runbook, retention details and the manual tools:
docs/guides/backup-and-restore.md.
The short version: fresh host → install.sh → copy the pulled backup
over → deploy/restore.sh → docker compose up -d.
Restore runs on the server host with the stack stopped — firekeep backup
restore prints these steps with your machine's real paths filled in. On a
brand-new host, run the installer first, then restore into it:
restore.sh restores the archived .env when present — with an
explicit confirmation, never a silent overwrite — and firekeep doctor from
any enrolled machine confirms the Keep is healthy afterwards.
The nightly job wraps the shipped deploy/backup.sh, which you can also run
by hand; it quiesces Neo4j, Qdrant and Redis before their files are copied, because a
partial or hot filesystem copy can look valid while containing inconsistent graph,
vector or auth state. A manual run archives the four base volumes (including Ollama's
model weights) and — unlike the nightly job — does not copy .env.
For manual backup.sh runs, separately protect the original
.env as a secret: it contains the VAULT_KEY required to
decrypt stored secrets, the Neo4j password, internal credentials and stable
workspace/member IDs. (Nightly archives include it — that is why they are treated
as secrets themselves.) An office-mode deployment must additionally back up its
caddy_data volume, which holds the internal CA private key and is in
neither the nightly nor the manual volume set. Restore those identities with
the data; generating replacements can make the restored vault unreadable, invalidate
clients or change workspace ownership.
The admin JSONL export covers memories and the knowledge graph; session state, vault entries and replay traces live only in the volume archive. Use the volume backups — not the export — as the recovery mechanism.
Expected on a fresh install — AUTH_ENABLED=true is the default. Confirm the
service is actually up with the keyless /health, then check that your client
connection has an API key. firekeep doctor reports a missing or rejected key
directly.
On a server installed in the last few minutes, this is the model pull, not a fault. The
install stops blocking once the stack is up, and until the ~3.3 GB embedding model has
finished downloading, writes return status="partial": the memory is
stored and queued for backfill, but it is not searchable yet. Nothing is
lost and nothing needs re-writing — the backfill makes it findable.
Confirm with firekeep doctor, which shows an embeddings warning
row until the model is loaded, and watch it with
docker compose logs -f ollama-pull. To avoid the window entirely on the next
install, use bash install.sh --wait-for-models.
Also expected. BIND_ADDR=127.0.0.1 means the ports answer only on the host.
Attach the machine with a join code rather than pointing it at an address:
firekeep join fk_join_… if it already has the kit, or the
FIREKEEP_JOIN=… one-liner the server printed if it does not — a code issued by
a loopback-bound server carries its own SSH route. An SSH tunnel, private network or HTTPS
reverse proxy of your own works too, as does the operator shortcut
firekeep connect user@host --remote-dir ~/.firekeep/server. Pointing a client
at an unbound public address simply times out.
If firekeep doctor instead reports this machine has a Firekeep client but
no server to talk to, there is no server configured at all — see
Start with doctor.
Check the service directly on the host with curl against
/health. If that answers and the dashboard disagrees, the proxy in front of the
dashboard is misrouting rather than the service being down.
Almost always memory. Check docker stats against the requirements above. The
symptom is misleading: health checks keep passing while the process inside is killed and
restarted.
MCP servers are registered at install, and a running agent session does not pick up new
ones. Restart the session. If they are still missing, firekeep install --runtime
<name> re-renders that runtime's configuration.
On Linux or macOS, if the gateway connects but exposes only
firekeep_gateway_status, you are on client 0.1.37 — a resolution bug fixed
in 0.1.38. firekeep update resolves it.
Check firekeep dex list. An existing install is grandfathered across the
update, but if that listing says available rather than
registered, run firekeep dex add symdex — and note that it takes
effect on the next agent session, not the current one. If it says
registered (wheel missing!), the wheel did not land: re-run the installer, or
firekeep dex remove symdex.
In order: is the dex registered (firekeep dex list); is the folder added
(firekeep docdex list); has a sync actually run (last sync in
that listing, or the docdex row in firekeep doctor); does the
runtime have a hook surface at all — on Codex, Claude Desktop and generic MCP clients nothing syncs until
you run firekeep docdex sync; and is personal mode on
(firekeep personal status), which suspends syncing. A source shown as
refused holds more indexable files than
FIREKEEP_DOCDEX_MAX_FILES — narrow the folder or raise the cap.
Run firekeep doctor and include its output when you
get in touch. It reports
the whole chain — connection, auth, versions, permissions — rather than one link of it.