Skip to content
agent-shPublic

About

Local or shared agent memory in plain Markdown, with source-grounded retrieval and review.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

tacit

Memory for coding agents, with the evidence to keep it honest.

CI agnix Release License: Apache 2.0

A decision made in one session should survive into the next. Tacit keeps project decisions, past mistakes and machine facts in a git repository, then gives your agents a small set of facts matched to the repo and prompt.

Run a local store on your laptop, or share one across machines. Works with Claude Code, Codex, Hermes, Grok, pi, Muse and agy on Linux, macOS and Windows.

  • Files you own. One fact per Markdown file, with its source, scope and git history.
  • Context that fits. Local full-text search and small context blocks. Hooks avoid repeating facts within a session.
  • Recall after a compaction. tacit episode and the MCP tool tacit_episode find the ids, commands, paths and errors a session already had, redacted.
  • Decisions with proof. Your own words and recorded review decisions establish your rulings. Agents leave changes to those rulings for you.

Quick start

Install git 2.29+, then use a prebuilt release. Each archive includes the CLI, browser app and compatible scrump redactor. No Go or Rust build is needed. Model jobs need a supported agent CLI and its own provider setup. Search, owner edits and review work without a model account.

Linux or macOS

curl -fLsS https://github.com/agent-sh/tacit/releases/latest/download/install.sh -o tacit-install.sh
sh tacit-install.sh
export PATH="$HOME/.local/bin:$PATH"
tacit init
tacit app --browser

Windows

Invoke-WebRequest -UseBasicParsing https://github.com/agent-sh/tacit/releases/latest/download/install.ps1 -OutFile tacit-install.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\tacit-install.ps1
$env:PATH = "$env:LOCALAPPDATA\tacit\bin;$env:PATH"
tacit init
tacit app --browser

The installers select amd64 or arm64, verify the archive checksum and test the bundled redactor before replacing executables. They install into your account and leave PATH changes to you. For a specific release or another directory, use sh tacit-install.sh --version v0.1.0 --bin-dir PATH, or -Version v0.1.0 -BinDir PATH in PowerShell. Git and model CLIs remain separate dependencies. Source builds are also available.

init creates a local store. It needs no server, tailnet or enrollment keys. Open the app to add your own rulings, inspect facts and review changes. tacit review opens the same page: it is your channel for every edit, retirement, new rule and folder change in every build. Its link carries a one-run token; it goes to the browser the command opens and is printed only on a terminal, so an agent running the command sees no token and cannot drive the page.

Choose the integration for your agent:

Agent Install Connection
Claude Code tacit install claude Session-start, prompt, pre-tool and pre-compact hooks, and the MCP tools (--no-mcp: hooks only)
Codex tacit install codex The same hooks; trust them once in /hooks
Hermes tacit install hermes Memory provider; follow the printed configuration steps
Grok / pi / Muse tacit install grok / pi / muse Prints the MCP configuration
agy tacit install agy Prints the MCP registration command
Tacit showing scoped facts, their source and git history in the browser app

The browser app, using the public example store. Screenshot setup.

One note, from a mistake to the next session

Record a failure and its fix. This example adds a sample note to your current local store:

tacit add --harness codex --kind observed --type past_mistake \
  --scope projects/demo-api --desc 'Run one database migration worker at a time' \
  --body 'Parallel migration workers contend for the database lock. Run one migration worker at a time.' migration-lock

tacit search --repo demo-api --inbox 'migration worker'
tacit app --browser

Open Inbox to inspect the note and its source. After curation, installed integrations can retrieve the reviewed fact in later sessions. search --inbox lets you inspect the note immediately. The codex source label records who wrote the note and does not require running a model for this example.

Portable setup covers dependencies, native jobs, build archives and platform validation. To exchange facts between machines, follow the shared-store setup.

How it works

