npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

wendkeep

v0.90.0

Published

Vault-first persistent memory for AI coding agents, with an optional profile-aware governance runtime: OFF, FLOW, GUIDE, GOVERN, or ASSURE. Local-first and agent-agnostic (Claude Code, Codex, Cursor…).

Readme

wendkeep

Português · English

Your AI coding agent forgets every session. wendkeep makes it remember — in the Obsidian vault you already use.

npm test zero deps node

wendkeep — persistent memory for AI coding agents, shown as a knowledge graph of sessions, decisions, bugs, learnings and changes

In the graph: 🔵 session · 🟣 decision · 🔴 bug · 🟢 learning · 🟡 change — every note, backlinked.

Persistent memory for AI coding agents, built on your Obsidian vault. Every Claude Code and Codex session is captured turn by turn into local Markdown — init wires both (Codex asks you to approve its hooks once; import backfills past sessions either way) — with token/cost tracking and automatically extracted decisions, bugs, and learnings. That always-on plane is Keep Core. On top of it, Wend Runtime provides a native, zero-dependency lifecycle (spec → change → TDD → sensor-gated archive), selected through the OFF, FLOW, GUIDE, GOVERN, and ASSURE Operating Profiles. 100% local, open-core.

When projecting sessions, trailing internal metadata is removed only from assistant responses; user reports remain intact. XML-like tags are written as escaped text so Obsidian Reading view does not interpret them as HTML.

