Skip to main content
TRW
Skip to content
TRWUpgrade to trw-mcp 7.0 and trw-memory 4.0

Upgrade guide

Upgrade to trw-mcp 7.0 and trw-memory 4.0

This release cuts the MCP surface from 51 tools to 15, hardens the memory store, and moves embedding work into the memory daemon. It covers everything since trw-mcp 6.1.0 and trw-memory 3.1.0. Upgrade both packages together.

What you get

Better tool picks

51 MCP tools became 15, with 13 on by default. In our tool-selection eval (30 prompts per client, one run each), the first TRW call was the right one 73% of the time on Claude Code, up from 30%, and 80% on Codex, up from 0%.

A safer memory store

Fixes three data-integrity bugs from earlier trw-memory releases, a recall crash on a default install, and a daemon crash that left clients unable to start a new one.

Faster sessions, lighter server

trw-mcp keeps one session open to the memory daemon, so trw_session_start p95 fell from 718–856 ms to 390–462 ms on one machine. The MCP server no longer loads torch or an embedding model; the daemon does that work.

A tighter network story

Models download only when you run trw-mcp models fetch or the installer, never at runtime. No embedding vector leaves your machine, and your platform key goes only to hosts you trust.

Before you start

  • Remove trw-memory’s local_only setting (or MEMORY_LOCAL_ONLY) if you set it. trw-memory 4.0 refuses to start while it is present, in any config source and at any value, so a leftover never silently turns sync back on. Where sharing must stay off, set sync_enabled: false and learning_sharing_enabled: false explicitly and check rbac_mode.
  • Remove encryption_enabled (or MEMORY_ENCRYPTION_ENABLED) if you set it. Encryption at rest is not available in trw-memory 4.0 and is planned for a later release; 4.0 refuses the setting with EncryptionAtRestUnsupportedError. Protect the store with disk encryption (FileVault, LUKS) and its owner-only file permissions.

Upgrade steps

Do these in order.

  1. Install both packages together

    trw-mcp 7.0 needs a trw-memory 4.x daemon, and a 4.x daemon refuses a 3.x client, so upgrade both at once. Drop [embeddings] only if you run keyword-only recall; the installer adds it by default.

    terminal
    pip install -U "trw-mcp==7.0.0" "trw-memory[embeddings]==4.0.0"
  2. Stop the running memory daemon

    One daemon serves each machine, and an old one keeps serving until it exits. Its pid is in daemon.json in the memory directory ($TRW_USER_DIR/memory, else $XDG_DATA_HOME/trw/memory, else ~/.trw/memory) and in any daemon_version_mismatch error. Stop it; the next memory call starts a 4.0 daemon.

    A 4.0 daemon will not start when its memory directory, or a parent of it, is owned by another user (other than root) or is group- or world-writable without the sticky bit. The refusal names the directory and goes to daemon-start.log. Fix the permissions or point TRW_USER_DIR at a trusted path.

    terminal
    kill "$(python3 -c "import json, pathlib; print(json.load(open(pathlib.Path.home() / '.trw/memory/daemon.json'))['pid'])")"
  3. Refresh each project

    This rewrites the hooks, skills, agents and instruction files, several of which named tools that no longer exist. Use --ide all for every client, and --dry-run to preview.

    terminal
    trw-mcp update-project --ide <id>
  4. Fetch the models

    trw-memory 4.0 loads the default embedding model at one pinned revision and never downloads at runtime, so a cache filled by an earlier release may not satisfy it.

    terminal
    trw-mcp models fetch
  5. Reconnect every MCP client

    Each client runs its own trw-mcp over stdio, and one started before the upgrade keeps running the old code. Run /mcp in Claude Code; restart the session in other clients.

  6. Run the doctor

    The retrieval row shows what recall is using and how many stored vectors sit outside the active embedding space. If that number is not zero, run trw-mcp memory reembed --json and check that status is ok. The new stray_servers row prints a kill line for each old trw-mcp server that no client will use again.

    terminal
    trw-mcp doctor
  7. Check stores written by an earlier trw-memory

    If you ran any trw-memory release before 4.0, run the integrity check on each store and look for memory.db.corrupt.*.bak files in the memory directory. See "Check your stores" below.

  8. Rebuild the code index

    Delete the old .trw/code-index/chunks.json (it can be several GB, and 7.0 never opens it), then run trw-mcp code index without --paths. The index rebuilds once after upgrading, and a --paths update of an index built by an older release is refused with that same remedy. trw_code search and symbol modes answer index_missing until the build has run.

    terminal
    trw-mcp code index
  9. Turn on dispatch if you use it

    If your agents hand work to other coding CLIs, set dispatch_tools_exposed: true in .trw/config.yaml. It is off by default and is the only switch for trw_dispatch.