Agents send notes to collect, and a dreamer reads their transcripts; collect writes both to a git store; curate turns them into facts there; deliver gives facts back at session start and per prompt; check and organize maintain the store. All of it runs in the local client; an optional shared server syncs stores between machines, and then one machine curates the shared store.
  1. Collect. Agents write short inbox notes. Imports bring in existing memory files. An optional dreamer extracts candidates from redacted transcript deltas: from the prompt hook once a session's undreamed part fills a dream window, before a compaction, every 10 minutes for the sessions that went quiet, and every 4 hours as a backstop. It saves each successful window before the next call and recovers pending notes after interrupted runs.
  2. Curate. Notes become individual facts with sources and scopes. Contradictions and uncertain changes become review items. A quick run after the idle dream curates the last day's notes, so a session's fact reaches other sessions within about an hour.
  3. Deliver. A local SQLite FTS5 index matches facts to the repo, host and prompt. Hooks supply up to 6 of a repo's facts (10 for a host outside a repo) at session start, again after a compaction, resume, clear or fork, and up to 5 curated facts per prompt, with a separate match for a computed fact. Explicit search can return the full text.
  4. Check. A verifier reads code, git, docs and permitted machine sources. It records evidence for its decisions and leaves unresolved questions for you; a question that went moot is closed, and an agent that can prove the answer to one closes it (tacit questions close), so you see only the ones no source settles. An answer you type in a session, under the question's own words, is your answer: an agent relays it (tacit questions close --proof words). A daily rotation sends the facts unchecked longest back to the curator's model with the proof code gathers, stamps each last_checked, and retires, redirects, notes or compresses only what the proof shows; it asks you about your own facts instead of changing them.
  5. Organize. Every project folder has a record that code checks: what it is (a repository, a folder, an area of ongoing work, a bounded topic), its status and its history, decided by the curator's model on evidence from git and sessions, or by you on the Folders page. A folder suppressed into another moves its facts there. Dead and shipped folders go quiet in the hooks and stay searchable. An area's facts arrive before its tools are used, a topic's when the prompt names it, and each folder can carry an overview whose every line cites its facts.

Git also supplies hot spots, module maps, committed measurements and deletion-based staleness checks. Those steps need no model. The app brings facts, sources, history and review decisions together.

New local stores require evidence for owner rulings. Existing and server-created stores switch to that definition with the ruling audit.

The methods guide explains the ranker, curation, ruling proof and verification. The store contract defines the file format and write rules.

Architecture

The Go client holds the git store and search index locally. Hooks and MCP read from that local copy. Model jobs run through your selected agent CLI on the machine you configure for them. The dreamer, curator, conflict judge and verifier can each use a different runner.

For shared stores, a small Elixir server adds git transport, signed writer identities and a change feed. Writers add notes to their own inboxes; the curator writes the rest of the store. Clients fetch changes and rebuild their local indexes. The server holds no model credentials.

Configuration

Keep operator settings in an untracked file. The repository ignores config/local.yaml; config/example.yaml contains generic values:

cp config/example.yaml config/local.yaml
chmod 600 config/local.yaml
export TACIT_SETTINGS="$PWD/config/local.yaml"
tacit init

Or use tacit --config /absolute/path/config/local.yaml <command>. On Windows, copy the example with Copy-Item and set $env:TACIT_SETTINGS to its absolute path. An explicit config selection is carried into installed hooks, MCP commands and jobs.

Without an override, Tacit reads ~/.config/tacit/config.yaml on Linux/macOS or %APPDATA%\tacit\config.yaml on Windows. A user-config symlink can point to the ignored repository file so it loads from any working directory. Relative paths resolve against the actual settings file, including a symlink's target. A dangling config link is an error. Tacit loads only the selected file; it does not search other project checkouts for settings.

