Firekeep documentation

Provision Firekeep Solo, enroll your AI coding clients, and run the self-hosted stack day to day.

Solo is available now

The public client and server release channels are live. Use the installation steps below to provision Solo and connect supported clients. Team remains coming soon.

Architecture

Firekeep is two halves. A server you run once, and a client kit installed on each developer machine that wires your agent runtimes into it.

Server services

ServicePortPurpose
Cortex8100 API, 8080 MCPLong-term memory — semantic and graph recall
Bridge8070Session context that survives compression and crashes
Sentinel8060Environment observer — containers, git, file activity
Relay8050Agent-to-agent coordination, leases, tasks, messages
Dashboard8040Web 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.

Client kit

Installs to ~/.firekeep and renders configuration for whichever agent runtimes you use — Claude Code, Codex, Kiro and OpenCode are configured together. It provides the MCP gateway your agent talks to, plus lifecycle automation where each runtime's hook surface allows it. The day-to-day section below names the current differences explicitly.

Symdex code intelligence runs client-side. It has to be local to the code it indexes, so it ships as a stdio MCP server on your machine rather than in the server stack. The Decision Board is client-side too: it opens an ephemeral loopback browser surface and returns submitted answers to the waiting agent.

Capability map

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.

CapabilityCustomer outcomeCurrent boundary
Cortex memoryStore 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 sessionsKeep 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.
RelayCoordinate 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 & KnowledgeMake 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 BoardCollect answers to several agent-supplied questions in one browser board, alongside retrieved evidence and optional visual comparisons.Evidence and suggestions are best-effort; headless clients receive a text fallback. Answers return to the agent but do not execute actions or automatically become memory.
ReplayInspect 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.
SentinelFollow 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.
SymdexIndex 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.
Vault, policy & dashboardKeep 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.
FirekeepScopeRun 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 companion or dashboard.
Evals & patternsReview 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 local code intelligence

Symdex is installed and registered automatically with Firekeep. It parses your working tree locally with tree-sitter and gives supported agents focused codebase context through MCP.

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.

Local indexing does not mean model-local processing

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.

Targeted symbol benchmark

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.

LanguageReference projectSampled filesMean estimated-token reductionExact Git-source checks
PythonClick1782.01% lower30/30
JavaScriptExpress683.13% lower30/30
TypeScriptp-queue560.39% lower30/30
GoCobra1880.47% lower30/30
Rustclap3069.64% lower30/30
JavaGson3046.40% lower30/30
PHPGuzzle3021.74% lower30/30
Cjq2967.35% lower30/30
C#Humanizer300.55% lower30/30
RubyRack3032.95% lower30/30
KotlinMoshi3057.12% lower30/30
SwiftSwift Argument Parser3056.27% lower30/30
Balanced result12 projects28554.83% lower360/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. That exact-source check shows the requested code was preserved; it is not an answer-accuracy score. Results varied substantially: the median reduction was 78.42%, while 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 versus a whole-file baseline—not symbol discovery, ordinary range reads, complete agent tasks or whole-session use.

Mixed-task Click benchmark

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.

WorkloadUnique context comparisonsTotal context-token resultJudged accuracy: Symdex / raw
All questions2023.31% fewer4.42 / 4.45
Comprehension747.67% fewer4.62 / 4.67
Navigation739.75% fewer4.43 / 4.43
Modification625.30% more4.17 / 4.22

This older result is an in-sample observation, not proof of equal answer quality or a guarantee for other repositories. The accuracy difference was small, but the sample was not designed to establish statistical non-inferiority. Modification questions consumed more context because the tested builder combined raw files with structural analysis.

Working-state restore benchmark

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.

ScopeFull restoreDelta restoreToken reduction
26 real sessions, aggregate16,72510,07539.8% lower
The 7 sessions above 1,000 tokensnot recorded separatelynot recorded separately50.7% lower
Weakest single session9919830.8% lower
Strongest single session47015367.4% lower

This is a per-restore reduction, not a per-request one. A delta is only returned when an agent asks to restore its working state, which happens after a context compaction rather than on every turn. Read that before comparing this figure with any per-request cost.