The short version, per client

upgrade
pip install -U "trw-mcp==7.0.0" "trw-memory[embeddings]==4.0.0"
trw-mcp update-project --ide <id>    # or --ide all; add --dry-run to preview
trw-mcp models fetch

The client ids are antigravity-cli, claude-code, codex, copilot, cursor-cli, cursor-ide, grok and opencode. Then stop the old daemon, reconnect every client and run trw-mcp doctor. The installer’s --upgrade upgrades the packages and caches the models, but it never stops the memory daemon, and it runs update-project only when the deployed framework is out of date.

The new tool surface

  • Eleven tools are always on: trw_session_start, trw_init, trw_status, trw_recall, trw_learn, trw_checkpoint, trw_deliver, trw_build_check, trw_review, trw_prd_validate and the new trw_code. Four sit behind a flag in .trw/config.yaml: trw_send and trw_inbox (comms_enabled, on by default), trw_assess (assess_enabled) and trw_dispatch (dispatch_tools_exposed).
  • The surface is flat. Per-task packs, the discoverable and operator-only tiers, per-call grants and tools hidden by run phase are gone. Calling a tool whose flag is off answers tool_not_in_surface with an enable_with field naming the flag.
  • Removed tool names have no aliases; a call to one is an unknown-tool error. The replacement commands take the old arguments as flags and print one JSON document with --json.
  • On Claude Code the always-on tools load up front, so no tool-search round-trip comes before trw_session_start. Leave ENABLE_TOOL_SEARCH unset for that; an explicit ENABLE_TOOL_SEARCH=true defers them again.

Now a mode of a tool that stays

Removed tool
trw_code_search
Use instead
trw_code(mode="search", query=...)
Removed tool
trw_code_symbol
Use instead
trw_code(mode="symbol", query=<name>), exact matches first
Removed tool
trw_before_edit_hint
Use instead
trw_code(mode="hint", files=<path>)
Removed tool
trw_before_edit_hint_batch
Use instead
trw_code(mode="hint", files=[...])
Removed tool
trw_delivery_status
Use instead
trw_status(delivery=<delivery_id>); needs no active run
Removed tool
trw_submit_feedback
Use instead
trw_status(feedback={category, subject, message})
Removed tool
trw_profile_explain
Use instead
trw_status(detail="surface"), or trw-mcp profile explain
Removed tool
trw_graph_related
Use instead
trw_recall(graph_id=<learning id>)
Removed tool
trw_heartbeat
Use instead
trw_checkpoint(heartbeat=true)
Removed tool
trw_pre_compact_checkpoint
Use instead
trw_checkpoint(pre_compact=true)
Removed tool
trw_peers
Use instead
trw_inbox(action=...): enroll, list, heartbeat, announce, withdraw, discover
Removed tool
trw_dispatch_status
Use instead
trw_dispatch(action="status", target=<job id>)
Removed tool
trw_agent_work_evidence
Use instead
trw_dispatch(action="evidence", target=<run path>)
Removed tool
trw_validate_agent_work_evidence
Use instead
trw_dispatch(action="validate_evidence", target=...)

Now a trw-mcp command

Removed tool
trw_delivery_recover
Use instead
trw-mcp delivery recover; --action resume also needs --new-pid
Removed tool
trw_probe
Use instead
trw-mcp probe run
Removed tool
trw_probe_budget_status
Use instead
trw-mcp probe budget
Removed tool
trw_meta_tune_propose
Use instead
trw-mcp meta-tune propose (Linux only, as before)
Removed tool
trw_meta_tune_rollback
Use instead
trw-mcp meta-tune rollback
Removed tool
trw_query_events
Use instead
trw-mcp telemetry events
Removed tool
trw_surface_classify
Use instead
trw-mcp telemetry classify
Removed tool
trw_surface_diff
Use instead
trw-mcp telemetry surface-diff
Removed tool
trw_mcp_security_status
Use instead
trw-mcp telemetry security
Removed tool
trw_channel_stats
Use instead
trw-mcp telemetry channel-stats
Removed tool
trw_pipeline_health
Use instead
trw-mcp telemetry pipeline-health, and a trw-mcp doctor row
Removed tool
trw_code_index_update
Use instead
trw-mcp code index
Removed tool
trw_codebase_risk_report
Use instead
trw-mcp code risk
Removed tool
trw_prd_create
Use instead
trw-mcp prd create (the /trw-prd-ready skill runs it)
Removed tool
trw_prd_diff
Use instead
trw-mcp prd diff
Removed tool
trw_adopt_run
Use instead
trw-mcp run adopt
Removed tool
trw_instructions_sync
Use instead
trw-mcp instructions sync
Removed tool
trw_claude_md_sync
Use instead
trw-mcp instructions sync (it was an alias)