Precedence: command flags, then environment values (including a job's --env-file), then YAML, then generic defaults. Unknown fields and missing explicitly selected files fail before model work. Hooks with bad settings fail open without output. Store provider credentials in the selected CLI or the job env file.

Which facts reach each prompt (optional)

By default a lexical score decides which matching facts a prompt sees, with no model call, and that is what we recommend: in live agent sessions a model selector did no better (eval/VALUE.md, "The prompt selector in live sessions"). Optionally a model judges each candidate: does it add something useful for this request, beyond topic overlap? Of the models we measured for that, Jev (TypeSafe, hosted) was the most accurate and fastest. To keep data in your AWS account, Amazon Nova Micro on Bedrock never picked a wrong fact in our runs, but it kept fewer useful ones. Any System One-compatible server, Bedrock model or OpenAI-compatible endpoint can be plugged in:

utility:
  provider: jev            # or: bedrock, systemone, openai
  key_file: ~/.config/tacit/typesafe.env

Code still decides scope and limits first, and a failed or slow model falls back to the lexical selection. Setup for every provider, the thresholds and the full benchmark: Choosing what each prompt sees.

Client settings

Every YAML option is listed here:

Option Environment equivalent Meaning / default
store TACIT_STORE Git store; ~/.local/share/tacit/store
projects TACIT_PROJECTS Checkouts root; ~/projects
index TACIT_INDEX Local search index; ~/.local/state/tacit/index
keys TACIT_CONFIG Writer-key directory; ~/.config/tacit
local_overlay TACIT_LOCAL Local notes for a read-only clone; ~/.local/share/tacit/local
local_layer TACIT_LOCAL_LAYER on: a read-only clone dreams and curates its own sessions into its local overlay, which never leaves the machine; off (default)
owner_names TACIT_OWNER_NAMES Owner name aliases; YAML list, comma-separated environment value
memory_md TACIT_MEMORY_MD on (default): the curator's writes generate the flat MEMORY.md as before; off: they stop, and the next write removes the store's copy (tacit index too). For clients from before the folder indexes (_index.md); turn it off only once every client runs a version that reads them. The setting, and MEMORY.md, will be dropped then
hermes_db TACIT_HERMES_DB Hermes session store the dreamer and the owner's words read; ~/.hermes/state.db when it exists, off for none
delivery.repo_start TACIT_DELIVERY_REPO_START on (default): in a repo the SessionStart block is the repo's own rules and standards, then decisions and past mistakes; off: the release 0.7.1 block
delivery.repo_aliases TACIT_DELIVERY_REPO_ALIASES on (default): a checkout also answers to every remote's repository name in its git config and its root manifest's package name
delivery.prompt_metadata TACIT_DELIVERY_PROMPT_METADATA on (default): the prompt block adds the repo's fact whose applies_to paths or commands the prompt names
delivery.prompt_action TACIT_DELIVERY_PROMPT_ACTION on (default): the prompt block adds the repo's best rule or decision for the request when it has none
delivery.instruction TACIT_DELIVERY_INSTRUCTION on (default): the SessionStart title and the MCP server's instructions say what tacit holds and ask for one search before an action that changes something (the server's also point to tacit_tree); off: neither, and the server has no instructions
delivery.tool_push TACIT_DELIVERY_TOOL_PUSH on (default): the PreToolUse hook gives the one matching rule or decision before an edit or a shell command
delivery.tree_pointer TACIT_DELIVERY_TREE_POINTER on (default): when the SessionStart repo block shows fewer of the repo's facts than it has, its last line gives their count and the tree call that lists them
(environment only) TACIT_DELIVERY_AREA_PUSH on (default): before an MCP tool call or shell command an area's tool patterns or commands match, the PreToolUse hook gives a few of the area's rules and decisions, once a session, in a repo or not
(environment only) TACIT_DELIVERY_AREA_CEILING Most lines of one area push; default 3
(environment only) TACIT_DELIVERY_TOPICS on (default): a prompt that names a live topic searches its folder too
(environment only) TACIT_DELIVERY_WORKSPACE on (default): a session started in a folder that is in no repository but holds several (a workspace whose packages are each a checkout under src/, a folder of checkouts) reads all of them; at most 8 repositories, never home or above
(environment only) TACIT_DELIVERY_PROMPT_REPO_RANK on (default): at the prompt the session's repositories' rules and decisions weigh TACIT_DELIVERY_PROMPT_REPO_BOOST (1.5) times their score, another project's facts 1/TACIT_DELIVERY_PROMPT_OTHER_PENALTY (1.5); TACIT_DELIVERY_PROMPT_PENALIZE_MACHINES=on penalizes this machine's facts too
(environment only) TACIT_ROTATION_MAX Facts one rotation run checks; default 0, every fact that is due
(environment only) TACIT_ROTATION_AGE_DAYS Days a checked fact rests before the rotation checks it again; default 30
(environment only) TACIT_FORGE off to check no repository name on the forge; by default the checks ask GitHub through gh when it is installed and logged in (SPEC.md, Checked claims)
(environment only) TACIT_OVERVIEW_MAX, TACIT_OVERVIEW_CHANGE_PCT Overviews one curate writes (default 10), and the share of a folder's facts that must change for a new one (default 20)
delivery.start_ceiling TACIT_DELIVERY_START_CEILING Most lines of the SessionStart repo block; default 6
delivery.prompt_ceiling TACIT_DELIVERY_PROMPT_CEILING Most curated lines of the prompt block above its floor; default 5
delivery.prompt_relative TACIT_DELIVERY_PROMPT_RELATIVE A prompt line also needs this share of the best line's score; default 0.7, 0 for none
delivery.meta_ceiling TACIT_DELIVERY_META_CEILING Most metadata lines per prompt and per tool call; default 1
delivery.log TACIT_DELIVERY_LOG on (default): each hook block, with what its gates left out, is a line of this machine's private delivery log (delivery/ in the state directory, mode 0600, never sent; a request's terms the store's index holds, never its text; SPEC.md, Delivery log)
delivery.log_days TACIT_DELIVERY_LOG_DAYS Days of the delivery log kept; default 30
delivery.titles TACIT_DELIVERY_TITLES on (default): in a harness with tacit's MCP server (tacit install claude), the start, prompt and shell-command push blocks print an agent's note as a title (name, whose, type) the agent opens with tacit_fact; the owner's rules, rulings, statements and the notes holding their words or confirmed by them stay whole; off prints whole lines everywhere (SPEC.md, Titles)
(environment only) TACIT_DELIVERY_MARK_RATE Share of prompt blocks that ask the agent to mark which lines helped (tacit_mark); default 0.05, 0 for none (SPEC.md, Self-marks)
(environment only) TACIT_DELIVERY_JUDGE on (default): at the end of a full dream run, a model judges a sample of the delivered lines with hindsight (relevant, confused, novel) through claude -p on the dreamer's Bedrock route (Bedrock itself, or a Bedrock endpoint at a loopback address of the machine with the auth skipped), skipped where there is none; off for none (SPEC.md, The dreamer's judge)
(environment only) TACIT_DELIVERY_JUDGE_DAILY Lines judged a day at most; default 36
(environment only) TACIT_DELIVERY_JUDGE_MODEL The judge's model for claude -p; default global.anthropic.claude-fable-5-2
verify_roots TACIT_VERIFY_ROOTS Extra permitted source directories; YAML list, PATH separator in environment; every directory must exist
runner TACIT_RUNNER Default CLI for all model jobs; claude
runners TACIT_<ROLE>_RUNNER Per-role CLI overrides
models TACIT_<ROLE>_MODEL Per-role model IDs accepted by the CLI; Claude alias opus for dream, curate, judge and verify
models.verify_fallback TACIT_VERIFY_FALLBACK_MODEL Legacy same-runner verifier fallback; an empty environment value disables it
efforts TACIT_<ROLE>_EFFORT Per-role reasoning effort; omitted uses the CLI default, empty clears an override
profiles TACIT_<ROLE>_PROFILE Per-role Codex profile name; empty clears it
dream_max_runtime TACIT_DREAM_MAX_RUNTIME Extraction batch runtime; default 45m, 0 disables the batch limit; dream --max-runtime wins
dream_agent_windows TACIT_DREAM_AGENT_WINDOWS Dream windows with no turn of the owner's: all (default), recent:<days> or none; an owner window whose agent content is not taken is cut to the owner's turns with 12 lines around each; dream --agent-windows wins (SPEC.md "Owner windows and agent windows")
stale_workers TACIT_STALE_WORKERS Facts the stale step checks at once, each with its own git commands; default 4; set 1 on a busy machine; stale --workers wins
timeouts TACIT_<ROLE>_TIMEOUT Positive Go duration per model attempt, such as 10m; default 20m
commands TACIT_<TOOL>_COMMAND Executable name or path; default is the tool name
runner_args TACIT_<TOOL>_ARGS Extra argv without a shell; YAML list or JSON array in the environment
fallbacks TACIT_<ROLE>_FALLBACK One fallback route per role; JSON object in environment, null disables it