The spread is wide and the mean hides it: per-session reductions ranged from 0.8% to 67.4%. The weak cases are structural rather than noise. Scratchpad entries are stored without per-entry timestamps, so a delta has nothing to filter on and 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 that does occur, 80% comes from filtering decision, progress and file entries and only 20% from omitting an unchanged plan.

These 26 sessions came from a single operator on a single machine, so the result is an in-sample observation rather than a prediction for another team's usage pattern. A separate check against a live deployment on 2026-08-01 reduced one session's restore from 12,122 to 4,977 characters — a character-level measurement of one session, reported here because it is a production observation rather than a simulation, not because one session establishes a rate.

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.

Requirements

Server

  • Linux host with Docker and Docker Compose v2
  • Git
  • 16 GB RAM recommended for the default stack
  • No open ports required — a default install binds to 127.0.0.1
Memory is the one that bites

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.

Client

  • macOS, Linux or Windows
  • Nothing preinstalled — the bootstrap fetches its own pinned toolchain
  • Installing from a source checkout instead needs a system python3 >= 3.10

Solo and Team

Firekeep has one client, one server and one capability set. The commercial boundary is people—not agents, devices or individual features.

Solo — freeTeam — coming soon
MembersOne natural personMultiple people under a seat entitlement
Agents and devicesUnlimited personal agents, terminals and devicesUnlimited per member
CapabilitiesComplete current productThe same product, shared by more people
License documentNone requiredSigned, workspace-bound entitlement
Personal mode is unrelated to Solo

firekeep personal temporarily makes Firekeep dormant for private work. It is a session state, not a pricing plan. Solo is the free one-member product edition.

Server installation

The public path provisions the same self-hosted server for Solo and Team. It does not ask you to choose a plan and does not require a registry account or license token.

  1. Install the Firekeep client kit on the Linux Docker host
    on the server
    $ curl -fsSL https://kapella-hub.github.io/firekeep-dist/latest/install.sh | sh

    The bootstrap brings its own pinned Python toolchain and verifies downloads before use.

  2. Provision the latest public server release
    on the server
    $ firekeep init

    It downloads and checksum-verifies a source-free deployment bundle, then pulls the public Firekeep images.

  3. Add your workstation

    On a remote server, first install the client kit on your workstation, then run firekeep connect user@server --remote-dir ~/.firekeep/server. The explicit directory matches the public install default. The command uses your existing SSH access to issue a single-use code, enroll this first device and open a reusable local tunnel. Visit http://127.0.0.1:8040/, enter the admin key printed by init, and use Dashboard → Devices → Add device for later workstations. Dashboard-issued join codes are single-use and valid for 24 hours.

Pinning and TLS deployment

Use firekeep init --version vX.Y.Z to install a specific published server release. firekeep init --office enables the bundled TLS reverse-proxy deployment. Neither flag changes the Solo/Team edition.

Only the four Firekeep service images are published. Neo4j, Redis, Qdrant and Ollama are pulled by your own Docker daemon from their upstream registries — Firekeep never redistributes them.

As a developer — build from source

From a checkout of the repository you have been granted access to:

source checkout
$ firekeep init --server-dir .

A source checkout builds the Firekeep services locally. Add --pull only when deliberately testing the published-image path.

What the installer does

  • Checks for Docker and Compose v2, installing Docker if absent
  • Prompts for host address and Neo4j password, writing a validated .env at mode 600
  • Generates a vault encryption key
  • Mints API keys and prints an admin key exactly once
  • Pulls public images or builds source images, then starts the complete stack
Save the admin key now

It is printed once and never stored. On a long-running server it simply does not exist any more, and that key is what administers devices and workspace membership. If you lose it, key minting must be done on the server itself, where a shell already implies total control.

Your first authenticated call

A fresh install is closed by default in two independent ways.

DefaultValueEffect
AUTH_ENABLEDtrueProtected API routes require a key
BIND_ADDR127.0.0.1Ports answer only on the host itself

Both are deliberate. A stock install used to publish six ports on every interface and treat every caller as an anonymous admin — enough to read the vault and mint keys.