Deleted

Removed tool
trw_ordering_compare
Note
Deleted
Removed tool
trw_cross_repo_ordering
Note
Deleted
Removed tool
trw_replay_outcomes
Note
Deleted, with the TRW_ALLOW_REPLAY variable
Removed tool
trw_request_tool_access
Note
Deleted with per-call grants
Removed tool
trw_skill_discovery
Note
Deleted with the discoverable tier

Retired settings

  • TRW_OFFLINE is removed and ignored. Runtime model loads never download; platform_contact_enabled: false (or TRW_PLATFORM_CONTACT_ENABLED=false) turns off the update check and the team-sync pull; uploads stay behind platform_telemetry_enabled, off by default.
  • trw-memory’s local_only is removed and refused at startup (see "Before you start").
  • trw-memory’s encryption_enabled is refused, and the [encryption] extra is gone.
  • The [bm25] extra is gone: keyword ranking is part of the base install. Drop bm25 from any pip install "trw-memory[...]" line.
  • These trw-mcp keys have no effect and print a one-line notice: phase_exposure_enabled, tool_access_grant_max_ttl_seconds, the seven skill_* discovery and retirement keys, memory_store_path, max_cluster_size, audit_pattern_promotion_threshold, wal_checkpoint_idle_interval_seconds, pipeline_health_bandit_probe_enabled and pipeline_health_bandit_stale_days.
  • The profile key allowed_tools_by_phase fails validation. Delete it.
  • New keys: platform_contact_enabled, code_index_bounds and dispatch_fallback_clients.

The daemon version check

  • trw-memory 4.0 changes the daemon API: callers send text, never vectors. Both sides now check the major version, so a mismatch fails fast with a clear message instead of a confusing tool error.
  • A 4.x daemon refuses a call from a 3.x client (as under trw-mcp 6.1) with daemon_version_mismatch, its pid and the fix. A 4.x client refuses a daemon of another major before any call, naming both versions and the pid to stop.
  • A daemon refusal now fails trw_learn instead of storing the learning unchecked.

The store schema moves to 8

  • The first trw-memory 4.0 open of a 3.1 store migrates it from schema 6 to 8 in one transaction: the retired wiki’s link table is dropped (your entries are untouched) and the quarantine review log gains a namespace column.
  • Before migrating a store that holds rows, 4.0 writes a snapshot beside it at backups/memory.db.pre-schema-8.<UTC time>. If the snapshot cannot be written, the migration does not run and the store stays as it was.
  • The migration is forward-only: a 3.x build then refuses the store with SchemaDowngradeError rather than misread it. To go back to 3.1, stop every process using the store and copy the snapshot over the store file; writes made after the migration are not in it.

Models

  • trw-mcp models fetch downloads the daemon’s embedding model and the re-ranker and exits 1 if a download did not land. It needs trw-memory[embeddings]. The installer uses the same fetch.
  • The default model, BAAI/bge-small-en-v1.5, is pinned to one Hub revision; the loader, the cache check and the fetch all use it.
  • Without a cached embedding model, the daemon’s recall and store run keyword-only and the reply names trw-mcp models fetch. The in-process MemoryClient raises ModelNotCachedError.

Fixed in trw-memory 4.0

Store corruption when two processes share a store

Affected every trw-memory release from at least 0.11.0 through 3.1.0. Permission hardening opened and closed the store file on each backend open, which on macOS and Linux releases every SQLite lock the process holds on it, so a second process could write at the same time. 4.0 sets permissions by name and never opens an existing store for it.

Lost first writes to a new store

Affected trw-memory 2.0.0, 3.0.0 and 3.1.0. Lock contention on a brand-new store was treated as corruption, so the store was moved aside while other connections were still writing to it. 4.0 retries a busy store and never treats contention as corruption.

A passing open error set a healthy store aside