<ROLE> is curate, judge, dream or verify (uppercase in environment names). <TOOL> is claude, codex, hermes, grok, pi, muse or agy. An explicit non-Claude runner uses its own model when no model is set. Per-role effort/profile options take precedence over general runner arguments. Accepted effort values are none, minimal, low, medium, high, xhigh, max and ultra, subject to the selected CLI/model. Effort adapters exist for Claude, Codex, Grok, Muse and pi; use runner_args for other tools.

A fallback route has these fields:

Field Meaning
runner Required supported CLI name
model Model ID; omitted uses that CLI's default
effort Optional reasoning effort
profile Optional Codex profile name

The generic verifier fallback is Claude sonnet; other roles have none. An explicit runner or model selection disables that generic fallback unless one is configured. An explicit TACIT_<ROLE>_FALLBACK route wins over the legacy TACIT_<ROLE>_FALLBACK_MODEL override. Fallbacks run once for provider capacity, temporary service failures, expired authentication, a missing runner or an attempt deadline. Provider status and error codes decide whether to retry. They never start another fallback. Refusals, access denial and malformed output stop the job.

For example, users can choose different runners without publishing their settings:

runner: claude
runners:
  dream: muse
models:
  dream: your-model-id
commands:
  muse: ./bin/muse
fallbacks:
  dream:
    runner: claude
    model: haiku