on the server
# Pre-auth paths answer keyless — this is how you tell "up" from "gated" $ curl -fsS http://127.0.0.1:8100/health $ curl -fsS http://127.0.0.1:8100/version # A real route without a key → 401 $ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8100/memory/stats # ...and with one → 200 $ curl -fsS -H "X-API-Key: $KEY" http://127.0.0.1:8100/memory/stats
401 and "connection refused" are not faults

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.

Server configuration

Everything lives in .env beside the compose file. The settings that actually change behaviour:

VariableDefaultWhat it controls
BIND_ADDR127.0.0.1Which interface ports publish on. Widening this exposes the stack.
AUTH_ENABLEDtruePer-key auth and scopes on protected API surfaces.
IMAGE_TAGdevPublished version to pull. dev is never published.
EMBEDDING_MODELEmbedding model. Changing it requires re-embedding.
EMBEDDING_DIMVector width. Changing it requires a collection rebuild.
VAULT_KEYgeneratedEncrypts stored secrets at rest.
NEO4J_PASSWORDpromptedGraph credential. Embedded in the data volume.
Two settings you cannot change casually

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.

Client installation

One command on a bare machine. No system Python or Node required.

macOS / Linux
$ curl -fsSL https://kapella-hub.github.io/firekeep-dist/latest/install.sh | sh
Windows (PowerShell)
> irm https://kapella-hub.github.io/firekeep-dist/latest/install.ps1 | iex

What the bootstrap does

  1. Resolves the version and fetches that version's checksum manifest once.
  2. Verifies before use. Both a mirrored toolchain and the client wheel are checksum-verified against that manifest before either is executed. The wheel is fetched to a local file and installed by path — never by URL, which does no hash checking, and never by name.
  3. Installs the kit into ~/.firekeep with its own standalone Python.
  4. Renders every shipped adapter for Claude Code, Codex, Kiro and OpenCode.

Recommended device enrollment

On an existing server, open Dashboard → Devices → Add device and run the generated command. It supplies a single-use join code, so there are no profile, host, API-key, plan or runtime prompts. The client creates its credential locally, redeems the code once, writes the single server connection and runs firekeep doctor. Device credentials default to 90 days; doctor warns during the final 14 days, and a new join code rotates the device onto a fresh credential.

Already installed?

Copy the bare code from the dashboard and run firekeep join fk_join_….

From a source checkout

developer install
$ cd client && ./install # .\install.ps1 on Windows $ firekeep install --runtime claude # re-render one runtime

./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.

Connecting a device

A dashboard join code is the normal attachment path. The code identifies the server and enrollment ticket; the client chooses its own credential and stores one connection.

existing client kit
$ firekeep join fk_join_…
The credential never crosses the enrollment exchange

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.

SSH shortcut for operators

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:

operator shortcut
$ firekeep connect root@203.0.113.10 --remote-dir ~/.firekeep/server
Loopback is the default

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.

CLI reference

CommandWhat it does
firekeep initProvision or update a local/self-hosted Firekeep server
firekeep join <code>Enroll this machine through a single-use join code
firekeep installInstall from a source checkout, or re-render adapters in an installed kit
firekeep connect <target>Operator SSH shortcut that creates a join code, tunnel and verified connection
firekeep login <url>Reserved for hosted OAuth sign-in when a server supports it
firekeep doctorPreflight: health, versions, key ACLs, CA expiry, permissions
firekeep personal [on|off|status]Toggle personal mode — dormant, nothing recorded
firekeep updateUpdate the kit. --check reports only; --to pins or rolls back
firekeep night-shiftDistil queued sessions into memory and draft skills via a local model
firekeep versionPrint the client version

Start with doctor

When anything is wrong, this is the first command to run — it checks the whole chain rather than one link.

diagnostics
$ firekeep doctor

Day to day

The core MCP capabilities work through every shipped adapter. Lifecycle automation varies because each coding client exposes different hook surfaces.

Automation by client

ClientAutomatic surfaceCurrent boundary
Claude CodeThe 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.
KiroAgent-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.
OpenCodeA 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.
CodexMCP 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.

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.

What your agent calls directly

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:

