Reference
Environment Variables Reference
LLM & Model Selection
| Variable | Required by | Purpose |
|---|---|---|
OPENROUTER_API_KEY | trusty-search /chat, trusty-common chat helpers, trusty-analyze deep pass (OpenRouter path), trusty-review report, tga audit | LLM chat via OpenRouter. Pass as argument to library helpers; never read from env inside library crates. Required for POST /analyze/deep unless a bedrock/<model-id> model is selected. Required — not optional — for trusty-review report and therefore for tga audit, which renders through it (#5454). Both check it before doing any work and fail with a message naming this variable; tga audit checks it before stage 1 so a multi-minute sweep is never spent on a run that cannot finish. trusty-review reads it via trusty_common::env_vars::ENV_OPENROUTER_API_KEY into ReviewConfig::openrouter_api_key. A reviewer role configured for Bedrock or Fireworks is not preflighted and fails at provider construction instead. |
TRUSTY_LLM_MODEL | trusty-analyze deep pass | LLM model id for the deep-analysis narrative pass. Default: openai/gpt-4o-mini (OpenRouter). Set to bedrock/<bedrock-model-id> (e.g. bedrock/us.anthropic.claude-sonnet-4-6) to route through AWS Bedrock instead of OpenRouter. The bedrock/ prefix selects the Bedrock provider; anything else routes to OpenRouter. Claude Sonnet 4.6 uses the short form without date stamp or -v1:0 suffix. |
TRUSTY_MANAGER_MODEL | trusty-mpm L3 tm manager digest/chat (DOC-36 §3.3) | LLM model slug for the portfolio-manager digest (GET /api/v1/manager/digest) and chat (POST /api/v1/manager/chat) calls. Resolution precedence: TRUSTY_MANAGER_MODEL > TRUSTY_LLM_MODEL > openai/gpt-4o-mini. The slug is routed through the shared trusty_common::inference two-stage provider resolver (an explicit <provider>/… prefix selects a family when its credential resolves, else falls back to OpenRouter). When no provider credential resolves, /digest degrades to a clearly-marked deterministic fallback (503) and /chat returns a typed 503 — never a panic. |
AWS / Bedrock Credentials
| Variable | Required by | Purpose |
|---|---|---|
TRUSTY_AWS_REGION | trusty-analyze (Bedrock deep pass) | AWS region for Bedrock Converse calls. Takes priority over AWS_REGION. Default: us-east-1. |
AWS_REGION | trusty-analyze (Bedrock deep pass) | Fallback AWS region for Bedrock calls. Overridden by TRUSTY_AWS_REGION. |
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN | trusty-analyze (Bedrock deep pass) | Standard AWS credentials for Bedrock access. The full AWS credential chain (env vars, ~/.aws/credentials profiles, IAM roles, SSO) is supported. No API key is needed when using a bedrock/ model. |
AWS_REGION, AWS_PROFILE, AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN | trusty-mpm log drain (s3:// destinations) | Read through the same AWS default provider chain, for any s3:// log-drain destination that does NOT pin an identity. A destination that carries ?profile= ignores all of these — that profile alone supplies its credentials and region, so an AWS_ACCESS_KEY_ID in the daemon's environment cannot re-point one destination at another account (#6657). See log-drain.md. |
Logging
| Variable | Required by | Purpose |
|---|---|---|
RUST_LOG | all daemons | Tracing filter, e.g. RUST_LOG=debug or RUST_LOG=trusty_search=debug,warn. |
Machine tier — supported hardware and the degrade posture
The suite targets 24 GB, supports a 16 GB minimum, and degrades below
16 GB rather than refusing to run (#6820, epic #6802). One module answers
"how much RAM is really here" for every daemon:
trusty_common::machine_tier, behind the machine-tier feature. It reads
hw.memsize on macOS and /proc/meminfo on Linux, clamped on Linux to any
enclosing cgroup ceiling (#3657), then resolves a tier and two proportional soft
limits. Nothing else in the workspace reads total RAM for sizing — sysinfo's
total_memory() in trusty_common::host_metrics is live telemetry and applies
no cgroup clamp, so it reports the host's RAM inside a capped container.
| Tier | Total RAM | Posture |
|---|---|---|
Degraded | < 16 GB | Runs with reduced caps. One startup warning. Not a supported configuration — a working one. |
Medium | 16–31 GB | Minimum supported (16 GB) and the primary target (24 GB → 6144 MB / 18432 MB). |
Large | 32–63 GB | — |
XLarge | ≥ 64 GB | — |
| Variable | Required by | Purpose |
|---|---|---|
TRUSTY_SKIP_RAM_CHECK | trusty-search start | Set to 1 to silence the sub-16 GB startup advisory. Before #6820 this bypassed a hard exit; the exit is gone, so it now only suppresses the warning. Nothing else changes — the Degraded caps still apply. |
Per-tier caps: trusty-search's memory-tuning table.
Measure the effect on a live daemon with scripts/measure-daemon-footprint.sh.
trusty-search — Indexing, Memory & GPU
| Variable | Required by | Purpose |
|---|---|---|
TRUSTY_MEMORY_LIMIT_MB | trusty-search | Soft RSS ceiling for indexing pipeline. Auto-tuned from system RAM; override only when needed. |
TRUSTY_MAX_CHUNKS | trusty-search | Hard cap on chunks per index. Auto-tuned; rarely set manually. |
TRUSTY_MAX_BATCH_SIZE | trusty-search | ONNX embedding batch size. Auto-tuned; set if OOM during reindex. |
TRUSTY_EMBED_ONNX_BATCH | every consumer of trusty-common's FastEmbedder — trusty-search, trusty-memory, trusty-embedderd (issue #7106) | How many texts FastEmbedder::embed_batch hands ONNX in one inference. Default 16. embed_batch used to pass the whole cache-miss list with no bound, taking fastembed's own default of 256 at up to 512 tokens; one attention tensor at that batch is 256 × 12 heads × 512² × 4 B ≈ 9.7 GB before hidden states and the FFN, which took the trusty-memory daemon to 21.3 GB RSS on a single dream cycle. The peak is set by the batch and not by the corpus — a 141-drawer palace spiked as hard as a 365-drawer one — so this one bound covers every caller and every palace size. Read as a positive decimal integer on each call; unset keeps the default silently, while a malformed or 0 value keeps it and logs a warn naming the rejected value, so a typo can never restore an unbounded batch. Raise it on a host with RAM to spare (cost scales linearly: 32 roughly doubles the transient); lower it on a constrained one. |
TRUSTY_EMBEDDING_CACHE | trusty-search | LRU embedding cache capacity (entries). |
TRUSTY_MAX_RESIDENT_INDEXES | trusty-search | How many indexes stay loaded in memory at once; the residency sweep cold-parks the rest, non-destructively, and the next query reloads one lazily (#2161). Defaults ON and tier-scaled since #6821 — Degraded 2, Medium 8, Large 12, XLarge 16. It used to be unset-means-off, which is how a 128 GB host reached 56 resident indexes and 15 GB of heap with 35 of them never queried (epic #6802). off (any case) is the one spelling that disables it; a number is honoured verbatim, 0 included, which still means "park every resident index on the next sweep". An unset TRUSTY_WARMBOOT_MAX_INDEXES inherits this cap, so a boot never loads more than the sweep would keep. GET /health reports the acting value as resident_index_cap / resident_index_cap_source. |
TRUSTY_COREML_TRIPWIRE_MB | trusty-search (Apple Silicon) | RSS-delta ceiling per CoreML batch (default 4 GB). If exceeded, batch size is halved automatically. Override for hosts with different memory pressure characteristics. |
TRUSTY_GPU_MEM_LIMIT_BYTES | trusty-search / trusty-embedderd (CUDA EP, issue #600) | Exact CUDA gpu_mem_limit in bytes, applied alongside arena_extend_strategy=kSameAsRequested to stop ORT's BFCArena over-reserving VRAM and OOMing a 16 GB Tesla T4. Default 12 GiB (12884901888). Takes precedence over TRUSTY_GPU_MEM_LIMIT_MB; a malformed or 0 value is ignored. Removes the need for the old TRUSTY_MAX_BATCH_SIZE=32 workaround. |
TRUSTY_GPU_MEM_LIMIT_MB | trusty-search / trusty-embedderd (CUDA EP, issue #600) | CUDA gpu_mem_limit in megabytes (scaled by 1024²). Used only when TRUSTY_GPU_MEM_LIMIT_BYTES is unset/invalid. E.g. 6144 for an 8 GB card. |
ORT_DYLIB_PATH | trusty-search (CUDA, glibc < 2.38) | Path to libonnxruntime.so on hosts with glibc < 2.38 and CUDA builds. Not used by trusty-analyze — #5067 removed ONNX Runtime from that crate along with its unused neural embedder. |
SKIP_UI_BUILD | trusty-search build.rs | Set to 1 to skip the Svelte UI build step (CI publish flows). |
FORCE_UI_BUILD | trusty-console build.rs (issue #5078) | Set to 1 to rebuild a committed UI bundle even when it already matches its source, then re-stamp it via scripts/stamp-ui-bundle.sh. Without it a cargo build keeps the committed bundle, because the install and vite build steps rewrite tracked files (the lockfile, the ui-source-hash.txt stamp). Reach for it after editing crates/trusty-console/ui/src/, crates/trusty-console/ui-search/src/, or crates/trusty-console/ui-memory/src/ — #6155 moved the search and memory dashboards' Svelte source into that crate, and trusty-memory has no build.rs any more. |
TRUSTY_NO_KG | trusty-search daemon | Machine-wide default for skip_kg. When set to 1, true, or yes, every new index created via POST /indexes (or trusty-search index) has skip_kg=true applied automatically unless the caller explicitly sets skip_kg: false. Useful for CI machines or resource-constrained hosts where KG is never needed. |
TRUSTY_SHUTDOWN_FLUSH_TIMEOUT_SECS | trusty-search daemon (issues #874, #2922) | Explicit override for the graceful-shutdown per-index HNSW/corpus flush deadline, in seconds. When unset (the default), each index's deadline is instead scaled from its own on-disk HNSW snapshot size (30s floor + 1s per 20 MB, capped at 20 minutes) so a multi-hundred-MB index gets a workable budget instead of the old flat 10s — which was short enough to time out mid-write on large indexes before atomic tmp+rename hardening landed. Set this only to force an exact value (e.g. a constrained CI/test environment); any positive integer wins outright over size-based scaling for every index. 0 or unset falls back to size scaling. |
TRUSTY_VECTOR_QUANT | trusty-search daemon (issues #709, #6822) | Scalar precision newly built HNSW indexes use: f16 (the default since #6822 — ≈2× smaller vectors, recall@10 = 1.00 in the ooc_quick_wins fixture, no measured loss), f32 / none (full precision, opt in to keep the pre-#6822 behaviour), or i8 (≈4× smaller, recall ≈0.96 — stays opt-in). Applied at index creation only. An existing snapshot records its own scalar kind in its header and usearch rebuilds the metric from there on every open, so the default flip re-quantizes nothing and a forced reindex does not either — it upserts into the store object built at warm-boot. Convert an existing index with trusty-search quantize --dry-run then trusty-search quantize --to f16 (POST /indexes/:id/quantize). GET /indexes/:id/status reports what the LIVE index holds as semantic_coverage.vector_quant. |
TRUSTY_HNSW_DEMOTE_COOLDOWN_SECS | trusty-search daemon (issue #6826) | Seconds a WRITTEN HNSW index must go without a further write before the idle sweep persists it and re-opens it as an Index::view, releasing its heap copy. Default 300; 0, off, false, no, disabled, or none disables the demote; anything else unparseable warns and falls back to the default. TRUSTY_HNSW_REVIEW_IDLE gates BOTH demote paths — it is the kill switch for heap→view demotion as a mechanism, so turning it off disables this one too; this knob turns off only the write-cooldown path. TRUSTY_HNSW_MMAP_SERVE promotes an index to a heap copy on its first write, and the TRUSTY_HNSW_REVIEW_IDLE sweep's own trigger only fires when the on-disk snapshot already matches the graph — which a written index never does until something saves it. This knob covers that case: 76 MB of mapped file against 9 GB of heap on the 128 GB reference host. The cooldown only decides WHEN to try; a write that arrives during or after the save is never lost, because the demote re-checks under the same HNSW write lock every writer takes. id_to_key / key_to_id stay heap-resident either way. |
TRUSTY_SHUTDOWN_FLUSH_CONCURRENCY | trusty-search daemon (issue #2922) | Max number of indexes flushed concurrently during graceful shutdown. Default 4. Previously all indexes flushed strictly sequentially, so total shutdown time was N × per-index timeout; running a bounded number in parallel keeps a fleet of small/fast indexes from queuing behind one large one while still bounding peak concurrent disk I/O. Must be a positive integer; 0 or unparseable falls back to the default. |
Measuring what these tune
scripts/measure-daemon-footprint.sh is the one instrument for a before/after
memory claim about either daemon — it prints one comparable phys-footprint
number plus a category breakdown, the daemon's own /health rss_mb, its
data-directory size, and its index or palace counts.
bash scripts/measure-daemon-footprint.sh search # human table
bash scripts/measure-daemon-footprint.sh memory --json # stable key set
bash scripts/measure-daemon-footprint.sh --pid 42054 # explicit pid
On macOS the number comes from footprint -f bytes <pid> (vmmap -summary
when footprint is unavailable); on Linux from /proc/<pid>/status's
RssAnon, the same reading TRUSTY_MEMORY_ENFORCE_MEASURE=anon gates on,
falling back to VmRSS. Never ps RSS — macOS undercounts it. Any path that
cannot produce a number exits 2 instead of reporting 0. Fixtures:
scripts/measure-daemon-footprint_selftest.sh (#6819).
trusty-audit
| Variable | Required by | Purpose |
|---|---|---|
TRUSTY_AUDIT_WORKDIR | trusty-audit CLI | Root directory for the auditor's working tree. Resolution precedence: --work-dir flag, then this env var, then <cwd>/trusty-audit-work. |
trusty-git-analytics (tga)
| Variable | Required by | Purpose |
|---|---|---|
TGA_AI_MARKERS | tga collect, tga backfill ai-detection-commits, tga audit (#5414) | Path to a YAML file of operator-supplied agentic markers, appended to the shipped set in collect::ai_markers::BUILTIN. Lets a target org's house footer be detected without a code change or a tga release. Unset (or empty) falls back to ~/.config/tga/ai-markers.yaml; a leading ~ is expanded. Each entry is tool (label written to commits.ai_tool), mode (full_agentic or ide_assisted), scope (trailer, message, or email), and pattern (a regex crate expression). Operator markers are appended, never interleaved, so they can only classify commits the shipped set left unmarked — they never relabel one it already catches. A file that cannot be read, parsed, or compiled is rejected whole, logged at warn!, and named in detection_disclosure(); the run continues on the builtin markers rather than failing. Unknown keys and unknown scope/mode spellings are errors, not silently skipped entries. |
TGA_RATE_LIMIT_SLEEP_BUDGET_SECS | tga collect, tga analyze, tga audit (#6565) | Total wall-clock seconds one run may spend asleep waiting out GitHub rate limits, overriding the RATE_LIMIT_SLEEP_BUDGET default of 120 s. The allowance is shared by the whole run rather than held per GitHub client — one tga collect builds three clients, so the old per-client ceiling was charged three times over and a latched breaker did not carry across them. Once the allowance is spent the breaker latches, every later GitHub call fails fast instead of issuing another rejected request, and the result is reported as truncated rather than presented as complete. A trimmed, positive integer wins; unset, empty, 0, and any unparseable value all fall back to the default — a zero allowance would latch the breaker on the first rate-limited response, so junk must never produce one. Raise it for a long multi-org sweep that legitimately needs a larger total. |
TGA_DB | tga::profile contributor profiling (#5463) | Path to the org-wide tga database that profile::selector::resolve_db_path reads. Profiling spans every repository a contributor touched, which is not necessarily the per-config database a given tga collect run writes — hence its own override rather than reusing the database: config field. Precedence: an explicit path argument, then this variable, then <data-dir>/tga/tga.db (~/Library/Application Support/tga/tga.db on macOS, ~/.local/share/tga/tga.db on Linux). A leading ~ is expanded; a blank or whitespace-only value is treated as unset and falls through to the convention default rather than resolving to an empty path. |
trusty-memory
| Variable | Required by | Purpose |
|---|---|---|
TRUSTY_MEMORY_PALACE | trusty-memory (issue #1217) | Override for the default palace ID derived from project identity. When set to a non-empty value it is slugified and used verbatim as the default palace, beating every derivation source. Precedence for the default palace: (1) TRUSTY_MEMORY_PALACE; (2) a committed .trusty-tools/trusty-memory.yaml pin file (rename-stable, keeps existing palaces from being orphaned); (3) the git owner/repo slug from remote.origin.url (bobmatnyc/trusty-tools → bobmatnyc-trusty-tools); (4) the parent/dir slug of the project root (Projects/trusty-tools → projects-trusty-tools). Per-command --palace flags still take precedence over the default at their call sites. |
TRUSTY_MEMORY_REDB_CACHE_MB | trusty-memory, and any consumer of trusty-common's memory-core stores (issue #7106) | Page-cache ceiling in megabytes applied to every palace-scoped redb database — kg.redb, index.usearch.redb, chat_sessions.redb, the payload and analytics stores, and the activity log. Default 64. redb's own default is 1 GiB per database, which across three files per palace and the 64-palace LRU cap left a ceiling nothing bounded; that is what grew the daemon from 233 MB to 11–23 GB. Read as a positive decimal integer; unset, empty, 0, or unparsable values keep the 64 MB default and log a warn naming the rejected value — the fallback is never redb's 1 GiB. Raise it on a host with one very large palace; lower it on the documented 16 GB minimum (epic #6802). |
TRUSTY_MEMORY_STARTUP_OPEN_LIMIT | trusty-memory daemon (issue #7106) | How many palaces the daemon's startup work may hold open at once — palace hydration and both BM25 sweeps share ONE budget, so the bound is a property of the process rather than of each job. Default 4. Each concurrently open palace costs roughly 90 MB of hydrated drawer table, HNSW graph and KG adjacency plus its redb page caches, so this number multiplied by that cost is the transient startup peak. Read as a positive decimal integer; unset, empty, 0, or unparsable values keep the default and log a warn naming the rejected value — startup opens are never unbounded. The bound throttles, it never skips a palace. |
TRUSTY_DREAM_MAX_CONCURRENT | trusty-memory, and any consumer of trusty-common's dream loop (issue #7106) | How many dream cycles may run at once across every palace in the process. Default 2. The daemon spawns one dream loop per resident palace and, before this bound, all of them woke in the same second and each held its palace's whole corpus while queued behind one ONNX mutex — 61 loops on the reference host, measured as a 43 GB transient at launch+300 s. One shared semaphore backs the bound: the idle scheduler loops and the on-demand palace_dream / dream_consolidate_room MCP tools all acquire from it, so a burst of manual calls cannot bypass it. Read as a positive decimal integer, once per process; unset, empty, 0, or unparsable values keep the default and log a warn naming the rejected value — an unbounded fan-out is never reachable. Raise it on a host with plenty of RAM and few palaces; the transient peak is roughly this number times one cycle's working set. |
TRUSTY_DREAM_PERMIT_WAIT_SECS | trusty-memory, and any consumer of trusty-common's dream loop (issue #7106) | How long an INTERACTIVE dream call — the palace_dream / dream_consolidate_room MCP tools — waits for a slot in the TRUSTY_DREAM_MAX_CONCURRENT bound before giving up. Default 30. On expiry the call returns an error naming the cap and how many cycles are in flight, so the caller can retry or raise the cap; it never hangs. The idle scheduler loops do NOT use this — nothing is waiting on them, so they queue indefinitely. Raise it on a host where cycles are legitimately slow: one semantic-consolidation request alone is bounded at 120 s per palace, so two of those ahead in the queue can hold every slot for minutes. Read as a positive decimal integer of seconds; unset or unparsable keeps the default. |
TRUSTY_DREAM_DISABLED | trusty-memory daemon (issue #1529) | Set to any non-empty value (convention 1) to disable autonomous dream scheduling entirely — no per-palace loops are spawned. POST /api/v1/dream/run and the palace_dream / dream_consolidate_room MCP tools still work. For CI, integration tests, and deployments that prefer explicit runs. |
trusty-mpm / tm CLI
| Variable | Required by | Purpose |
|---|---|---|
TRUSTY_MPM_ORPHAN_GC | trusty-mpm daemon (issue #1458, epic #1452) | Toggle the orphan-GC that reaps leaked, untracked, idle managed (tm-/tmpm-/trusty-mpm-, issue #1955) tmux sessions. Default ON; set to 0, false, off, or no (case-insensitive) to disable entirely. The GC is conservative and fail-closed: it only reaps a session that carries a managed prefix, is absent from BOTH the in-memory DaemonState registry and the SessionManager store, AND is genuinely idle (pane command is a bare shell with no live agent child), and only after the session has been observed orphaned on two consecutive sweeps (debounce). An untracked-but-active managed session is logged at warn! and KEPT, never killed. |
TRUSTY_MPM_ORPHAN_GC_INTERVAL_SECS | trusty-mpm daemon (issue #1458) | Override the orphan-GC sweep interval in seconds. Default 60. Must be a positive integer; 0, negative, or unparsable values fall back to the default. Because the debounce is expressed in passes, this interval also sets the effective grace window — a freshly-appeared orphan survives at least one full interval before it can be reaped. |
TRUSTY_MPM_AUTO_RESUME | trusty-mpm daemon | When 1/true, the boot-time session-manager reconcile auto-resumes every Stopped session whose tmux is gone. Default off. |
TRUSTY_MPM_ALLOW_HOST_STATE | trusty-mpm daemon/CLI (issue #5784) | Opt in to reaching host state that $HOME does not isolate — the tmux server and the host process table. core::host_state_gate compares $HOME against the home the OS password database records for this uid; when they differ, TmuxDriver::discover (the crate's only constructor for a tmux-backed driver) and discovery::discover_all both refuse, so a daemon under a throwaway $HOME cannot list, adopt, resume, or kill the operator's real tmux sessions. Fails closed, deliberately inverted from this crate's usual direction: an environment the gate cannot classify (no $HOME, no passwd entry) is refused too, because a wrong skip costs a test daemon that adopts nothing while a wrong proceed writes into live project directories. Every refusal is logged at warn! with the two homes it compared. Set to 1/true/yes/on to lift it — the way to deliberately test tmux adoption under a scratch $HOME. Default off. |
TM_DISABLE_SPAWN_DISCLAIM | trusty-mpm daemon/CLI, macOS only (issue #2997) | Operational safety valve: when set to any value, forces every claude/tmux-spawning call site in core::spawn_disclaim (the tmux-hosted managed-session path, the tm run/tm login inherited-stdio path, and the daemon's default actor-managed StreamJsonBackend piped spawn) back onto a plain, non-disclaimed spawn — i.e. Command::output()/Command::status()/tokio::process::Command::spawn() exactly as before #2819/#2997. Has no effect on non-macOS (there is no TCC there, so these paths are already a pure pass-through). Set this only if the disclaim path itself is suspected of causing a regression (e.g. an unexpected spawn failure that disappears with the valve on) — flipping it back to disclaiming re-exposes the original App-Data/media-library TCC mis-attribution storm the surrounding code fixes, so treat it as a temporary diagnostic step, not a standing configuration. |
TRUSTY_MPM_ALLOW_STALE_INSTALL | tm reinstall --binary (issue #4462) | Install from a cargo install --path source whose HEAD is behind origin/main. tm is one global binary shared by every managed session on the machine, so a stale build regresses every session at once with no version number moving to show it — the guard refuses that install by default. It refuses on positive evidence only: a directory that is not a git repository, has no origin/main, or has no usable git warns and installs. Set to any value but 0/empty to install a known-stale source deliberately, mirroring ALLOW_UNMERGED_PUBLISH=1 on the publish side. Default off. |
TRUSTY_COMPRESS_NO_RTK | tm compress, and every consumer of trusty-agents-common's tool-output compression (issue #7325) | Force the in-tree native fallback chain even where rtk is installed. Set to 1, true, yes, or on (case-insensitive, trimmed); every other value and an unset variable keep the real resolver. Compression normally prefers the external rtk pipe subprocess, which trusty_common::bin_resolve::resolve_binary finds in /opt/homebrew/bin whatever PATH says — so a tm compress test that pins native-chain output (the 80-byte size gate, byte-for-byte passthrough) passed or failed by host until this existed. It doubles as the operator escape hatch for a broken or slow local rtk. The variable can only ever downgrade to the native chain: reporting compression_path=rtk_binary still requires a subprocess that ran and exited zero. |
CLAUDE_CODE_DISABLE_AUTO_MEMORY | Set BY tm on every managed claude spawn (issue #7685) — not read by any trusty binary | Claude Code's own switch for auto memory (MEMORY.md), documented at https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory. core::runtime::claude_code::env_bin_prefix assigns =1 on the env prefix of every spawn and resume WHEN AND ONLY WHEN trusty-memory answered a health probe at launch (core::memory_reachable): trusty-memory is the memory, and auto memory is the fallback that carries a session while trusty-memory is down (owner ruling 2026-09-12). Per those docs the variable also wins over a subagent's own memory: frontmatter field, so when present it forecloses an agent asset opting back in. It reaches only the claude child tm spawns; the project-tier autoMemoryEnabled: false key core::session_launch::settings writes — under the same condition — covers a bare claude launched in the same project. tm doctor's auto_memory row grades both halves against its own reachability probe, tm doctor --fix --yes writes the settings half, and tm memory import-auto-memory migrates an existing MEMORY.md into the palace. |
TRUSTY_MPM_URL | tm / trusty-mpm CLI (all subcommand families) | Explicit override for the daemon base URL every tm subcommand talks to. Always wins outright when set to a non-empty value — bypassing the trusty-console gateway proxy, the daemon.lock file, and the compiled-in default (http://127.0.0.1:7880) unconditionally, even when the value you set happens to equal that default verbatim. Precedence: (1) --url flag / TRUSTY_MPM_URL env var, if actually supplied; (2) the trusty-console gateway (http://{console}/api/mpm) if the console is running and reachable — when trusty-console is up, it proxies ANY /api/mpm/{path} to the daemon so all tm traffic can flow through the unified web UI (audit logging, future auth); (3) ~/.trusty-mpm/daemon.lock (records the daemon's actual bound address, which may be an ephemeral port); (4) the compiled-in default. Set TRUSTY_MPM_URL explicitly to bypass the console proxy for a specific invocation. See #2487. |
Cargo build environment for a dispatched engineer (#6868)
Not read by any trusty binary — these are the cargo/workspace variables
tm doctor's rust_build_env row RESOLVES and prints, for a PM to paste into
an engineer brief. An agent's shell environment does not persist between tool
calls, so they are prefixed inline on every cargo invocation, never exported.
| Variable | Resolved from | Purpose |
|---|---|---|
CARGO_TARGET_DIR | build.cargo_target_dir in ~/.trusty-tools/trusty-mpm/config.yaml, defaulting to ~/.trusty-tools/cargo-target/<owner>/<repo> derived from the project's origin remote | One shared target directory per repo, so every worktree of that repo reuses warm artifacts instead of building cold. Cargo's target lock serialises concurrent builds sharing it, which is wanted — six concurrent cold builds crashed the reference host on 2026-08-08. |
CARGO_BUILD_JOBS | build.build_jobs, defaulting to half the host's cores with a floor of 2 | Caps one build's CPU and RAM so a sibling agent's build is not starved or OOM-killed (the exit-137 shape in common-pitfalls.md). |
RUSTC_WRAPPER | build.sccache; emitted as RUSTC_WRAPPER=sccache only when that key is true | Opt-in shared compilation cache. Measured neutral on this path-crate-heavy workspace, because incremental artifacts are not cacheable. tm reports whether build.rustc-wrapper is wired in ~/.cargo/config.toml and never writes it — that file is machine-global for every Rust project on the host. |
SKIP_UI_BUILD | Always 1 on the printed line | Skips the Svelte UI build step in the crates that embed one, which a Rust-only gate never needs. |
The full build: section, its defaults and the row's status rules are in
config-convention.md.
Active-project residency (trusty_common::residency)
Shared contract for pinning trusty-mpm's active-project set against a
consumer's own idle-eviction policy (issue #7087). Slice 1a lands the
contract and the client (trusty_common::mpm_rpc::fetch_active_projects)
alone — nothing reads these four yet; a producer (trusty-mpm, slice 1b) and
consumers (trusty-memory, trusty-search; slices 2–3) wire them up in later
slices. Each is parsed by a pure function taking the raw Option<&str>
value (residency_pull_secs, residency_stale_secs, residency_grace_secs,
residency_enabled) — the future ticker reads the variable and passes it in.
| Variable | Required by | Purpose |
|---|---|---|
TRUSTY_RESIDENCY_PULL_SECS | any future consumer of trusty_common::residency | How often a consumer's pull ticker re-fetches the active-project set from trusty-mpm. Default 30. Unset, empty, or unparsable keeps the default. |
TRUSTY_RESIDENCY_STALE_SECS | any future consumer of trusty_common::residency | How long ResidencySnapshot trusts a pulled set with no further successful pull before treating it as stale and clearing the pin. Default 600. Unset, empty, or unparsable keeps the default. |
TRUSTY_RESIDENCY_GRACE_SECS | any future consumer of trusty_common::residency | How long a resident handle that has fallen out of the active set is kept before a consumer parks or evicts it. Default 120. Unset, empty, or unparsable keeps the default. |
TRUSTY_RESIDENCY | any future consumer of trusty_common::residency | Set to off (case-insensitive, whitespace-trimmed) to disable residency pinning outright. Any other value, including garbage, leaves pinning on — a typo must never silently disable it. |