Check a setup without sending model requests:

tacit doctor
tacit doctor --models
tacit doctor --role dream --json

doctor checks Git 2.29+, scrump's text masking canaries (a scrump before 0.2.0, which leaves a quoted value a cut left open, fails) and its records mode (--records, scrump 0.2.0 and later; without it a warning, since batched texts then go joined by a boundary; a malformed answer fails), effective role arguments, attempt timeouts and Codex profiles. It checks primary and fallback executables with --version. Missing runners are warnings for a memory-only installation. --models requires every configured runner; --role requires only that role and its fallback. --json prints check records. Exit 0 means the requested offline checks passed, 1 means a check failed, and 2 means invalid command options or settings. Provider credentials, model availability and live completions need a separate live test. Grok preflight also checks the provider settings and native file references needed by its isolated runtime.

Malformed extraction or incomplete judge answers leave the batch pending. Every conflict verdict is validated before any fact is retired. A fresh installation can curate observations without Claude or Codex owner history. Unbacked owner notes stay pending; owner rulings still require proof.

Grok jobs use a fresh runtime home for every request. Provider/model settings come from GROK_HOME (default ~/.grok); native sign-in and requirements files are referenced without copying credentials. User hooks, plugins, memory and MCP servers stay outside the job. Managed defaults and mandatory policy hooks are retained. Provider keys and headers in copied settings must use environment references or native auth. On Windows, file references use hard links when symlinks are unavailable; put the job cache and Grok home on the same filesystem in that case.

Local job logs record each model attempt's role, route, fallback status, input tokens and reported cost. A batch reaching its runtime or call limit pauses successfully and resumes pending windows next run. Attempt deadlines and genuine model, redaction or persistence errors still fail. Accounting records pause_reason and remaining_windows.

A null cost means the runner did not report it; zero means a reported zero. Summaries label incomplete totals as reported cost. Logs contain no prompts or model answers in these accounting records.

~ expands to the current home directory. Windows paths can use forward slashes or single-quoted YAML strings. Command paths containing a directory separator resolve against the config file; bare command names use PATH. A CLI --model option overrides the configured model. tacit --runner TOOL overrides all role runners for that invocation.