AreaToolsUse
Memorymemory_recall / memory_learnFind prior evidence, then record a fix, decision or non-obvious outcome.
Skillsskill_recall / skill_createFind or author a reusable playbook; document-derived drafts stay out of recall until reviewed.
Knowledgecorpus_ingest / knowledge_ingest / knowledge_ingest_urlMake pasted content or a bounded public documentation crawl searchable; the Knowledge front door also queues reviewable procedure drafts.
Sessionsctx_start_session / ctx_update / ctx_get_shadow / ctx_resume_sessionPersist explicit working state across compression, interruption and crashes.
Relay leasesrelay_lease / relay_heartbeat / relay_releaseCoordinate ownership of a file or task with a renewable fenced lease.
Relay workrelay_task_post / relay_task_list / relay_task_updateCreate, assign and advance work that another agent identity can pick up.
Relay messagesrelay_post / relay_read / relay_send_dm / relay_get_dmPost to a catch-up channel or exchange pollable direct messages; relay_who_is_online reports best-effort presence.
Decision Boarddecision_board / decision_board_checkOpen a multi-question clarification board and wait for the human's submitted answers.
FirekeepScopescope_start / scope_ask / scope_post / scope_checkRun gating or asynchronous clarification screens through Relay and the dashboard.
Replayreplay_timeline / replay_inspect / replay_context_at / replay_narrowMove from a recorded timeline to event details, nearby context and likely contributors to a failure.
Sentinelsentinel_get_events / sentinel_get_health / sentinel_push_eventRead configured environment activity, check collector health or add a custom operational event.
Vaultvault_list / vault_retrieveDiscover metadata and explicitly retrieve an authorized secret without putting it in memory.
Vault administrationvault_store / vault_deleteCreate or irreversibly remove entries; these operations require an admin-scoped credential.
Evalseval_session / eval_summaryInspect trace-derived operational metrics for one completed session or recent sessions.
The habit that pays

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 dashboard

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.

Personal mode

An escape hatch that makes Firekeep dormant for work you do not want it to record.

any runtime
$ firekeep personal toggle # or: on | off | status

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.

How it clears

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.

Operations

Updating

server / client
$ firekeep init --version v0.1.0 # server: current release $ firekeep update # client: latest release $ firekeep update --check # report only $ firekeep update --to X.Y.Z # client: pin or roll back
Close your agent sessions before updating the client on Windows

The update rebuilds the kit's environment, and a running session holds MCP servers open from it. The installer names the holding processes and asks you to close them rather than failing with an unexplained access error. On macOS and Linux the running session keeps working and the new version applies to the next one.

What version am I running?

Every service answers /version without a key and without touching its dependencies, so it responds even when the things behind it are down.

on the server
$ curl -fsS http://127.0.0.1:8100/version

Health

default server directory
$ cd ~/.firekeep/server $ docker compose ps $ docker compose logs -f cortex-api $ docker stats --no-stream
Healthy is not the same as working

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.

Backups

Use the shipped deploy/backup.sh so Neo4j, Qdrant and Redis are quiesced before their files are copied. It archives the four base volumes together: Neo4j, Qdrant, Redis and Ollama. A partial or hot filesystem copy can look valid while containing inconsistent graph, vector or auth state.

from the server bundle directory
$ bash deploy/backup.sh ~/firekeep-backups # restore only with the stack stopped; the script asks for confirmation $ docker compose down $ bash deploy/restore.sh ~/firekeep-backups/firekeep-backup-…
The volume archive is not a complete recovery set

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. An office-mode deployment must also back up its caddy_data volume, which contains the internal CA private key. Restore those identities with the data; generating replacements can make the restored vault unreadable, invalidate clients or change workspace ownership.

Troubleshooting

Everything returns 401

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.

Connection refused from another machine

Also expected. BIND_ADDR=127.0.0.1 means the ports answer only on the host. Use the connection encoded by the dashboard join code, establish an SSH/private-network route, or run the operator shortcut firekeep connect user@host --remote-dir ~/.firekeep/server. Pointing a client at an unbound public address simply times out.

The dashboard says a service is unreachable

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.

Containers restart or get killed

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.

The agent does not see the tools

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.

Still stuck

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.