Affected every release from 1.0.0 through 3.1.0. Errors such as running out of file descriptors, a full or read-only disk, or a schema change sent a healthy store to recovery, which moved it aside and started an empty one. 4.0 fails the open and leaves the file alone; only definite corruption triggers recovery.

Recall crash on a default install

Affected 2.0.0, 3.0.0 and 3.1.0: recall could fail with NameError: BM25Okapi. Keyword ranking is now part of the base install.

A crashed daemon stranded every client

On macOS the daemon could abort while two threads encoded at once, and clients kept reading its pid as live. Models now run on CPU on macOS, a zombie daemon reads as not running, and a client reaps the daemon it starts.

Check your stores

integrity check
# Default location; use $TRW_USER_DIR/memory or $XDG_DATA_HOME/trw/memory if either is set
sqlite3 ~/.trw/memory/memory.db 'pragma integrity_check'
ls -l ~/.trw/memory/memory.db.corrupt.*.bak
  • Check the user store and any project store (<project>/.trw/memory/memory.db). Anything but ok means damage: stop every process using the store, then run trw-memory restore --from-snapshot latest --db <path>, or --from-cold to rebuild from the YAML copy of each learning.
  • A memory.db.corrupt.*.bak left by trw-memory 1.0.0 through 3.1.0 may be a healthy store that a passing open error set aside, and one whose timestamp matches the store’s first use points to the lost-writes bug. Open it read-only before deleting it (sqlite3 -readonly <file> "select count(*) from memories") and copy back by hand any rows the live store lacks. Only the newest five backups are kept by default.

Bounded reviewer lanes

  • A reviewer lane (the default for the code-review and audit roles) gets exactly trw_recall and trw_code from TRW, enforced by the server.
  • Its host tools are bounded too: a Codex reviewer no longer inherits your other MCP servers or ChatGPT apps, and a Claude reviewer’s own tools are only Read, Grep and Glob.
  • Only Claude and Codex have a reviewer launch, so a reviewer role on another client is refused. --posture default restores an unbounded child and prints a warning.

Other changes you may notice

  • Your platform key goes only over https to api.trwframework.com, to hosts you list in the user-level ~/.trw/config.yaml platform_trusted_hosts, or to a loopback host. A project’s tracked config can still name another host, but that host gets requests without the key. The update check runs at most once a day per process.
  • The code index is bounded by the new code_index_bounds. A crossed bound answers index_bound_exceeded; missing_index is now index_missing, and a build never enters a nested worktree, clone or submodule.
  • The stdio server exits when its client dies, even if another process still holds the pipe.
  • trw-mcp memory migrate --apply refuses a source store that has SQLite sidecar files beside it (-wal, -shm or -journal), more than one hard link, or a symlinked path component, and refuses the copy if the store changes while it runs. Stop the clients writing that store so SQLite checkpoints it, then rerun. Do not delete the sidecars.
  • CLI dispatch can fall back to another client, but only one you list (--fallback-clients or dispatch_fallback_clients). Read client and fallback_note in the result.
  • trw_assess answers can carry an optional advice field near a decision boundary.
  • For SDK users: trw_memory.bandit, trw_memory.code_index and trw_memory.migration are deleted, and trw-mcp’s in-process embedder and vector-store APIs are gone.

Known issues

  • After a bulk write of about 5,000 rows or more, closing a MemoryClient can raise TimeoutError while background graph updates drain. The store still closes intact, and its WAL is applied on the next open. trw-memory 3.1.0 behaves the same; a fix is planned for 4.1.
  • SDK only: a DaemonClient(keep_session=True) whose event loop ends while it holds an idle session never closes that session until the client is garbage-collected or the process exits. Call await client.retire() before the loop ends. trw-mcp is not affected.
  • If trw_learn fails after the daemon accepted a duplicate merge (for example, its local YAML write failed on a full disk), retry that trw_learn before another learning merges into the same one; a different merge in between can undo the first merge’s recurrence count. A fix is planned for 7.1.
  • trw-memory restore checks once, before it replaces memory.db, that no daemon is running. Stop every process using the store, not just the daemon, before you restore.
  • trw-mcp doctor and the trw-mcp memory migrate preview can report a stale row count if a writer starts while they read a store. Re-run to confirm the number.
  • Automatic recovery of a genuinely corrupt memory.db does not yet check whether another process still has the store open. Stop the other clients before you reopen a store reported as corrupt.

Keep going

If you haven't installed yet, start with the quickstart. If you have, the lifecycle page explains what TRW actually does once it's running.