Other environment settings

Variable Meaning / default
TACIT_SETTINGS Select the YAML file; same as --config FILE
TACIT_FOLLOW_STATE Follower heartbeat file; ~/.local/state/tacit/follow.json
TACIT_DERIVE_CONFIG Separate derive YAML; ~/.config/tacit/derive.yaml
TACIT_WRITER Writer identity used to sign a shared-store push
TACIT_SERVER Server URL for scripts/mac-setup.sh
TACIT_ENROLL_SSH SSH enrollment target for scripts/mac-setup.sh
TACIT_REPO Code checkout used by scripts/mac-setup.sh; script's checkout by default
TACIT_BIN Hermes integration executable override; installer-captured path by default
TACIT_MODEL_JOB Internal recursion guard; Tacit sets it for model subprocesses

The separate derive file accepts branches (repo-to-branch map) and ordinary_names (repo names that need explicit evidence because they are common words). Command-specific options, including job --env-file, are in the client reference. Provider variables belong to the selected CLI and can be supplied through the private job env file.

Optional server environment

The server reads its own settings at startup:

Variable Meaning / default
TACIT_DATA State root; $XDG_STATE_HOME/tacit-server or ~/.local/state/tacit-server
TACIT_BIND Bind IP; tailnet IPv4 when available, otherwise 127.0.0.1
TACIT_PORT Git/API port; 7447
TACIT_TAILSCALED Tailscale LocalAPI socket; /var/run/tailscale/tailscaled.sock
TACIT_WHOIS Identity lookup; localapi, or static:<ip>=<login>,... for tests
TACIT_ALLOW_LOOPBACK 1 permits loopback in the tailnet check; testing only
TACIT_PUBLIC_PORT Optional reader-only listener on 127.0.0.1; disabled when unset

For background work, tacit install dream (the 4-hour dreamer and the 10-minute idle job) and tacit install curate write native job files and print start commands. Select the private config and provide the job environment before starting them. See portable job setup.

Upgrading a shared store to folder records

