
Kronicle Lite
io.github.rafe-walker由 GitHub 账号 rafe-walker 发布v0.8.0更新于 Nov 3, 2026
带签名回执的哈希链式本地文档存储,以及用于过期智能体记忆的orient协议
AI 翻译由 AI 模型根据下方的原文描述翻译,可能有误。
原文描述
Hash-chained local document store with signed receipts and an orient protocol for stale agent memory
概览
Kronicle Lite 的本地 MCP 服务;无需登录;STDIO。
暂无 AI 概览:以下信息来自注册中心条目和服务本身。
安装
在 SourceWeft 中
- 打开 控制台中的 Kronicle Lite,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
kronicle-lite
A local-first MCP server that tells your agent when its notes went stale.
Agents write notes, runbooks, decisions. Then the world moves: a block gets rewritten, a decision gets reversed, a procedure gets retired. Nothing in a plain memory store tells the agent. It keeps reasoning from the thing it read three sessions ago, confidently.
kronicle-lite is a small SQLite-backed document store where:
- every write is an event on a hash chain you can verify from a public
genesis with
sha256sum; - every
recall()hit comes with a signed receipt that later answers "is this still the current version?" —VERIFIED,SUPERSEDED(here is the new one),TOMBSTONED, orUNVERIFIED; get_system_stategives the agent an orient call: pass your last cursor, get exactly what changed since, a drift banner when you have been away too long, and a retraction list of things you may have relied on that are now wrong;- every hit carries an honest label —
can_act,inspect_onlyornever_act, with the reason — and an empty answer says what was searched, what was not, and whether the index was fresh. Secrets are refused before they reach the append-only chain.
It is one process, one file, no accounts. It runs over stdio next to Claude Code, Cursor, Claude Desktop, Codex, GitHub Copilot or any MCP client, and over loopback Streamable HTTP for clients that cannot spawn a process.
See it in one command
No LLM, no network, a temp dir that is removed afterwards. A runbook goes
in; an agent orients and reads "Deploys go to the staging cluster
stg-west-2 first."; someone changes it to stg-east-1; the agent's next
orient says, before it acts:
Then someone edits the SQLite file by hand: recall withholds the edited
text, the old receipt verifies UNVERIFIED (content_tampered),
verify-chain exits 1, rebuild restores the text from the chain. A put
holding an API key is refused before anything is chained, an empty recall
answers absent_in_searched with the scopes it did not search, and an edit
to the chain itself is caught at its seq.
0.6.0 — honest labels. Every
recallhit carriesauthority: can_act | inspect_only | never_actwith a reason; only block-level evidence (the block's exact text found, now, in its recorded source file) reachescan_act; superseded, tombstoned, withheld and drifted text never does.absence {searched, not_searched, index_fresh, verdict}separates "searched, found nothing" from "not searched", and a stale or cold index never certifies "not found". Hits you already read this session rank lower (never hidden). Secrets (API keys, tokens, private keys, connection strings) are refused on put / import / watch, or stored redacted on request; served text is scrubbed again at read time.serve --coreserves six tools;recallcaps content with a "read the whole document" pointer. Rules:docs/HONESTY.md. All additive: no hash, receipt, cursor or event layout changed.
0.5.0 closes the gaps an adoption audit found: what the agent reads is now checked against the chain, not only the log (
recall,verify,verify-chain,doctor,rebuild); instruction files are keyed by project, so two repositories sharing a data dir no longer retract each other's rules; retractions carry the old and new words;tools/listis 71% smaller;serve --httpalso serves 2025-era clients such as Cursor. Details in CHANGELOG.
0.3.0 speaks MCP 2026-07-28 (TypeScript SDK v2). Every tool has an
outputSchemaand returnsstructuredContent;tools/listandserver/discovercarry cache hints; results carryresultType. The stdio server and (since 0.5.0)serve --httpare dual-era: a client that still opens with the 2025-erainitializehandshake (2025-11-25, 2025-06-18, 2025-03-26) is served too.
0.4.0 adds off-box anchoring (
checkpoint --push,verify --remote), chained instructions (watch, retractions of kindinstruction), git-aware blocks (bind_git,STALE_SOURCE) andkronicle-lite doctor. All additive: 0.3.0 chains verify byte-for-byte.
kronicle-lite is not a memory server. It sits beside one. Keep using whatever you use for knowledge graphs or semantic recall; point kronicle-lite at the notes whose staleness would hurt.
Install
Requires Node ≥ 20.
Claude Code
Optional: copy skills/orient/ to .claude/skills/orient/ and add the
wake contract from examples/.claude/CLAUDE.md to your CLAUDE.md (it
includes "pulse before every world-changing command"). Then typing orient
re-grounds the agent against the chain. To push changes that land while the
agent works, add a PostToolUse hook on kronicle-lite orient --cursor C --focus retractions --json (docs/PUSH.md).
To gate world-changing commands on changes the agent has not re-read yet,
add a PreToolUse hook on kronicle-lite pending --actor <agent> --json
and block while pending_count > 0 (docs/PUSH.md "Pending"). For a check
at the moment git push / terraform apply / kubectl apply actually
runs, in any client, see exec-time pulse shims.
Notes the agent writes after reading something are linked to what it read;
when a source changes, the note is served never_act / stale_derived
(docs/HONESTY.md §6).
Cursor
Cursor reads .cursor/mcp.json (project) or ~/.cursor/mcp.json
(global) and interpolates ${workspaceFolder}, ${userHome} and
${env:NAME} in command, args, env, url and headers:
This uses the default store (~/.kronicle-lite, shared with your other
clients; documents are scoped per project since 0.5.0), which is also the
one the exec-time shims check. To keep a store per
workspace instead, add "--data-dir", "${workspaceFolder}/.kronicle-lite":
the shims (0.8.1) find a project-local .kronicle-lite/ by walking up from
the repository a command acts on, but when ~/.kronicle-lite holds a store
too they cannot tell which one the agent uses and refuse world-changing
commands until you pin one (kronicle-lite shim install --data-dir DIR).
For the HTTP mode below use { "url": "http://127.0.0.1:7417/mcp", "headers": { "Authorization": "Bearer ${env:KRONICLE_LITE_BEARER}" } }
instead of command/args. Since 0.5.0 a 2025-era HTTP client such as
Cursor's is served (statelessly); before, it was refused.
Source:
Cursor Docs — Model Context Protocol.
Claude Desktop
claude_desktop_config.json:
Codex
~/.codex/config.toml (or .codex/config.toml in a trusted project):
Codex reads the server instructions at startup and uses the first 512
characters as server-wide guidance; kronicle-lite's instructions are the
orient loop and fit in that window. Per OpenAI's docs the same file also
takes enabled_tools / disabled_tools, startup_timeout_sec (default
10) and tool_timeout_sec (default 60). Source:
OpenAI — Model Context Protocol.
GitHub Copilot (coding agent + code review)
Repository Settings → Copilot → MCP servers (under "Code, planning, and automation"); the configuration is shared by the Copilot coding agent and Copilot code review:
The store lives in the checkout (./.kronicle-lite): exec-time shims
installed in the same environment find it by walking up from the
repository (0.8.1), or pin it with kronicle-lite shim install --data-dir "$PWD/.kronicle-lite".
tools is required; GitHub recommends allowlisting read-only tools because
the agent calls them without asking. The six above are the ones
kronicle-lite marks readOnlyHint: true, which is also the set Copilot code
review will use (it ignores tools without that annotation). Add
put_document, supersede_block, tombstone_block (or "*") if the
coding agent should write. Secrets must be named COPILOT_MCP_* and
referenced from env. Source:
GitHub Docs — Extending Copilot coding agent with MCP.
More in examples/.
Streamable HTTP: serve --http
For a client that cannot spawn a process (or several clients sharing one store on the same box):
- Auth. Every request must carry
Authorization: Bearer <token>. By default the token lives in<data dir>/http-bearer.token, generated on first run with mode0600; print it withcat ~/.kronicle-lite/http-bearer.token. - Loopback. Binds
127.0.0.1;HostandOriginare validated against loopback (DNS-rebinding defence).--host 0.0.0.0 --allow-host myhost.lan --allow-origin myhost.lanopens it up; put TLS in front. - Stateless, both eras. No session id,
GET/DELETEanswer405. A 2026-07-28 request carries its protocol version in_metaand theMCP-Protocol-Versionheader; a 2025-era client that opens withinitialize(Cursor, most clients today) is served by a fresh server instance per request (0.5.0).--modern-onlyrefuses those withUnsupportedProtocolVersionError(-32022), as 0.4.0 did. - Trust domain. Single tenant: the token is the whole store. See
docs/THREAT-MODEL.md.
Sixty-second tour
Works as-is in an empty directory after npm install -g kronicle-lite
(data goes to ~/.kronicle-lite; add --data-dir DIR to keep it apart):
In an agent session the loop is: get_system_state → work → recall (keep
the receipts) → verify before building on an old receipt → write with your
cursor → get_system_state again next turn with the new cursor.
Anchor off-box (0.4.0)
kronicle-lite is free and local. Anchoring adds one flag —
checkpoint --push — and a URL anyone can check. The local key proves the
rows still match what the box signed; it cannot prove anything against the
box owner, who holds the key. An anchor service countersigns your signed
Merkle root with its own key and a received_at time, so a later rewrite of
an anchored range is detectable even when it was re-signed locally.
- What leaves the box: the root, range, signature and your public key. Never events or content. Details in FORMAT §9 and THREAT-MODEL.
- MCP:
checkpoint_chain {push: true}returns the anchor outcome next to the local checkpoint;anchor_status(read-only) compares the local chain with the last anchor (match | diverged | beyond_head | gap | unverified),remote: truealso asks the service. Once something was anchored,get_system_stateadds one banner line:anchored N events ago (status); before that it says nothing about anchoring, anddoctoronly probes the service when a license key or URL is configured. - The service. The default,
https://anchor.isokron.ai, is deployed with a Free tier. When it cannot be reached,--pushstores the checkpoint locally and exits 2 withanchor service unreachable at …;verify --remoteexits 2 the same way; every local command, the MCP server andorientbehave exactly as without anchoring. - What the client trusts (0.8.1). Only countersigned receipts: every
comparison uses the root and range inside a receipt whose countersignature
verifies against a pinned service key and whose checkpoint signature
verifies against your own chain key — never the unsigned fields of the
service's listing or the local
anchors.rootcolumn. The first online push orverify --remotepins the service key it is served (<data-dir>/anchor-keys.pinned.json, 0600); later keys are accepted only with a successor signature from a pinned key or byanchor keys add. Receipts you hold are checked even when the service stops listing them.http://URLs are refused unless the host is loopback or you pass--insecure-http; preferKRONICLE_ANCHOR_KEY/config.jsonover--key(which warns: argv is visible to other users). - Exit codes: 0 ok, 1 divergence, conflict or an untrusted receipt, 2 usage
or I/O (incl. unreachable and a refused
http://URL).
Chained instructions (0.4.0)
Your agent's instructions are notes too, and they go stale the same way:
someone edits CLAUDE.md, a rule file is rewritten, Claude Code's auto
memory index changes. kronicle-lite can chain them, so a changed instruction
is a supersession and the next get_system_state lists it as a
retraction of kind instruction, in words (You previously relied on instruction "Use pnpm, not npm." (instructions/acme-api-1a2b3c4d/claude-md › Project); current truth is "Use bun, not npm." …). A deleted file
retires its blocks (severity safety).
Default set, relative to the git worktree root (or the working directory).
Since 0.5.0 every slug carries a project key, <repo dir name>-<8 hex of the root path's sha256>, so one data dir can serve many repositories:
syncing repo B's CLAUDE.md never touches repo A's, and an agent orienting
in A is not shown B's instruction changes (all_projects: true /
--all-projects shows them). KRONICLE_LITE_PROJECT=<name> fixes the key.
Upgrading from 0.4.0: the first sync of a file whose un-keyed document
(instructions/claude-md) still holds exactly that file's text renames the
document in place (a document.renamed event): same blocks, receipts keep
verifying, no retraction. An un-keyed document holding some other text (in
a shared data dir it may be another project's) is left alone.
Auto memory lives at ~/.claude/projects/<project>/memory/MEMORY.md, where
<project> is the git repository's main worktree root (shared by all
worktrees and subdirectories; outside git, the working directory) with every
non-alphanumeric character replaced by -. CLAUDE_CONFIG_DIR,
CLAUDE_CODE_PROJECT_DIR_NAME and autoMemoryDirectory are honoured as
Claude Code documents them
(memory,
sessions).
kronicle-lite watch --list prints what it resolved.
Unchanged files append nothing. watch uses fs.watch on the containing
directories with a debounce (150 ms; --debounce) plus a polling pass
(--interval, default 2000 ms) that also discovers new rule files;
--poll uses polling only.
A file moved inside the project with its content intact is a rename,
not a removal: the document follows it (document.renamed, same blocks and
receipts, no retraction), whichever of the two paths is synced first. Edits
that are format-only — the same raw text up to line endings, trailing
whitespace, reflow inside a paragraph and blank lines (not inside code,
quotes or link targets) — are chained like any other but reported under
format_only_edits, not as retractions. Every other change is a retraction
with its diff: a changed character, quote, date, case or hyphen, a
double space or tab inside a line, an emphasis or list marker (*↔_, 1)↔1., renumbering: agents copy raw
text into commands), a paragraph moved to another section, and blocks
reordered within a section. A typo-shaped one carries hint: likely_typo, a label only.
Inside Claude Code: hooks, not a watcher. Claude Code already watches
files: a SessionStart hook can return watchPaths, and a FileChanged
hook runs whenever one of them changes on disk, whoever wrote it
(hooks: FileChanged).
put --from-instructions --stdin-hook is both hooks: on SessionStart it
syncs the set and answers with its watchPaths; on FileChanged it re-puts
the one file and posts a one-line systemMessage when something changed. It
never fails the hook. This is the shape of cc-anchor's watchPaths /
FileChanged hook; with a cc-anchor that does not ship it yet, or without
cc-anchor, add it to .claude/settings.json:
The FileChanged group has no matcher on purpose: it then runs for every
path in the dynamic watch list. Install kronicle-lite globally for hooks
(npx adds seconds per call) and pass the same --data-dir your MCP server
uses. Everywhere else — Cursor, Codex, Copilot, a plain editor — run
kronicle-lite watch in a terminal or as a user service.
Git-aware blocks (0.4.0)
A document put from a file in a git repository can remember which blob it came from, so "the runbook says X" gets checked against the runbook file as it is now, not only against the store:
Over MCP: put_document {slug, title, markdown, source_path, bind_git: true}.
When the working-tree file changes (or is deleted), verify on a receipt
for that document returns STALE_SOURCE and audit_assumptions grades
claims about it stale_source, each with a diff stat (+3 −1) and the
bound vs working blob; get_system_state lists the document under a
Source drift heading. Re-put with --bind-git to rebind. It only uses
git rev-parse / git hash-object / git cat-file; outside a repository
(or without git) the put succeeds with a warning and nothing is bound.
kronicle-lite doctor (0.4.0)
Read-only: it never creates the data dir or writes a key, config or schema.
Checks: Node version (≥ 20); data dir and key-file modes (0700 dir,
0600 keys — a group/world-readable signing key, cursor secret, bearer
token or license-bearing config.json fails); PRAGMA integrity_check;
chain links and hashes over the last 1000 events plus every checkpoint;
the stored documents, revisions and blocks replayed from the chain and
re-hashed (0.5.0; a mismatch fails, rebuild repairs it once the chain
verifies); FTS5 index vs blocks; the MCP catalog this build serves vs the
fingerprint pinned for this version; config.json sanity; the last anchor
vs the local root (fails on divergence); anchor service reachability
(warning only, and only when anchoring is configured); which MCP clients have kronicle-lite configured
(~/.claude.json user and local scopes, .mcp.json, .cursor/mcp.json,
~/.cursor/mcp.json, ~/.codex/config.toml — read, never written) and with
which --data-dir. On Windows it adds a note that the POSIX modes are
no-ops there, with an icacls line to lock the data dir down.
Exec-time pulse shims
A push hook only reaches clients that have hooks, and a check made before a
Bash call misses a runbook change that lands while build && deploy runs,
or a deploy hidden in make release, bash -c "$CMD" or a wrapper script.
Shims check at the moment the real binary is executed, for any client
(Claude Code, Cursor, Codex, Hermes, a human in a terminal):
Each shim is a small POSIX sh wrapper (plus .cmd/.ps1 on Windows). A
read-only invocation (git status, terraform plan, kubectl get) execs
the real binary at once with shell builtins only, ~1 ms overhead and no
node start. A world-changing one (git push, terraform apply,
kubectl apply|delete|patch|replace|rollout …, helm install|upgrade|uninstall,
npm|pnpm|yarn publish, npm run deploy, plus your own --world "make release,docker push")
first runs kronicle-lite pulse (~0.2 s): when a document changed since
the last check and whoever read it has not re-read the current version, it
is refused with the diff (exit 77):
The gate is version-bound, like pending: once the agent recalls the
runbook again (or reads kronicle://docs/runbook) and gets the current
version, the same command runs, no acknowledgement needed. Who has to
re-read: shim install --pending-actor <agent>, else the invoking actor
(KRONICLE_LITE_ACTOR in the agent's environment), else (or with
--all-readers) everyone who read the changed block. The project is the
one the command acts on (git -C, --git-dir, terraform -chdir=, …).
kronicle-lite shim ack --through SEQ is an operator override: it needs
a terminal or --operator, is logged, and the refusal never mentions it.
The PATH shim only sees commands found through PATH; shim install --git-hook adds a git pre-push hook that checks every push (absolute
paths, sudo, aliases, hooks, rebase -x; --no-verify aside).
--mode warn prints the same and runs the command. A store that fails its
integrity check refuses world-changing commands in both modes (fail
closed), and so does a store file that is damaged (0.8.1). The shims check
the store the server uses: shim install --data-dir DIR pins it; else
$KRONICLE_LITE_DATA_DIR or ~/.kronicle-lite, plus a project-local
.kronicle-lite/ above the repository (0.8.1). No store, or two different
ones, refuses world-changing commands in deny mode; a missing kronicle-lite
CLI or a crash lets them run (fail open, noted once on stderr, logged in
.kronicle-shim/shim.log). A check that times out
(KRONICLE_SHIM_TIMEOUT, default 10 s) prints kronicle-lite check TIMED OUT … was NOT checked on every occurrence and runs the command, or refuses
it with exit 77 under shim install --on-timeout deny. Every world-changing
call's check time and outcome go to shim.log. Matching rules,
recursion guard, reconciliation, per-project acknowledgement and client snippets:
docs/PUSH.md § Shims.
Tools
Every write tool accepts an optional cursor and returns the new chain head
plus a stale_write_advisory (advisory only; the stale-write check never
blocks; the secret guard does). The kronicle://docs/{slug} resource serves
a document's current revision.
serve --core (0.6.0) serves only get_system_state,
audit_assumptions, recall, verify, put_document and
supersede_block, for small context windows: tools/list is 10.5 KB
instead of 14.2 KB. Its catalog is pinned separately
(.mcp-catalog/kronicle-lite-core.json).
Honest labels (0.6.0)
Full rule table and invariants: docs/HONESTY.md.
Secrets are refused, not tombstoned (0.6.0)
The chain is append-only and every byte of a put is hashed into it. A
tombstone hides a block from recall; it does not remove the secret from the
events table, from export, or from any backup, and deleting it would break
verification by design. So put_document, supersede_block,
tombstone_block, kronicle-lite put, put --from-instructions, watch
and import scan for common secret shapes (provider API keys and tokens,
private keys, JWTs, scheme://user:password@ connection strings, bearer
headers, …_PASSWORD= / …_TOKEN= assignments) before anything is
chained, and refuse with secret_detected naming the detector and line
(never the secret). Overrides: redact_secrets: true / --redact-secrets
chains a copy with [REDACTED:<detector>] in place of each match;
import --allow-secrets imports verbatim (chained bytes cannot be redacted
without breaking their hashes). An independent read-time ruleset masks
anything that got in anyway (pre-0.6.0 data, --allow-secrets) in recall,
orient, audit_assumptions and the document resource.
Every tool declares an outputSchema and returns the same JSON as
structuredContent and as a text block (get_system_state renders Markdown
in the text block by default; response_format: "json" makes the text the
JSON too). Since 0.5.0 tools/list advertises compact output schemas (every
top-level field with its type, enum and required; nested shapes as bare
types) and short descriptions: 12.4 KB instead of 43.2 KB (13.6 KB in 0.6.0 with the honest-label fields). Results are
still validated against the full schemas, which the
kronicle://schemas/tools resource serves; the orient skill carries the
longer guidance. The emitted catalog is pinned in
.mcp-catalog/kronicle-lite.json and CI
fails on byte drift (npm run catalog:check), because a changed description
or schema silently invalidates every client's prompt-cache prefix.
Full hash recipes and payload shapes: docs/FORMAT.md.
What the local signature does and does not prove:
docs/THREAT-MODEL.md.
How it compares
Four axes that matter for "agent reasons from stale notes". As documented by each project at time of writing; corrections welcome.
The honest summary: the first three are memory stores and do their job; none of them answer "has what I read changed?". InALign hash-chains what an agent did; kronicle-lite hash-chains what an agent knows and signs what it was told.
Guarantees, briefly
- The chain verifies from a public genesis (
sha256("kronicle-lite-genesis-v1")). No secret is needed to check it. - What the agent reads is checked against the chain, not just the log:
recall,verifyand the document resource re-hash the stored text (BLAKE3) against the event that created it and refuse a mismatch;verify-chainanddoctorre-derive the whole store from the chain. - Receipts bind
(block_id, content_hash, doc_slug, revision)to(chain_seq, chain_head_hash). A store reset or rewrite under the agent makes old receiptsUNVERIFIED, not silentlyVERIFIED. - The signing key is local. This proves integrity against accidents and unprivileged edits; it is not third-party notarization. Read the threat model before relying on it for anything adversarial.
- Orienting never fails on a bad cursor; the server recovers position from the flight recorder and says so.
- (0.6.0)
can_actcomes only from block-level evidence; an emptyrecallnever claims "not found" from a stale or cold index; a briefing that hid a scope says it is partial.
Development
See CONTRIBUTING.md (DCO sign-off required) and
ROADMAP.md for what is deliberately not here yet: inclusion
proofs against published anchor day roots, chain-backed tickets, semantic
recall.
The anchor acceptance tests run against an in-test stub of the service. To
run them against the real isokron-anchor Worker under Miniflare as well,
point KRONICLE_ANCHOR_WORKER_DIR at a checkout with its dependencies
installed: KRONICLE_ANCHOR_WORKER_DIR=../isokron-anchor npx vitest run test/anchor.test.ts.
Beyond one agent
kronicle-lite is one actor, one process, one trust domain, on purpose. IsoKron is the platform growing out of the same ideas — a typed graph shared by many agents, claim fencing so parallel agents don't collide, and per-tenant chains. It is in development and not self-serve; https://isokron.ai explains what exists today and what doesn't.
License
Apache-2.0. See LICENSE and NOTICE.
Built off-grid in Cochise County, AZ by a laid-off support engineer — https://theexiledentrepreneur.com
来源:README.md,提交 2c746ba
工具
0版本历史
4- v0.8.0最新Nov 3, 2026
- v0.7.0Nov 1, 2026
- v0.5.0Nov 1, 2026
- v0.3.0Nov 1, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分