The runtime is separated into thirteen physical boundaries — cli, commit, contracts, evidence, harness, integrations, mcp, migrations, observer, pi, sync, vault, and worktrees — without fragmenting installation. The root package publishes exactly wendkeep/commit, wendkeep/contracts, wendkeep/evidence, wendkeep/harness, wendkeep/mcp, wendkeep/migrations, wendkeep/observer, wendkeep/sync, wendkeep/vault, and wendkeep/worktrees. CLI, Pi, and Integrations remain private, and no @wendkeep/* workspace is an independent package. Historical facades preserve identity throughout 0.x. See the modular architecture, compatibility, migrations, and support policy.

In the 0.66 Integrations Kernel phase, packages/integrations/src/ becomes the canonical authority for the hook catalog and projection, the envelope/provider, transcript content and usage filters and parsers, and session identity. These rules are pure: stdin/stdout, environment, filesystem, Vault, and registry effects remain in the historical facades. MCP and Integrations are sibling adapters with no dependency between them, and the direction remains cli/mcp/integrations/pi → Harness → Vault. Hooks, sessions, paths, configuration, and schemas remain equivalent; the private @wendkeep/integrations workspace stays inside the single published wendkeep package without a public subpath. Consumers use the supported historical facades, while deep packages/ imports remain blocked.

The native MCP workspace now serves semantic project, context, memory, change, spec, task, handoff, evidence, and Observer tools through wendkeep mcp serve. A versioned, verified catalog declares every effect/capability; known reads skip the mutation gate, while writes require a capability, session, active context, lease, and reason. Stable schemas, pagination, byte budgets, timeouts, cancellation, redaction, and payload-free local audit bound the surface. init preserves the .mcp.json merge while invoking the installed package through npx --no-install wendkeep mcp serve—with no dynamic @latest dependency or arbitrary filesystem access. Stdio may start outside a bound project; without --vault, each call resolves and audits only its declared project_root. The workspace remains private inside the single wendkeep package.

In the 0.64 CLI Runtime phase, packages/cli/src/index.mjs owns help, version reporting, Vault selection, error presentation, and lazy dispatch. bin/wendkeep.mjs is reduced to the shebang and a runCli() invocation. The tarball remains a single artifact and proves both aliases in an isolated consumer; there is no public wendkeep/cli subpath in this phase.

In the 0.63 Harness FLOW Store phase, packages/vault/src/locale.mjs becomes the canonical source for Vault locale and taxonomy, while packages/harness/src/flow-store.mjs becomes the canonical durable FLOW store. The historical hooks/locale.mjs and hooks/vault-runtime-store.mjs facades preserve export identity. Harness depends only on Vault's public index — never the reverse — with no migration of paths, schemas, or locks; the tarball remains a single artifact published by the root wendkeep package. Under multiprocess contention, transient release of the public lock and its owner/lease metadata is revalidated with a bounded budget/deadline, including final cleanup; junctions, reparse points, dangling locks, and non-transient errors are still rejected before any write.

npm i -D wendkeep && npx wendkeep init      # captures from the next session on
npx wendkeep import                          # backfill past Claude + Codex sessions

▶ Interactive demo: docs/index.html — a self-contained page with the live knowledge‑graph hero. It lives in the GitHub repo (the npm tarball ships only the runtime), so clone or download docs/ to open it locally or serve it on any static host. The image above is a static render of it.

From one real production vault (npx wendkeep stats): 308 sessions · 1,696 prompts · $4,836 captured across 46 active days (Jan–Jul 2026) · 15 models — every one a note in the graph.

Extracted from a system in daily production use: the capture engine, cost tracking and graph wiring are battle‑tested; the cross‑platform installer (wendkeep init) and the native change loop are the newer parts. See docs/ for the project's strategy and decision log.


The problem: the context dies when the window closes

Decisions, dead ends, the reason you chose X over Y — gone next session. The pieces to fix that exist but are scattered (qmd‑sessions, memsearch, Nexus, hand‑written hooks). wendkeep ships local capture plus an optional Docker Observer that keeps complete memory browsable without depending on Obsidian.

| | | |---|---| | Capture — every turn, on disk | SessionStart / Stop hooks write each session to a dated Markdown note: prompts, iterations, files touched, wikilinks. | | Derive — decisions, bugs, learnings | Pulled from the transcript into their own notes, backlinked to the session. Your history becomes navigable, not archival. | | Recall — injected back | Canonical CORE + operational SHARED_MEMORY enter on startup, /clear, and /compact; on every prompt, the local chunk index selects a few passages with source, authority, and validity under an explicit budget. | | Cost — what it all cost | Per‑model, cache‑aware token pricing per session — plus cost --trend with a run‑rate projection across the whole vault; research previews without a final rate remain unestimated. | | Multi‑agent — one vault, both agents | init wires the session hooks into .claude/settings.json and .codex/hooks.json, and every note is tagged with the agent that wrote it: Claude Code is detected from its environment, anything else is recorded as Codex. One shared graph, whichever agent you are in. | | Local‑first — no cloud, no account | Everything is plain Markdown on your disk. The native MCP queries local semantic state and gates writes by capability/context/lease. | | Local Observer — many projects, one view | wendkeep observer keeps documents, FTS5 chunks, sessions, agents, tokens, costs, calls, and transcripts in SQLite. Identities and foreign keys are project-scoped; each event is atomic. Hooks publish only what changed; idempotent gzip batches retry transient socket resets once; observer reconcile --url ignores the incremental cursor to regenerate the complete projection while preserving local/remote revision baselines. |

During historical migration, the Observer preserves differences between frontmatter totals and the ledger as explicit reconciliation rows, and disambiguates duplicate session_id values per file without inventing calls.

Requirements

The Codex scope guard treats commit, push, pull, merge, publish, and destructive operations as independent capabilities, including inside compound commands.

  • Node.js ≥ 18
  • An AI coding agent with hooks. init wires Claude Code and Codex automatically — Codex gets twelve compatible hooks, including per-prompt recall and the scoped PreToolUse guard, and enumerates them untrusted, so approve its “Hooks need review” prompt once at startup (see Notes & roadmap)
  • Obsidian (to view the graph) — optional but the point

Install & set up

# in your project
npm install --save-dev wendkeep   # or: npm install -g wendkeep
npx wendkeep init

wendkeep init is interactive and idempotent. It will:

  1. Create the vault folder taxonomy and a templated README.md (default vault: <project>/.<project-name>-vault, e.g. .MyApp-vault; override with --vault).

  2. Write a provider-neutral .wendkeep.json binding at the project root and a matching .brain/PROJECT.json marker in the vault, then merge the session hooks into .claude/settings.json. The binding is provider-neutral by design: any agent resolves the same vault from its session cwd, with no machine-global environment variable. Older registrations already in .claude/settings.json are adopted automatically.

  3. Wire the Codex hooks in .codex/hooks.json — twelve compatible entries: brain-inject + session-start + observer-publish on SessionStart, session-ensure + evidence-context + change-context on UserPromptSubmit, session-stop + observer-publish + change-nag on Stop, subagent-stop + observer-publish on SubagentStop, and change-guard on PreToolUse for Bash, exec_command, apply_patch, and mutable MCP tools, always in the npx wendkeep hook <name> form. For the Observer, SessionStart only drains the outbox, Stop enqueues the changed session, and SubagentStop enqueues only the affected transcript; full scanning is explicit through observer reconcile. When the host omits work_session_id, session-start and session-ensure derive it from the canonical session_id, preserving an explicit handoff and the already registered value first. The guard accepts object, raw-string, and argv Codex payloads; before a mutation it compares the session with the project, Git root, remote, branch, and worktree, denying missing or divergent targets. A raw git checkout/switch branch transition is denied before it can strand the session; use wendkeep context switch <branch> [--create], which moves Git and the causal scope together in the same worktree with an audited revision and rollback. If a divergence is already quarantined, context status --session <id> inventories sanitized reserved/observed candidates; context recover --session <id> --select <reserved|observed> --revision <n> --reason <text> requires an explicit choice, CAS, and current-checkout proof, failing closed before clearing the conflict if revalidation changes. doctor diagnoses orphaned active contexts, removed worktrees, and expired request-stop leases without writing; context repair --key <key> --revision <n> --reason <text> --session <id> revalidates under lock, closes only the ownerless/removed context or expires only its lease, while preserving the record and all historical memory. The change lifecycle uses active_contexts, identified by repository_id + worktree_id + work_session_id; two matching sessions fail with ambiguity instead of selecting silently, CURRENT_CHANGE.md is only a derived projection for one unambiguous context, and migration never invents a worktree or session identity. The other four stay out because Codex offers no equivalent payload, tool, or event: change-warn (no reliable tool_input.file_path), plan-capture (no ExitPlanMode), decision-capture (AskUserQuestion is Claude-only), and task-log (TaskCompleted is not in Codex's event enum). Codex scope blocks use permissionDecision: "deny"; ask is never emitted in PreToolUse. The merge remains non-destructive, preserves third-party hooks, and migrates legacy timeout to timeoutSec. Codex enumerates every hook as untrusted and runs none until you approve the “Hooks need review” prompt at startup — init cannot pre-approve them. Once active_contexts is initialized, brain-inject and change-context mark only the causal context's change as current; the backlog remains global, and an empty or ambiguous store never revives CURRENT_CHANGE.md.

  4. Add the native semantic wendkeep-vault MCP server to .mcp.json. It offers bounded reads and capability-gated writes without arbitrary filesystem access or an @latest download. Skip with --no-mcp. (--no-mcp skips only wendkeep's own MCP; companion MCPs still follow --companions.)

  5. Offer to pin companion plugins/MCP (multi-choice; none pre-checked — wendkeep is a neutral harness and presumes no third-party plugin). Each is wired the most agent-agnostic way it supports:

    • context-mode — context optimizer + FTS5 memory, wired as a Claude Code plugin. It ships its own MCP server, so wendkeep deliberately adds no .mcp.json entry (registering both cold-started two servers at once). On non-Claude agents, add the MCP by hand: npx -y context-mode.
    • understand-anything — project domain graph, via a understand-inject SessionStart hook that injects the graph when generated.
    • caveman — token-compression mode; runs its own cross-agent installer on non-Claude agents.
    • dotcontextlegacy, not recommended, and hidden from the picker. wendkeep's native a2 loop (change / verify / gate) already does its job, so installing it duplicates the harness. Reachable only via an explicit --companions dotcontext for anyone already invested (tune with --dotcontext-mcp / --dotcontext-hooks).

    Control with --companions <csv> or --no-companions. The Claude Code plugin layer (extraKnownMarketplaces + enabledPlugins) is wired as a bonus where the companion has one.

  6. Install a color system into the vault's .obsidian/: a CSS snippet that accents notes by type (session/decision/bug/learning, via the cssclasses the hooks emit) plus graph color groups by folder. Non-destructive merge into appearance.json/graph.json; skip with --no-colors. Re-apply it any time on an existing vault with wendkeep theme sync — Obsidian owns graph.json and can drop the color groups (a grey graph); the re-sync restores them without a full re-init.

  7. Seed Shared Project Memory v2 without overwriting existing artifacts: .brain/CORE.md, .brain/SHARED_MEMORY.md, .brain/MEMORY_EVENTS.jsonl, .brain/MEMORY_CANDIDATES.jsonl, and .brain/COMPACTION_PROTOCOL.md. The durable outbox appears under .brain/memory-outbox/; EVIDENCE_INDEX.jsonl is rebuilt locally from chunks while DIGEST.md/index.jsonl remain compatible. Everything stays in the vault.

  8. Seed the definitions + skills layer: .brain/agents/ + .brain/skills/ (versioned source of truth), including the native process skills wk-workflow / wk-tdd / wk-debugging / wk-brainstorming / wk-planning / wk-verify (some ship templates — e.g. wk-verify's verdict-template.json + reviewer prompt). init runs wendkeep sync-defs for you, delivering the skills to .claude/skills/ and .agents/skills/, and the agent definitions (.brain/agents/*.toml) to .codex/agents/, plus a managed section in AGENTS.md that indexes the skills for Codex; sync-defs --check detects stale copies (re-run sync-defs after editing .brain).

  9. Seed the change/spec lifecycle: the 07-Specs/ + 08-Mudanças/ folders and a native wendkeep.sensors.json — critical memory validation/health sensors plus one for each of typecheck / test / lint / build found in your package.json. memory-health blocks delivery on corruption or projection divergence; semantic conflicts degrade only the affected keys and await curation. Pending outbox events and ordinary candidates are warnings. Add sensors with wendkeep sensors add. Drives wendkeep change / wendkeep verify — see Change lifecycle below.

npx wendkeep init --vault "~/vaults/work" --project . --yes   # non-interactive (no companions unless you ask)
npx wendkeep init --companions "context-mode,understand-anything" --yes
npx wendkeep init --no-companions --no-mcp --yes              # zero companions, no wendkeep MCP

init options

| Flag | What it does | |---|---| | --vault <path> | Vault folder. Default <project>/.<project-name>-vault; interactive init asks. Point it at an existing vault to install into it. | | --project <path> | Project root to wire (default: current directory). | | --locale <pt-BR\|en> | Vault language — folder names, scaffold, skills. Interactive init asks; locked at init. | | --companions <csv> | Companions to pin: context-mode,caveman,understand-anything (default: none — opt in explicitly; dotcontext is legacy). | | --no-companions | Pin no companions. | | --no-mcp | Skip wendkeep's own vault MCP (wendkeep-vault). Companion MCPs still follow --companions. | | --no-colors | Skip the Obsidian color system (.obsidian snippet + graph groups). | | --vscode-worktree-tasks | Create a local, Git-excluded .vscode/tasks.json for creating/listing/opening/finishing worktrees; never overwrites an existing file. Also accepted by sync. | | --git-commit-hooks | Opt in to copying commit hooks into .githooks/ and setting local core.hooksPath; custom hooks are preserved without --force. | | --yes, -y | Non-interactive; accept defaults (skips the language / vault / companion prompts). | | --force | Overwrite existing wendkeep config blocks. |

Then open the vault in Obsidian, send a test prompt in your agent, and confirm a note appears under 02-Sessões/… (or 02-Sessions/… for an en vault).

Project isolation

Each project owns a .wendkeep.json containing a stable projectId and its vault path. Relative paths (for example .NutriGymBrain) are resolved from the project root; absolute paths are also supported. Hooks search upward from the agent's cwd, so nested packages use the nearest binding. The vault carries the same identity in .brain/PROJECT.json; a mismatch is rejected before any session is written. If no binding exists, hooks fail closed and never create the historical ~/wendkeep-vault fallback. In linked worktrees, profile use and profile status resolve the main worktree's canonical binding through the shared Git registry; the persistent selection applies project-wide without rewriting the current worktree's versioned .wendkeep.json.

OBSIDIAN_VAULT_PATH remains only as legacy/manual CLI compatibility. It is not used to route automatic Codex or Claude hooks and a project-local binding overrides an inherited machine value.

Updating

The hooks live inside the installed package, so upgrading means installing the new version and re-wiring the project. sync does the three steps (initsync-defsdoctor) in one command:

npm install --save-dev wendkeep@latest && npx --no-install wendkeep sync --project . --yes

sync lets its own init stage validate or rebuild the binding before resolving the Vault for later stages. An invalid .wendkeep.json stops at init without falling back to an inherited global Vault.

The install stays outside sync on purpose: a running process cannot replace itself and keep going — the code in memory would still be the old one.

In WendKeep's own development checkout, do not install wendkeep in devDependencies. Use node ./bin/wendkeep.mjs sync --project . --yes: the installer recognizes the self-checkout and keeps hooks on the working tree without duplicating consumer npx commands.

In a pnpm monorepo the install command differs (npm in a pnpm repo fails with Cannot read properties of null (reading 'matches')). Resolve the published version first and reuse exactly the value returned:

$version = pnpm view wendkeep version
pnpm add -D -w "wendkeep@$version" --config.minimumReleaseAge=0
pnpm install --update-checksums --config.minimumReleaseAge=0
pnpm exec wendkeep sync --project . --yes

Do not ask pnpm for wendkeep@latest. pnpm 11 ignores packages published in the last 24h by default (minimumReleaseAge, a supply-chain guard) — and it does not complain: it installs the previous version, exits 0, and the only hint is a quiet (X.Y.Z is available) in the output. You end up on the old version thinking you upgraded. Check with pnpm exec wendkeep --version.

Do not edit only the version or integrity in pnpm-lock.yaml. pnpm add and pnpm install --update-checksums must recalculate the complete entry. If the lock is already inconsistent and ERR_PNPM_TARBALL_INTEGRITY appears, prune the local store and repeat:

pnpm store prune
pnpm install --update-checksums --config.minimumReleaseAge=0

After installing, record the exception in pnpm-workspace.yamlpnpm does not write that line for you:

minimumReleaseAgeExclude:
  - wendkeep@<the version returned by pnpm view>

Without it, CI's pnpm install fails with ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION until the version turns 24h old.

Restart Codex and Claude Code afterwards — the generated skills are read at startup.

sync reseeds the wk-* skills from the installed version's seeds. That is not an extra: they are package artifacts, and merely copying .brain/skills would propagate the previous version's content while stamping the new version into the metadata — doctor would stop reporting defs stale without a single skill having been updated. If you hand-edited a wk-*, that edit is overwritten; your own customisation belongs in a skill of your own, which the reseed never touches.

Features by group

The README is the map; the guides provide syntax, options, exit codes, examples, and diagnosis.

| Group | Use it for | Detailed guide | |---|---|---| | Installation and updates | init, sync, companions, and the first project↔vault binding | Installation and first use | | Managed worktrees | worktree create/list/status/open/finish/cleanup/remove/prune, merge proof, preflight, crash-safe cleanup/common gate, and receipts | Managed worktrees | | Active context | active_contexts by repository_id/worktree_id/work_session_id, causal transition, quarantine, and explicit recovery | Active context | | Portable state | portable status/export/import/diff, authored/runtime boundary, redaction, and the active-work snapshot | Portable state | | Local-first sync | sync status/push/pull/conflicts/resolve, revision/CAS, outbox, leases, and explicit conflicts | Sync protocol | | Native MCP | semantic tools, effects/capabilities, stdio, schemas, pagination, budgets, audit, and client configuration | Native MCP | | Evidence recall and embeddings | cursor/byte budgets, bounded lexical/FTS sidecars, and an optional local plugin contract that is off by default | Optional embedding plugin | | Host capabilities | versioned lifecycle/effect matrix, degraded mode, human waivers, and evidence/Observer coverage | Host capabilities | | Ecosystem bridges | optional Spec Kit/Superpowers adapters, canonical baseline, single ownership, drift, and Git/CI/Envelope proof with an index/worktree-identical manifest | Ecosystem bridges | | Operating profiles | profile, flow, always-on Keep Core, and Wend Runtime governance | Operating profiles | | Changes and verification | change, specs, sensors, TDD, evidence, Task Contracts, and archive | Changes and verification | | Shared memory | CORE, SHARED, status, validation, repair, and curation | Memory | | Sessions and import | causal hooks, observability reconciliation, and Claude/Codex backfill | Sessions and import | | Notes and knowledge | BUG/APR/ADR, repairs, renumbering, lessons, and dashboard | Notes and knowledge | | Costs and observability | safe dry-run, tri-state, aggregation, trends, and historical rebuild | Costs and observability | | Maintenance and diagnostics | doctor, frontier/manifest freshness, drift, version, and help | Maintenance and diagnostics | | Evidence-based commits | wendkeep commit, canonically ordered derived tasks, tests only from execution bound to the exact SHA, opt-in Git hooks, privacy, and remote range gate | Commits | | Local Observer | observer serve, scoped/expiring hash-only bootstrap, incremental publishing with canonical timestamps, reconcile, policy, stable structural identities, content-bound hashes, deletion-safe capture, required encryption, retention, purge, and multi-project index | Local Observer · Security |

Operations that deserve step-by-step guidance: verify and exits 0/1/2, causal TDD attestation, legacy-memory migration, and safe retroactive import.

Operating Profiles — Keep Core is always active

Keep Core is always active: the Vault, sessions, identity, CORE/SHARED, lessons, costs, and persistence do not turn off with the harness. Wend Runtime controls only the automatic governance layer. Even under OFF, explicit WendKeep commands remain available; invoking one is a deliberate opt-in and runs that command's own validations:

| Profile | Route | Use | |---|---|---| | OFF | LLM-native harness | No Wend router, skill gate, or gates; explicit selection only. | | FLOW | E → V | Microcontract with Git baseline, allowlist, sensor, and receipt, without a change. | | GUIDE | P → E → V | Compact change; no automatic design/spec/ADR when contract impact is none. | | GOVERN | P → R → E → V | Current a2 loop and compatible fallback. | | ASSURE | P → R → E → V → C | Governance with confirmation and handoff. |

A route is a sequence of work stages, not a list of command names:

  • P = Plan/Propose — understand the request, bound the scope, and record the approach when a change is needed.
  • R = Review — inspect the proposal/design before execution; this is the formal a2-loop review.
  • E = Execute — edit the permitted code or artifacts.
  • V = Validate — run tests, sensors, and checks and record evidence.
  • C = Confirm/hand off — obtain explicit confirmation and complete the handoff.

Thus, P → R → E → V means “plan/propose, review, execute, and validate”. FLOW starts at the execution/validation microcontract; OFF applies no automatic Wend route and returns process ownership to the native LLM harness.

Who selects the profile, and for how long?

The LLM harness (Codex, Claude, or another agent) classifies the current implementation and can record a temporary choice with wendkeep profile route. Wend Runtime does not interpret prompt text or use diff size, heuristics, or environment variables: it validates the choice, applies the route in hooks, and expires the lease when the request ends. With no recorded route, the configured base profile remains effective.

Resolution follows this order:

  1. a valid lease for the current request in SESSION_REGISTRY.json;
  2. a persistent session override in that registry;
  3. harness.profile in the project's .wendkeep.json;
  4. GOVERN when no valid setting exists.

Without --session, profile use changes the project default for conversations/hooks that do not have a session override. With --session <id>, it changes only that session and leaves the project default untouched. Therefore, profile use OFF without --session is not an isolated test: it writes the project binding and can be shared if .wendkeep.json is committed.

profile route is different: it requires --session and --reason, accepts only FLOW, GUIDE, GOVERN, or ASSURE, does not rewrite the project/persistent override, and applies only to the current causal prompt. An accepted Stop consumes the lease; if the process dies first, the next prompt advances the sequence and makes the old lease ineffective. OFF is never selected automatically.

npx wendkeep profile status
npx wendkeep profile use GUIDE                 # project default
npx wendkeep profile use FLOW --session <id>   # one session only
npx wendkeep profile route FLOW --session <id> --reason "local fix"  # current request
npx wendkeep profile status --session <id>     # session-effective profile

In human status --session output, base=<profile>/<source> and lease=<state> accompany the effective profile; --json exposes the same data as base_profile, base_source, and task_lease. profile route only accepts a session after UserPromptSubmit has recorded a positive causal turn and sequence that agree in the registry.

Which profile fits a simple request?

“Small” describes size, not risk. The harness uses this matrix to choose and record a temporary route; semantic inference remains in the agent, not Wend Runtime:

| Situation | Work kind | Suggested profile | New change | |---|---|---|---| | Question, inspection, or diagnosis with no mutation | inspection | No transition | No | | Local, reversible fix with an allowlist and no contract/spec change | maintenance | FLOW (E → V) | No | | Small behavior change without formal review | implementation | GUIDE (P → E → V) | Yes, compact | | Public contract, security, schema, dependency, CI/release workflow, or policy | implementation | GOVERN/ASSURE | Yes | | Merge, push, tag, or publication of approved behavior | delivery | ASSURE | No | | Operational recovery without code/config correction | recovery | FLOW/ASSURE | No |

Work kind, profile, contract impact, and operational risk are independent dimensions. A delivery records authorized capabilities and an append-only receipt without creating a change, spec, or ADR. If delivery requires a code/config edit, it pauses and work returns to implementation:

In multi-context Vaults, active_contexts[].delivery_id is authoritative and --session <id> selects the caller explicitly. CURRENT_DELIVERY is only a derived projection when there is one single, unambiguous context; hooks consult only the causal delivery, and an ID from another context fails with WENDKEEP_DELIVERY_CONTEXT_MISMATCH.

operating_profile_task belongs to the causal work session's active context. profile route and profile status --session <id>, hooks, and Stop read/consume only that lease; a temporary route never crosses into a sibling. Legacy session fallback exists only without active_contexts; an initialized registry never copies a global authorization without proven identity.

npx wendkeep delivery start release-0-74-0 --allow git:merge --allow git:push --allow publish --source-change <slug> --source-commit <sha> --session <id>
npx wendkeep delivery status release-0-74-0 --session <id>
npx wendkeep delivery finish release-0-74-0 --target origin/main --ci-url <url> --version 0.74.0 --npm-integrity <sha512> --release-url <url> --session <id>

For git:merge and git:push capabilities, delivery finish requires --target <remote>/<branch> (for example, --target origin/main). delivery start binds the origin remote to the expected repository; during finish, the target is resolved again with git ls-remote. If the target cannot be resolved or the origin/repository binding diverges, the delivery is blocked before provenance adapters run.

The provenance gate re-derives authority against the current subject before archive, delivery, release, or cleanup. Its single taxonomy is verified, reported, legacy-unbound, stale, conflict, and unproven; only verified authorizes required proof. Evidence, a verdict, or a receipt captured before amend/rebase, from another branch/worktree/session, or backed only by a reported/offline external claim fails closed with objective recovery. New receipts use schema v2, previous_hash, receipt_hash, and a separate checkpoint to detect tampering and truncation. Stable codes are WENDKEEP_PROVENANCE_GATE_BLOCKED, WENDKEEP_RECEIPT_LEDGER_BUSY, WENDKEEP_RECEIPT_LEDGER_CONFLICT, WENDKEEP_RECEIPT_LEDGER_CORRUPT, and WENDKEEP_RECEIPT_LEDGER_TRUNCATED. Safe recovery reads state, reasonCodes, diagnostics, and repair.command in --json output, runs npx --no-install wendkeep verify --deep --json or the indicated status command, and recaptures proof; it never prints raw stderr, tokens, private URLs, or Vault paths, and never edits the ledger/checkpoint.

If the harness does not record a lease, a small fix remains under the configured profile — GOVERN by default. OFF does not mean “simple task”: it is a persistent human choice that hands governance to the native harness. The LLM may temporarily elevate an OFF base to a Wend route, but it can never select OFF on its own.

A corrupt binding never selects OFF: with one unambiguous explicit or legacy Vault, Keep Core remains active under GOVERN, the error stays visible, and mutation guards fail closed. Additional roots that FLOW must protect can be declared as project-relative paths under harness.flow.protectedRoots in .wendkeep.json; any change below them requires promotion. Invalid local config, marker, or identity never silently falls back to a parent/global Vault.

wendkeep profile status/use/route makes the choice observable; wendkeep flow start/finish/promote handles local adjustments without manufacturing an ADR and fails closed on physical escapes, Git metadata/hidden flags, mutating sensors, protected surfaces, or incomplete session projection. Bounded no-follow discovery sees empty/ignored protected aliases; Vault writes and owner+lease locks validate physical topology. Concurrent promotion elects one owner and supports retry through --change-slug. Read the complete Operating profiles guide.

wendkeep doctor separates structural errors, workflow attention, repairable debt, and semantic ambiguity. Use --scope core for Keep Core health, --scope runtime for governance, and --strict in CI/release; wendkeep sync validates Core only so work in progress does not become an installation failure.

To resume a change in another clone without tracking transcripts, tokens, paths, leases, or outboxes, wendkeep portable export creates .wendkeep/portable/state.json with sanitized authored CORE/ADRs/specs/deltas and a compact active-work projection. portable import validates project, hashes, revisions, and paths before writing; stale or conflicting state never silently replaces local state. Git tracking is opt-in and the command never adds files automatically.

Shared Project Memory v2

Hot memory now separates human authorship, operational state, and evidence:

  • CORE.md is canonical. It is the short, hand-curated nucleus for durable preferences, active patterns, and open issues; no projector may infer or overwrite it.
  • SHARED_MEMORY.md is bounded generated operational state. The Stop hook turns the session handoff into sanitized events; the projector deterministically reduces the ledger and publishes a verifiable revision, cursor, and hash. Admission prioritizes critical operational state and never publishes beyond 48 lines/6 KiB; omitted events remain in the append-only authority and surface only as verifiable counts. Facts are verified only with local evidence; unsupported reports remain reported, and disagreements become candidates for human judgment.
  • MEMORY_EVENTS.jsonl is the append-only authority. Stop makes events durable in the outbox before acknowledging the attempt; the projector runs outside the registry lock and retries reuse the same IDs. Repeating an identical event_id/payload is a no-op; reusing the ID with different bytes is observable corruption.
  • MEMORY_CANDIDATES.jsonl is the curation queue. Conflicts and legacy content are never silently promoted. promote and reject record the decision as a new event; promotion preserves the selected event's JSON type, session, activation/epoch, and source turn.
  • Registers are scoped. git.local-head, handoffs, verdicts, and change status carry project, work-session, change, branch, or worktree scope. Two branches do not create a global conflict; only events in the same scope and causal lineage may advance automatically. Once active_contexts is initialized, Stop derives work_session_id, repository_id, worktree_id, branch, and change from the causal active context; a divergent handoff fails before CAS, note, outbox, or ledger mutation. Legacy compatibility exists only without the contextual store.
  • EVIDENCE_INDEX.jsonl is local recall. Markdown is chunked by headings and blocks without requiring the Observer. Ranking combines BM25, exact phrases, field weights, authority, validity, bounded recency, and source diversity. The automatic UserPromptSubmit hook is read-only: it never migrates CURRENT_CHANGE.md or mutates the registry; it excludes passages owned by an active sibling session or change while preserving global and historical evidence. Explicit /brain-recall remains global.

Artifacts stay under .brain/ only. Sanitization strips secrets, tokens, local paths, transcripts, and harness payloads both before persistence and before injection. Events carry a project_id, and one vault never accepts another project's events.

Lifecycle in brief: each SessionStart opens an epoch that spans multiple Stop events; UserPromptSubmit advances the native turn and recovers exactly one closed legacy activation. Codex uses session_id/turn_id plus transcript order, with no artificial causal fields. See sessions and hooks and memory.

Injection and budgets

CORE.md is the only manual layer: it accepts up to 40 lines, warns from 35, keeps a 4 KiB ceiling, and caps each line at 320 characters. SHARED_MEMORY.md is generated exclusively by the projector and ledger; never edit it to repair state. brain-inject delivers the same revision/hash on startup, /clear, and /compact SessionStart events, always placing CORE and SHARED before change context. The full envelope is capped at 24 KiB; SHARED reserves up to 48 lines/6 KiB. Under pressure, lessons are removed first, then non-current changes. CORE is never sliced and SHARED admits deterministic whole events rather than prefix-slicing; a missing, invalid, or over-budget layer becomes a visible, repairable <wk_memory_error>.

memory status --gate and validate-memory --vault also check semantic coverage: they report a code, counts, and active/projected/missing keys. An empty v2 bundle is neutral; a bounded omission that exactly reproduces ledger selection is an operational warning. An arbitrarily missing event, false count, placeholders as the only content, or an unresolved decision link remains explicitly degraded/blocking without printing memory values.

DIGEST.md is no longer the operational handoff: it remains the /brain-recall bridge and legacy-vault fallback. A vault without SHARED receives CORE+DIGEST with a deprecation warning; migrate during the compatibility window:

npx --no-install wendkeep memory status --gate --vault .MyApp-vault
npx --no-install wendkeep memory migrate --vault .MyApp-vault          # preview, zero writes
npx --no-install wendkeep memory migrate --apply --vault .MyApp-vault  # backup + candidates + v2 bundle
npx --no-install wendkeep memory rescope --vault .MyApp-vault          # preview without values
npx --no-install wendkeep memory rescope --apply --vault .MyApp-vault  # append-only and idempotent

Health and recovery

Use npx --no-install wendkeep memory status --gate --vault <vault> in CI and before verify/archive. Revision 0 immediately after valid migration is healthy. The gate correlates last_memory_attempt, outbox, ledger, SHARED, and checkpoint: degraded with a durable outbox is a warning; an ambiguous attempt, lost publication, or mismatched checkpoint blocks. See migration and diagnostics.

If status blocks, preserve the evidence and run npx --no-install wendkeep memory repair --vault <vault> to back up the corrupt ledger, retain valid lines, and re-project. Repair remains structural: its only narrow acknowledgement exception covers attempts entirely represented by the outbox consumed by that same run; it does not scan or reclassify historical attempts. Valid pre-0.59 causal checkpoints and exactly re-derived assert-only historical prefixes are CAS-migrated on both the attempt and memory_checkpoint to the correct physical boundary with backup/audit; divergent mirrors fail closed. A demonstrably superseded ambiguity uses memory reconcile <session> --by-session <successor> --reason <reason> as a dry run and requires --apply; the decision is backed up and audited without rewriting ledger, CORE, or notes. Run status --gate again afterwards. memory rescope append-only separates legacy handoffs with proven identity even when they already participate in candidates; it never selects a winner. Actionable conflicts require explicit, durable curation. Start with memory curate --vault <vault>: the menu shows actionable conflicts only, groups them under friendly names, shows sanitized previews, and confirms every write with default no. memory curate --all includes proven historical handoffs and lets H batch-close them after confirmation. In a non-TTY environment, use memory candidates --active --vault <vault> to list only safe IDs and metadata in read-only mode — it does not expose memory values or content. After human review, memory promote <id> --event <event-id> selects one event from the candidate, while memory reject <id> keeps the current value. memory repair does not choose a winner. The decision is idempotent, and a new promotion accepts a later Stop from the same session/activation without recreating a conflict. A promotion written by 0.66.1 remains historical: if the next Stop forms a new candidate, update to 0.66.3 and run memory repair. During replay, a transient candidate is re-evaluated against the final modern source and, when causal supersession is proven, re-anchored to it; explicit promotion uses that anchor and crosses only the physical predecessors required by replay. The same session/activation/epoch and a higher turn advances; a lower turn is superseded. Repair migrates the checkpoint and mirror only when it proves the exact previous replay, attempt identity, and absence of a real conflict; it creates a backup and audit without appending or rewriting events. Ambiguity stays queued for explicit curation. Do not publish or install 0.66.2; use 0.66.3 or later. Decisions survive repair/replay; blocked_by_core cannot override CORE. Doctor only diagnoses, now with human-readable output and the guided next action; its health hook preserves JSON for automation. A missing Vault or unsafe boundary/registry also yields blocked memory, a safe command with the resolved path, and structured JSON—never a false “intact bundle” or a stack trace. When status/doctor reports projected acknowledgement pending on 0.66.4 or later, first run the targeted dry run memory recover-attempt <session> --vault <vault>, then authorize --apply; it changes only registry/checkpoint. See syntax, preconditions, and fail-closed behavior in memory and curation.

Session notes use one live ## Agentes, tokens e custos snapshot. Main-agent and subagent hooks recompose it atomically, with costs, token dimensions, reasoning tokens and effort per model/source. On Codex, subagent prompts register their rollout for observability without advancing the main agent's sequence; SubagentStop reads the child from agent_transcript_path and persists its signal only when parent_thread_id matches a validated session root. The main Stop uses the registry's causal turn_id mapping before falling back to local transcript order. Every terminal attempt writes a sanitized, idempotent receipt to .brain/SESSION_ITERATION_OUTCOMES.jsonl, distinguishing insertion, duplicate, skipped, aborted, busy-lock, failure, and observability status; the cursor advances only after note confirmation. subagent_notification is not a human prompt, turn_aborted is explicit, and custom tool output is not double-counted. To recover missing markers while a conversation is open, hook session-backfill is a dry-run by default and never writes a Codex turn without task_complete. Every hook that rewrites a session note takes a per-file lock and writes through a temp file + rename, so the SubagentStop fan-out (one hook run per subagent) can never leave a note half-written; a note whose frontmatter reads back damaged is left untouched rather than patched.

On definitive close, the activation and session become done in SESSION_REGISTRY.json only after memory/observability publication; CURRENT_SESSION.md is a derived view, not the identity authority, and does not list finalized sessions.

Retroactive memory (import) — install today, remember yesterday

Install wendkeep into an existing project and it only remembers sessions from now on. wendkeep import fixes that: one command backfills your project's past Claude & Codex sessions into the vault — deduped, dated, with cost — so the graph starts full, not empty. It rebuilds each transcript as a full session note in its real date folder — frontmatter (tagged with the transcript's real provider), one iteration block per turn, cost + subagent telemetry, derived decision/bug/learning notes, finalized closing. An offline replay of the live capture flow, so an imported note is indistinguishable from a captured one.

wendkeep import --vault .myproject-vault --dry-run   # preview what would be imported (both agents)
wendkeep import --vault .myproject-vault             # write the notes
wendkeep import --vault .myproject-vault --source codex   # just Codex
  • Both agents by default (--source all). Claude sessions come from ~/.claude/projects/<slug>/; Codex rollouts from ~/.codex/sessions/**, scoped to this project by the cwd recorded in each session (case- and separator-insensitive, subdirs included). Narrow with --source claude / --source codex.
  • Every note records its session_id and provider in frontmatter (live capture and import alike). Backfill older notes with wendkeep import --stamp-ids (fills the id from the registry; idempotent).
  • Deduped by session_id against the vault's SESSION_REGISTRY and existing notes' frontmatter — only sessions not already present are imported, and it never overwrites an existing note. Re-running is a no-op.
  • --from <dir> / --codex-from <dir> point at the transcript folders explicitly (use if the auto-derived path misses). Also: --since <date>, --limit <n>, --rescan-decisions, --json.
  • Once imported, wendkeep cost aggregates your entire history — retroactively, across both agents.

Derived notes — numbered like ADRs (note new, renumber-*)

Decisions, bugs and learnings are derived notes: they live in the month folder of their tree (<folder>/<year>/<MM-MON>/) and carry a sequential id — ADR-0001, BUG-0001, APR-0001. One glance tells you what a note is and where it sits in the project's history. No day-level subfolders: a DIA N folder holding one note is noise, and it hides the note from folder-wide search.

Creating one (never write the file by hand — the command owns the number, the folder and the frontmatter):

wendkeep note new --type bug "login 500s when the token expires mid-refresh"
# → 05-Bugs/2026/07-JUL/BUG-0007-login-500s-when-the-token-expires-mid-refresh.md

wendkeep note new --type learning "a regex without /g only ever returns the first match"
# → 06-Aprendizados/2026/07-JUL/APR-0003-a-regex-without-g-only-ever-returns-the-first-match.md

It prints the created path, numbers from the current max (recursive scan), files it in the month folder for today (--date YYYY-MM-DD to override), and links the active session in source: so the graph stays connected. Agents get this rule injected at SessionStart — they call the command instead of guessing a filename.

Reconnecting legacy notes. Derived notes created by older versions carry no source: session and sit as islands in the graph. wendkeep note relink backfills them: each orphan inherits the modal source session of its type/month cohort (the session its non-orphan siblings already point to). Dry-run by default; --apply writes; notes with no sibling to infer from are skipped and reported.

Migrating an existing vault. Notes created before 0.41.0 have date-prefixed names (2026-07-16-bug-<slug>.md) and may sit in legacy DIA N subfolders. One command per tree renumbers them chronologically, moves them up into the month folder, and rewrites every wikilink across the vault:

# Bugs — 05-Bugs → BUG-NNNN
wendkeep renumber-bugs                  # preview: prints every from → to, writes nothing
wendkeep renumber-bugs --apply          # migrate

# Learnings — 06-Aprendizados → APR-NNNN
wendkeep renumber-learnings             # preview
wendkeep renumber-learnings --apply     # migrate

# Decisions — 04-Decisões → ADR-NNNN (since 0.30.0)
wendkeep renumber-decisions             # preview
wendkeep renumber-decisions --apply     # migrate
  • Preview is the default. Nothing is written until --apply — read the from → to list first; that is where a mangled slug shows up, before it touches your files.
  • One tree at a time, on purpose. There is no renumber-all: each folder is migrated and reviewed on its own.
  • Order is chronological, derived from the note's date (frontmatter → filename prefix → folder), so BUG-0001 is genuinely the oldest bug — not the first one the scanner happened to read.
  • Wikilinks are rewritten vault-wide (full-path and basename forms, aliases preserved), the body's type/bug:/apr:/H1 are normalized, and emptied DIA folders are removed. Idempotent: a second --apply renames nothing. Close Obsidian while migrating, and commit the vault first if it is under git.

Change lifecycle — the a2 loop (spec‑driven, native)

Beyond capturing sessions, wendkeep is a harness: a native, zero‑dependency loop that keeps intent (specs), work (changes) and proof (sensors) together in the vault, wikilinked into the Obsidian graph.

explore → propose → apply (TDD) → verify → archive
  • Proposewendkeep change new <slug> scaffolds 08-Mudanças/<slug>/ (proposta.md, design.md, tarefas.md; --simple skips the design). --guide creates the compact GUIDE contract and omits automatic design/spec/ADR when contract_impact:none. It becomes the global current change. When the change declares spec_impact: required, you author the delta yourself at specs/<capability>/spec.md — there is no placeholder to delete. Multiple changes may remain open: change list/status and the hooks show every pending one, while commands without --change act on the current one alone. change use <slug> changes focus and change continue <archived> <new> creates an auditable continuation.
  • Apply — implement each tarefas.md task. Mark machine proof with one or more [sensor:<id>] tags on the same task: every distinct ID enters the gate once, in declaration order. Also mark satisfied requirements with one or more [req:<ID>] tags. For causal TDD, add [tdd] and record wendkeep tdd red|green; the TDD attestation guide covers profiles, waivers, and exit codes.
  • Verifywendkeep verify runs declared sensors and writes an Evidence Envelope v2 to evidencia.json, SHA-256-bound to project/repository/worktree/session, HEAD, index tree, normalized worktree digest, tasks, effective spec, TDD attestations, and sensor configuration. Each sensor records a sanitized command, execution window, duration, exit code, output digest, and a sanitized tail bounded to 2,000 characters; artifact_results binds explicit digests for versioned files without using stdout as proof. If HEAD changes during the run, no new envelope is published. change status reports bound, stale, context-mismatch, or legacy-unbound; v1 evidence remains readable but cannot satisfy v2 authority. The public schema is schema/wendkeep.evidence-envelope-v2.schema.json. verify --deep binds the package, attestations, and verdict to the current envelope_id.
  • Archivewendkeep change archive <slug> gates on the evidence (blocks unless every declared critical sensor is green), promotes each applicable spec delta (ADDED/MODIFIED/REMOVED) into the living 07-Specs/<capability>.md and moves the change to _arquivo/. GOVERN/ASSURE mint an ADR in 04-Decisões/; compact GUIDE with no contract impact does not mint one automatically.

The gate blocks unless the scaffold is filled, no task is open, evidence is fresh, and every declared requirement is covered. --force waives exactly one of those — the open-task check — and is the human's call, never the agent's. An unfilled scaffold, a red critical sensor, stale evidence, an orphan requirement or a missing verdict block regardless.

After the fix, archive requires a final recapture with wendkeep verify --deep --change <slug>. The package is complete and canonical; the verdict must also be complete and canonical, with both bound to the same checkout, change, tasks, spec, and sensors. Before any mutation, the command writes an authorization receipt to the separate change-archive-receipts-v2 ledger; only after that receipt is valid may it promote the spec/ADR or move the change. change archive --json returns the serializable state, reason_codes, diagnostics, and repair fields. Corruption or truncation in any ledger fails closed before mutation. --force does not bypass provenance, integrity, package, verdict, corruption, or truncation; the exact recovery is the recapture above.

Archive sealing uses the runtime lock and a private ASCII transaction at .brain/runtime/archive-transactions/<uuid>/{original,authorized}: it atomically renames the live change to original, checks the digest, and promotes only authorized. On a seal or divergence failure, it removes the snapshot and restores original without partial promotion. Multi-spec promotion is one atomic unit: it captures before-images/digests, rolls back before/after writes, and permits retry only after reconciliation and fresh verification. The post-release finalizer validates original/destination digests, but the completed journal keeps the original retained; no destructive cleanup is automatic. A failure leaves published-recovery-required. Text and --json keep the same sanitized diagnostic (code, operation, state, blocker, expected, observed, recovery).

The archive uses a directory lock with a token-specific marker and lease: acquisition prepares a sibling .pending directory and publishes it by atomic rename, uses no hardlink, and allows at most 3 topology attempts. A live owner returns WENDKEEP_ARCHIVE_BUSY, a dead owner is safely reaped, an invalid marker returns WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE, and ownership loss returns WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST. The transaction keeps archive-transaction.json with phases preparedisolatedcopiedsealedpublishedpromotion-preparedpromotion-appliedcompleted or recovery-required. A pending journal blocks a new archive for the same slug before the gate. On a collision/post-publication failure, original is retained and the state is published-recovery-required; operation_id and transaction_phase are sanitized. Inspect it with wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]: without --spec-action, this is a read-only, fail-closed, idempotent operation that returns sanitized actions without promoting or deleting. rollback restores before-images and resume converges after-images for a promotion-prepared promotion, while retaining the journal for reconciliation. When an operation ID exists, repair.command points to that recovery; do not treat command:null as the normal flow.

wendkeep init seeds process skills into the vault's .brain/skills and delivers identical copies to .claude/skills/ and .agents/skills/; Codex gets the agent definitions (.brain/agents/*.toml.codex/agents/) plus a managed section in AGENTS.md that indexes the skills. Every skill carries source hash/version metadata; doctor warns when reseed + agent restart is required.

The loop in five minutes

npx wendkeep init --yes                        # vault + hooks + sensors + skills
npx wendkeep change new dark-mode              # proposta/design/tarefas — change is now active

Edit tarefas.md — tag proof and requirement per task:

- [ ] 1.1 toggle persists across sessions [req:UI-1] [sensor:tests] [tdd]

Declare the capability in proposta.md (specs: [ui]) and author its delta only in 08-Mudanças/<slug>/specs/ui/spec.md. 07-Specs is generated/read-only. Then:

npx wendkeep change status                     # every open change + its pending tasks
npx wendkeep change list                       # same backlog, plus the archived ones
npx wendkeep change status dark-mode           # one screen for one change: specs / tasks / sensors / verdict
npx wendkeep spec effective --change dark-mode # living contract + this change's delta
npx wendkeep change done 1.1                   # tick a task from the CLI
npx wendkeep tdd red 1.1 --requirement UI-1 --test tests/ui.test.mjs --command "npm test"
# implement; then observe GREEN in the same causal context
npx wendkeep tdd green 1.1 --command "npm test"
npx wendkeep verify                            # run the declared sensors -> evidencia.json
npx wendkeep verify --deep                     # assemble the verification package
# the wk-verify skill (fresh, read-only pass) writes verdict.json
npx wendkeep change diff                       # preview what will land in 07-Specs
npx wendkeep change archive dark-mode          # gate: sensors + verdict + no open tasks

The archive promotes the delta into generated 07-Specs/ui.md, mints an ADR, and the Obsidian graph now links session ↔ change ↔ requirement ↔ decision. Every generated artifact (design/tarefas) is born linking its change's proposta hub, and hand-authored spec.md deltas are auto-linked on verify/archive — no change artifact is a graph island. To backfill older changes that predate this, run wendkeep change backlink --apply (dry-run without --apply). A change that names no [req:] still runs verify --deep, but skips the wk-verify reading pass: the command writes a trivial verdict on its own and the sensor gate is the real proof.

How it works

agent session ──hooks──▶ wendkeep ──▶ Markdown in vault ──▶ .brain memory + Obsidian graph
   (Claude/Codex)        (Node)      (02-Sessões/…)        (CORE+SHARED, ledger, backlinks)

The agent's settings.json points each hook at npx wendkeep hook …; in Claude Code the change-lifecycle hooks instead run the installed script directly (node on ${CLAUDE_PROJECT_DIR}/node_modules/wendkeep/hooks/<name>.mjs) when the package is present locally, skipping an npx resolve on every event. .codex/hooks.json mirrors the same groups with PascalCase event keys, but always uses the npx form (${CLAUDE_PROJECT_DIR} does not exist in Codex) and spells its timeout timeoutSec — a plain timeout is neither a field nor an error there, it silently falls through to a 600s default, so init migrates that legacy key in place. On Stop, wendkeep parses the session transcript, appends the turn, updates token/cost data, emits derived notes, and publishes the sanitized handoff to the memory outbox. On SessionStart — startup, /clear, and /compactbrain-inject injects CORE + SHARED, every open change with its pending tasks, the causal current-change marker, project lessons, and a <wk_process> router. The inventory remains global, but CURRENT and the sentinel hash come from the session's active context; active_contexts: {} fails closed instead of reviving CURRENT_CHANGE.md. Claude, Codex, or another agent can therefore resume work started elsewhere without hiding the rest of the backlog.

The archive gate blocks unless: the change scaffold is filled (G0), no task is open (G1), every declared critical sensor is green (with fresh evidence), and a verdict.json is present and current. --force waives G1 only — G0 is inescapable by design (a placeholder change forced through once minted a fake ADR), and no flag turns a red sensor or a missing verdict green. The agent is instructed never to use it on its own.

Notes & roadmap

  • Vault folder names default to Portuguese (02-Sessões, 04-Decisões, …). Pass wendkeep init --locale en for an English vault (02-Sessions, 04-Decisions, English scaffold/skills). The locale is a vault property, locked at init; parsers are bilingual so mixed content never breaks.
  • Default recall remains local lexical/FTS. Embeddings require an explicitly supplied trusted local plugin with forbidden network access, budgets, and lexical fallback; Core ships no model or provider.
  • Transcript formats are agent‑internal and can change between agent versions; parsing is isolated but may need updates.
  • Installer wires both agents: .claude/settings.json + .mcp.json for Claude Code, .codex/hooks.json for Codex. Eight Codex hooks are compatible; change-guard validates the project lease in PreToolUse and denies mutations outside it. The four hooks without an equivalent remain Claude-only: change-warn, plan-capture, decision-capture, and task-log.
  • Codex hooks start untrusted. They are