Folder records, areas/ and topics/, overviews and last_checked form store format 1. A binary from before it reads such a store wrong, so nothing writes them until the store holds the format marker. Install the new binary on every machine that reads the store first (tacit doctor shows each machine's format and the marker), then set the marker once with tacit format --set. The assessment, migration, overviews and rotation start with the next curate and maintain runs. The rotation checks every fact that is due unless TACIT_ROTATION_MAX is set; its cost per fact is logged in rotation.jsonl in the state directory (measured in eval/VALUE.md).

What we measured

The initial evaluation uses one owner's private store and Claude Code/Codex sessions. Results cover that workload; the original data is private. The scripts and methods are available to run on your own data.

Those measurements shaped the client: lexical retrieval beat the dense variants tested, splitting notes into individual facts improved delivery, and larger context blocks cost more without helping. The verifier remains limited: in the held-out sample it agreed with the owner on a minority of findings and missed most of the owner's retirements. Human review remains part of the method.

Methods and decisions · Grep baseline · Run the synthetic sample

The synthetic sample runs without a server or model account. It demonstrates the formats and scoring. Long-session outcomes and delivery in other harnesses have not been measured.

Recall from a session's own transcript

Characters brought into context per task, by transcript size from 1 to 64 MiB: tacit episode brings 550 at 1 MiB and 3.7K at 64 MiB, grep's matching lines 3.4K and 36K.

At 64 MiB, tacit episode brings a median of 3.7K characters into context per task. grep prints whole transcript lines and brings 36K. Each task's matching events include one with a fake secret. Every grep output carried one. None reached tacit's output: scrump masked the ones it printed, and the rest lay outside what it printed. tacit found the right value in all 112 tasks, grep in 111 (the misses). Both counts assume the whole output reaches the agent, with no harness cap on tool output. Synthetic sessions, 16 tasks per size: python3 -I eval/recall/bench.py.

Time per task, by transcript size from 1 to 64 MiB: tacit episode takes 617 ms at 1 MiB and 1.0 s at 64 MiB, grep 1.9 ms and 33 ms.

grep is faster: 1.9 ms per task at 1 MiB and 33 ms at 64 MiB, where tacit takes 617 ms and 1.0 s. Most of a small call's time is scrump loading its rules, which tacit starts before it reads the transcript. Times are from one machine; same run and command.

The numbers: median (min to max) of 16 tasks; a task's time is the median of 5 launches
MiB Arm Right Characters Planted secrets Calls Time
1 tacit 16 of 16 550 (386 to 11,190) 0 (0 to 0) 1 (1 to 3) 617 ms (567 ms to 1.7 s)
1 grep 16 of 16 3,416 (452 to 19,677) 1 (1 to 2) 1 (1 to 1) 1.9 ms (1.5 ms to 3.8 ms)
2 tacit 16 of 16 756 (388 to 9,474) 0 (0 to 0) 1 (1 to 3) 629 ms (528 ms to 1.7 s)
2 grep 16 of 16 9,876 (454 to 25,798) 2 (1 to 3) 1 (1 to 1) 2.4 ms (2.1 ms to 3.6 ms)
4 tacit 16 of 16 848 (459 to 12,720) 0 (0 to 0) 1 (1 to 4) 648 ms (553 ms to 2.2 s)
4 grep 16 of 16 7,131 (914 to 31,968) 2 (1 to 2) 1 (1 to 1) 3.8 ms (3.1 ms to 5.2 ms)
8 tacit 16 of 16 858 (459 to 16,723) 0 (0 to 0) 1 (1 to 4) 593 ms (531 ms to 2.4 s)
8 grep 16 of 16 10,400 (2,561 to 25,115) 1 (1 to 2) 1 (1 to 1) 5.6 ms (4.9 ms to 7.8 ms)
16 tacit 16 of 16 849 (461 to 18,937) 0 (0 to 0) 1 (1 to 4) 612 ms (544 ms to 2.3 s)
16 grep 16 of 16 12,636 (2,557 to 27,297) 1 (1 to 2) 1 (1 to 1) 11 ms (9.8 ms to 14 ms)
32 tacit 16 of 16 4,231 (509 to 17,692) 0 (0 to 0) 1.5 (1 to 5) 822 ms (499 ms to 2.6 s)
32 grep 16 of 16 25,626 (2,520 to 74,165) 2 (1 to 2) 1 (1 to 1) 19 ms (16 ms to 27 ms)
64 tacit 16 of 16 3,688 (465 to 30,474) 0 (0 to 0) 1.5 (1 to 10) 1.0 s (689 ms to 5.8 s)
64 grep 15 of 16 35,838 (2,597 to 384,925) 2 (1 to 2) 1 (1 to 1) 33 ms (32 ms to 46 ms)

Security model

Agent writes and model digests pass through scrump before storage or a model call. A failed redaction stops the write. Local commits and shared pushes also check for known token shapes.

Local mode uses your OS account for access. Shared mode adds tailnet identity, signed keys and per-writer inbox enforcement. An optional public listener accepts signed readers only.

Model jobs send redacted digests and fact excerpts to the provider configured in the selected CLI. The verifier can read permitted source files. Choose the provider with that access in mind.

Security policy and private reporting · Shared-store details

Documentation

Guide Covers
Local and portable setup Configuration, dependencies, native jobs and validation
Shared-store setup Server deployment, keys, machine roles and job configuration
Client reference Commands, flags, hooks and the app
Methods How facts are collected, delivered and checked
Choosing what each prompt sees The optional model selector: Jev, Bedrock, any System One or OpenAI-compatible model, and the benchmark
Evaluation Scripts, samples and how to measure another store
Contributing Development, tests and pull requests

Agent configurations are checked in CI with agnix, including the hooks and MCP settings generated by the client.

License

Apache 2.0. Bundled fonts use the SIL Open Font License 1.1; see NOTICE.

About

Local or shared agent memory in plain Markdown, with source-grounded retrieval and review.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages