The Ultimate Local AI Coding & Memory Stack: Conductor, Claude Code, RTK, Headroom, and Obsidian
A comprehensive instructional guide on building a local, memory-backed, and token-optimized AI development setup using Claude Code, Conductor, Graphify, Headroom, Obsidian, and RTK.
Building a Local AI Coding & Memory Stack
In modern software engineering, AI assistants like Claude and Codex have transitioned from basic copy-paste utilities to fully active agents operating in our development environments. However, scaling these agents across complex, multi-project workflows introduces friction: sky-high API token bills, lack of persistent cross-session memory, and βcontext overloadβ where models get lost in codebase noise.
To address these hurdles, I have wired together a seven-layer local AI coding and memory stack. It turns Claude Code into a project-aware, memory-backed agent capable of executing complex code tasks securely, efficiently, and with context preservation.
All layers run locally on your machine, with no cloud interaction beyond direct, secure model API calls. Below is a detailed, instructional blueprint on how to configure and run this exact setup.
High-Level Architecture
Here is how the seven layers cooperate to optimize reasoning, control costs, and capture context:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ββββββββββββββββββββββββββββββββββββββββββββββββ
β Claude Code (Primary Agent) β
β instructions Β· hooks Β· skills Β· plugins β
ββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ¬βββββββββββ
β β β β
(Hooks) β (MCP) β (Sub- β (Skill) β
β β agent) β β
βΌ βΌ βΌ βΌ
βββββββββββββββ ββββββββββββ ββββββββββ βββββββββββββββββββββββ
β RTK β β Obsidian β β Codex β β Skills β
β (PreToolUse β β Vault β β CLI β β graphify, ponytail, β
β hook) β β (MCP + β β plugin β β rails-*, pr-review β
ββββββββ¬βββββββ β hooks) β ββββββ¬ββββ βββββββββββββββββββββββ
β ββββββ¬ββββββ β
βΌ β βΌ
βββββββββββββββ β βββββββββββββ
β Headroom β βΌ β OpenAI β
β Proxy :8787 β ββββββββββ β API β
ββββββββ¬βββββββ βObsidianβ βββββββββββββ
β βGit β
βΌ ββββββββββ
βββββββββββββββ
β Anthropic β
β API β
βββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββ
β Conductor β
β Orchestrates parallel worktrees, β
β each with its own agent session β
ββββββββββββββββββββββββββββββββββββββββ
Letβs break down each layer and construct the environment step-by-step.
Layer 1: Claude Code with Layered Instructions, Hooks, and Skills
Claude Code is the primary agent. Configuration is not monolithic β it loads in a strict cascade from most-global to most-local, and a hook system allows you to intercept and transform agent behavior at runtime.
Step 1: Establish Your Instruction Cascade
Claude Code loads instructions in this order, each layer overriding or augmenting the previous:
~/.claude/CLAUDE.mdβ Machine-global rules. Apply everywhere, every project.<REPO>/CLAUDE.mdβ Team-visible project conventions, checked into version control.<REPO>/AGENTS.mdβ Repository structure, style conventions, and gotchas (referenced via@AGENTS.mdfrom the project CLAUDE.md).- Subdirectory
AGENTS.md(e.g.<REPO>/app/javascript/AGENTS.md) β Activates only when working inside that directory. Use this to scope frontend-specific rules so they donβt pollute backend tasks.
Use @filename imports to compose instructions from external files rather than maintaining huge, duplicated configs:
1
2
3
4
5
6
7
8
9
# ~/.claude/CLAUDE.md
@RTK.md
# Global Directives
- Always run `/graphify query` for any architectural or behavioral question
before opening code files.
- Favor using `rtk` commands over native shell utilities to keep payload
sizes optimized.
The @RTK.md import pulls in a separate file (~/.claude/RTK.md) with RTK-specific usage rules, keeping the main file focused.
Step 2: Wire Up the Hook System
Hooks are the key mechanism that transforms Claude Code from a passive assistant into a self-optimizing agent. They are configured in ~/.claude/settings.json and fire at specific lifecycle events:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/rtk-rewrite.sh"
}
]
}
],
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/graphify-nudge.sh"
}
]
}
],
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 ~/.claude/skills/obsidian-second-brain/hooks/load_vault_context.py"
}
]
}
],
"PostCompact": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "~/.claude/skills/obsidian-second-brain/hooks/obsidian-bg-agent.sh",
"timeout": 10,
"async": true
}
]
}
]
}
}
Each hook serves a distinct purpose:
| Hook Event | What It Does |
|---|---|
| PreToolUse (Bash) | Intercepts every shell command and rewrites it through RTK for token optimization β completely transparent |
| UserPromptSubmit | Scans your prompt for behavior/architecture questions and injects a reminder to query Graphify first |
| SessionStart | Loads Obsidian vault context (_CLAUDE.md) into the session when working inside the vault directory |
| PostCompact | When the context window is compacted, spawns a background agent that harvests vault-worthy items from the transcript |
Step 3: Install Plugins
Claude Code supports a plugin system for integrating external tools. Enable plugins in settings.json:
1
2
3
4
5
6
7
8
{
"enabledPlugins": {
"headroom@headroom-marketplace": true,
"codex@openai-codex": true,
"obsidian@obsidian-skills": true,
"discord@claude-plugins-official": true
}
}
Plugins add MCP tools, hooks, skills, and subagent types. The Codex plugin, for example, registers the codex:codex-rescue subagent and several slash commands (/codex:rescue, /codex:review, /codex:status).
Step 4: Set Up Skills
Skills are packaged instruction sets that activate on slash commands. They live in ~/.claude/skills/ as directories containing a SKILL.md file:
1
2
3
4
5
6
7
8
9
10
11
12
~/.claude/skills/
βββ graphify/SKILL.md # /graphify β code-to-knowledge-graph
βββ obsidian-second-brain/ # /obsidian-* β vault management
β βββ SKILL.md
β βββ hooks/ # SessionStart + PostCompact hooks
βββ pr-review/SKILL.md # /pr-review β parallel multi-reviewer PR review
βββ pull-request/SKILL.md # /pull-request β create PR with Linear issue
βββ resolve-fault/SKILL.md # /resolve-fault β Honeybadger fault β PR
βββ review-fix/SKILL.md # /review-fix β self-review and fix
βββ ponytail -> ~/code/agent-skills/skills/ponytail # symlink
βββ rails-best-practices-core -> ... # symlink
βββ ...
Symlinked skills point to a shared ~/code/agent-skills/ repository, so updates to the skills repo propagate to all projects without manual copying.
Layer 2: Headroom (Context Compression Proxy)
Headroom is the single biggest token saver in this stack. It runs as a local HTTP proxy that compresses everything flowing between your agent and the model API β tool outputs, file contents, conversation history β before it reaches the LLM.
How It Works
Headroom intercepts API calls by sitting between Claude Code and the Anthropic API. You point Claude Code at the proxy instead of the real API:
1
2
3
4
5
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8787"
}
}
This single environment variable routes all model calls through Headroomβs compression pipeline. No code changes, no wrapper scripts β Claude Code thinks itβs talking directly to Anthropic.
Step 1: Install and Start
1
2
pip install "headroom-ai[all]"
headroom proxy --port 8787
Or wrap your agent directly:
1
headroom wrap claude
Step 2: Understand the Compression Pipeline
Headroom applies multiple compression strategies based on content type:
1
2
3
4
5
6
7
8
9
10
11
12
Agent prompt / tool output
β
βββββ΄βββββββββββββββββββββββββββββββββββββββββββ
β Headroom (runs locally) β
β CacheAligner β ContentRouter β CCR β
β ββ SmartCrusher (JSON) β
β ββ CodeCompressor (AST) β
β ββ Kompress-base (prose) β
βββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β compressed prompt + retrieval tool
βΌ
LLM provider
- SmartCrusher β Compresses JSON (tool outputs, API responses) by removing structural noise
- CodeCompressor β Uses AST-level analysis to strip non-essential code while preserving semantic meaning
- Kompress-base β A HuggingFace model that compresses natural language while preserving key claims
- CacheAligner β Stabilizes prompt prefixes so provider KV caches actually hit, reducing costs further
- CCR (Compressed Context Retrieval) β Stores originals locally; the LLM can call
headroom_retrieveif it needs the full version of something that was compressed
Step 3: Verify Savings
1
2
headroom perf # one-shot savings report
headroom dashboard # live dashboard (proxy must be running)
On real agent workloads, Headroom typically delivers 47β92% token reduction depending on content type:
| Workload | Before | After | Savings |
|---|---|---|---|
| Code search (100 results) | 17,765 | 1,408 | 92% |
| SRE incident debugging | 65,694 | 5,118 | 92% |
| GitHub issue triage | 54,174 | 14,761 | 73% |
| Codebase exploration | 78,502 | 41,254 | 47% |
Headroom also reduces output tokens β it trims ceremony and restated code from what the model writes back, not just what you send.
Step 4: Persistent Deployment with launchd
For a βset and forgetβ proxy, deploy it as a macOS LaunchAgent:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- ~/Library/LaunchAgents/com.user.headroom-proxy.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.headroom-proxy</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/headroom</string>
<string>proxy</string>
<string>--port</string>
<string>8787</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/headroom-proxy.log</string>
<key>StandardErrorPath</key>
<string>/tmp/headroom-proxy.err</string>
</dict>
</plist>
Load it once:
1
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.user.headroom-proxy.plist
Now Headroom starts automatically on login and restarts if it crashes.
Layer 3: Conductor (Parallel Worktree Agents)
Conductor is an orchestration app that spawns parallel git worktrees under a canonical path, such as ~/conductor/workspaces/<project>/<workspace-name>/. Each workspace hosts an isolated, non-interfering Claude Code session. This is how you scale from βone agent on one taskβ to βmany agents on many tasksβ without branch conflicts or context pollution.
Step 1: Global Conductor Configuration
Conductorβs global settings live at ~/.conductor/settings.toml. This configures which model each agent uses, git conventions, and paths to agent executables:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"$schema" = "https://conductor.build/schemas/settings.schema.json"
claude_code_executable_path = "~/.local/bin/claude"
codex_executable_path = "/opt/homebrew/bin/codex"
[git]
branch_prefix_type = "github_username"
delete_branch_on_archive = true
[models]
default = "opus-4-6-1m"
review = "opus-4-6-1m"
[models.codex]
default_thinking_level = "high"
review_thinking_level = "high"
Key settings:
branch_prefix_type = "github_username"β Branches auto-prefix with your GitHub handle for easy identificationdelete_branch_on_archiveβ Cleaned up branches donβt litter your remote- Model selection β Different models for different tasks. The 1M context variant is essential for large codebases
Step 2: Per-Project Setup Scripts
Each project has a .conductor/settings.local.toml file (gitignored, private to your machine) that defines a setup script. This script runs automatically when Conductor creates a new worktree:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# <REPO>/.conductor/settings.local.toml
"$schema" = "https://conductor.build/schemas/settings.repo.schema.json"
file_include_globs = ".env*\n.gitignore\n"
[scripts]
run = "dev"
run_mode = "concurrent"
setup = """#!/usr/bin/env bash
set -euo pipefail
ROOT="$(git rev-parse --show-toplevel)"
MAIN_REPO="${CONDUCTOR_ROOT_PATH:-$HOME/code/my-project}"
# Ensure PATH includes language version managers
export RBENV_ROOT="${RBENV_ROOT:-$HOME/.rbenv}"
export PATH="$RBENV_ROOT/shims:$RBENV_ROOT/bin:$PATH"
if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
source "$NVM_DIR/nvm.sh"
nvm use 22 --silent || nvm install 22 --no-progress
fi
echo "Root: $ROOT"
# Symlink graphify-out from the main repo into this worktree
if [[ "$ROOT" != "$MAIN_REPO" ]]; then
GRAPHIFY_BIN="$HOME/.local/bin/graphify"
if [[ ! -d "$MAIN_REPO/graphify-out" && -x "$GRAPHIFY_BIN" ]]; then
echo "graphify-out missing - rebuilding (AST only, no LLM)"
( cd "$MAIN_REPO" && "$GRAPHIFY_BIN" update . ) \\
|| echo "graphify rebuild failed - worktree will have no graph"
fi
if [[ -d "$MAIN_REPO/graphify-out" && ! -e "$ROOT/graphify-out" ]]; then
ln -s "$MAIN_REPO/graphify-out" "$ROOT/graphify-out"
echo "Linked graphify-out from $MAIN_REPO"
fi
fi
# Install dependencies
bundle install
yarn install
# Copy credentials from the main repo (if applicable)
SRC_KEY="$MAIN_REPO/config/credentials/development.key"
DEST_KEY="$ROOT/config/credentials/development.key"
if [[ -f "$SRC_KEY" ]]; then
mkdir -p "$(dirname "$DEST_KEY")"
cp "$SRC_KEY" "$DEST_KEY"
echo "Copied development.key"
fi
"""
Key design decisions:
- Inline script in TOML β The setup script is embedded directly in the settings file, not a separate bash file. This keeps the entire workspace config self-contained.
- Graphify symlink β Every worktree shares one canonical
graphify-out/from the main repo. If the graph is missing, it rebuilds automatically (AST-only, no LLM required). - Auto-rebuild β If the graphify-out directory is missing from the main repo, the setup script runs
graphify update .to rebuild it before symlinking. file_include_globsβ Conductor copies.env*and.gitignorefiles into new worktrees, so environment config is always present.
Step 3: Working with Workspaces
Conductor names each workspace after a city. When you open the Conductor app and create a new workspace for a project, you get something like:
1
2
3
4
5
~/conductor/workspaces/my-project/
βββ tokyo/ β feature branch A
βββ berlin/ β bug fix B
βββ nairobi/ β refactor C
βββ amsterdam/ β review task D
Each has its own branch, its own Claude session, and its own running dev server. The setup script runs once on creation, ensuring every workspace is immediately ready for work with no manual setup.
Layer 4: Graphify (Code to Knowledge Graph)
Instead of feeding hundreds of raw code lines to the model to search for a bug, we use Graphify β a CLI tool that constructs a local knowledge graph of your codebase with community detection, an audit trail (EXTRACTED/INFERRED/AMBIGUOUS edges), and multiple query modes.
Step 1: Build the Graph
1
2
3
4
graphify . # full pipeline on current directory
graphify . --mode deep # thorough extraction, richer edges
graphify . --update # incremental - only new/changed files
graphify . --obsidian --obsidian-dir ~/vaults/my-project-graph # export to Obsidian
Graphify produces two key artifacts:
- Machine Graph (
graphify-out/graph.json+GRAPH_REPORT.md) β Queried directly by Claude Code - Visual Export β An Obsidian vault with interlinked markdown files and a
graph.canvasshowing relationships between controllers, models, jobs, and services
Step 2: Query the Graph from Claude
Claude can query the graph directly via the /graphify query skill:
1
2
3
4
5
/graphify query "How does authentication work in this app?" # BFS - broad context
/graphify query "Trace the payment flow" --dfs # DFS - follow one path deep
/graphify query "What calls the UserMailer?" --budget 1500 # cap answer at N tokens
/graphify path "AuthModule" "Database" # shortest path between concepts
/graphify explain "BackgroundWorker" # plain-language node explanation
Step 3: Auto-Enforce Graphify-First with a Hook
The real power is making Claude use Graphify automatically. The graphify-nudge.sh hook (registered as a UserPromptSubmit hook) scans every prompt you submit for behavior/architecture questions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
# ~/.claude/hooks/graphify-nudge.sh
set -u
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty')
CWD=$(echo "$INPUT" | jq -r '.cwd // .working_directory // empty')
# Only fire when graphify-out exists in the current project
if [ ! -f "$CWD/graphify-out/graph.json" ]; then
exit 0
fi
# Pattern-match behavior/flow/architecture questions
if echo "$PROMPT" | grep -qiE \
'how (does|do|is|are|can)|what calls|where is .+ (used|called)|why does|walk me through|explain (the|how)|architecture|data ?flow|control ?flow|trace the|life ?cycle|end-to-end'; then
jq -n '{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "GRAPHIFY REMINDER: A behavior/flow question was detected and graphify-out/graph.json is present. Your FIRST tool call MUST be /graphify query. Only Read/Grep the files it surfaces."
}
}'
fi
When you ask βHow does authentication work?β, the hook injects a context reminder into the prompt that forces Claude to query the graph first, then only read the specific files the graph identifies. No more reading 30 files to answer a cross-cutting question.
Step 4: Automate with a Weekly launchd Agent
To ensure the graph never goes stale, configure a background launchd job on macOS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- ~/Library/LaunchAgents/com.user.graphify-update.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.graphify-update</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>~/.local/bin/graphify-update.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>1</integer>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</dict>
</plist>
The companion script:
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# ~/.local/bin/graphify-update.sh
REPO_PATH="$HOME/code/my-project"
VAULT_PATH="$HOME/vaults/my-project-graph"
cd "$REPO_PATH"
graphify update .
graphify export obsidian --dir "$VAULT_PATH"
echo "Graphify update completed at $(date)"
Layer 5: Obsidian as a βSecond Brainβ
A key design decision: nothing durable is written to Claudeβs built-in memory. Built-in model memory is transient and difficult to version. Instead, a dedicated Obsidian vault hosts all durable cross-project memory, and a pair of hooks keep it synchronized with your agent sessions automatically.
Step 1: Enforce the AI-First Operating Manual
Create a root _CLAUDE.md file in your vault. This file is automatically loaded into Claude sessions via the SessionStart hook when working inside the vault:
1
2
3
4
5
6
7
8
9
10
11
12
# _CLAUDE.md (vault root)
## AI-First Note Writing Rules:
1. **Self-Contained**: Each note must be understandable without requiring other context.
2. **Context Preamble**: Every note begins with a 2-3 sentence summary for future AI sessions.
3. **Rich Frontmatter**:
```yaml
type: logic-explainer
date: 2026-07-17
topic: Authentication
confidence: high
ai-first: true
- Time Markers: Reference events with precise dates: βAs of 2026-07β¦β.
- Wiki Links: Link entities with
[[wikilinks]]so Conductor/Claude can parse the graph. ```
Step 2: The SessionStart Hook (Vault Context Loader)
The load_vault_context.py script fires at session start and checks whether the current working directory is inside the Obsidian vault. If so, it injects the vaultβs _CLAUDE.md into the agentβs context:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# ~/.claude/skills/obsidian-second-brain/hooks/load_vault_context.py
import json, os, sys
from pathlib import Path
def main():
vault = os.environ.get("OBSIDIAN_VAULT_PATH", "")
if not vault:
return 0
payload = json.load(sys.stdin)
cwd = payload.get("cwd", "")
# Only inject context when working inside the vault
if not cwd.startswith(vault):
return 0
claude_md = Path(vault) / "_CLAUDE.md"
if not claude_md.is_file():
return 0
content = claude_md.read_text(encoding="utf-8")
output = {
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": f"Vault operating manual:\n\n{content}"
}
}
json.dump(output, sys.stdout)
return 0
if __name__ == "__main__":
raise SystemExit(main())
Configure the vault path in settings.json:
1
2
3
4
5
6
{
"env": {
"OBSIDIAN_VAULT_PATH": "/path/to/your/vault",
"OBSIDIAN_BG_AGENT_ENABLED": "1"
}
}
Step 3: The PostCompact Hook (Background Vault Agent)
This is the most powerful hook in the system. When Claudeβs context window fills up and gets compacted (summarized), the PostCompact hook spawns a background Claude session that reads the compacted transcript and propagates everything worth preserving to the vault:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash
# ~/.claude/skills/obsidian-second-brain/hooks/obsidian-bg-agent.sh
VAULT="${OBSIDIAN_VAULT_PATH:-}"
[[ -z "$VAULT" ]] && exit 0
[[ "${OBSIDIAN_BG_AGENT_ENABLED:-0}" != "1" ]] && exit 0
INPUT=$(cat)
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // ""')
[[ -z "$TRANSCRIPT" || ! -f "$TRANSCRIPT" ]] && exit 0
# Extract the compaction summary from the transcript
SUMMARY=$(jq -rc 'select(.isCompactSummary == true) | .message.content' \
"$TRANSCRIPT" | tail -n 1)
[[ -z "$SUMMARY" ]] && exit 0
TODAY=$(date +%Y-%m-%d)
# Build the prompt for the background agent
PROMPT="You are an autonomous Obsidian vault agent. The Claude session was just
compacted. Propagate everything worth preserving from the summary to the vault.
VAULT: $VAULT
TODAY: $TODAY
SESSION SUMMARY:
$SUMMARY
INSTRUCTIONS:
1. Read _CLAUDE.md at the vault root - follow its rules exactly.
2. Identify vault-worthy items: decisions, tasks, people, projects, dev work,
ideas, learnings.
3. Before creating any note, search for an existing one. Never duplicate.
4. Update today's daily note with links to everything you touched.
5. Propagate: nothing saved in isolation - every write ripples to the daily
note, boards, and linked notes."
# Spawn the background agent (fire-and-forget)
(cd "$VAULT" && claude --dangerously-skip-permissions -p "$PROMPT" \
>> /tmp/obsidian-bg-agent.log 2>&1) &
exit 0
This means every long Claude session automatically captures decisions, code changes, and project context into the vault β without you doing anything.
Step 4: The Obsidian Skill Catalog
The obsidian-second-brain skill exposes a rich set of slash commands for manual vault interaction:
| Command | Purpose |
|---|---|
/obsidian-save | Save conversation highlights to the vault |
/obsidian-find <topic> | Smart vault search with context |
/obsidian-log | Log a dev session to the vault |
/obsidian-daily | Create/update todayβs daily note |
/obsidian-project | Create/update a project note |
/obsidian-person | Create/update a person note |
/obsidian-task | Add a task to the right kanban board |
/obsidian-decide | Record a decision (lightweight or formal ADR) |
/obsidian-recap | Summarize a time period from vault history |
/obsidian-health | Vault health check β contradictions, gaps, staleness |
/obsidian-synthesize | Auto-scan for unnamed patterns, write synthesis pages |
Step 5: Set Up Obsidian Git Plugin for Version Control
- In Obsidian, go to Community Plugins, search for Obsidian Git, and install.
- Configure backup intervals to trigger every 5 to 10 minutes. This provides a timestamped memory log of how your notes and reasoning evolve over time.
Layer 6: Codex CLI as a Second-Opinion Subagent
Sometimes Claude gets stuck in a recursive loop or needs a second perspective. For this, the Codex CLI (OpenAI) runs as a Claude Code plugin that registers a subagent called codex:codex-rescue.
Step 1: Install the Plugin
The Codex plugin is installed via Claude Codeβs plugin marketplace system. Once enabled, it registers:
codex:codex-rescueβ A subagent that forwards tasks to Codex CLI for independent investigation/codex:rescueβ Slash command for manual delegation/codex:reviewβ Ask Codex for an adversarial code review/codex:statusβ Check on a background Codex task
Step 2: Configure Codex in Conductor
Conductorβs global settings specify the Codex executable path and thinking levels:
1
2
3
4
5
6
# ~/.conductor/settings.toml
codex_executable_path = "/opt/homebrew/bin/codex"
[models.codex]
default_thinking_level = "high"
review_thinking_level = "high"
Step 3: How the Rescue Agent Works
The codex-rescue agent is a thin forwarding wrapper. When Claude encounters a blocker, it spawns a Codex task through the shared runtime:
1
2
3
4
5
Claude (stuck on a bug)
β spawns codex:codex-rescue subagent
β subagent calls: node codex-companion.mjs task "<prompt>" --write
β Codex CLI runs independently, reads/writes code
β result returns to Claude's context
Selection guidance built into the agent:
- Proactive β Donβt wait for the user to ask; trigger when Claude is stuck
- Bounded β Donβt grab simple tasks the main thread can finish quickly
- Write-capable β Default to
--writemode so Codex can apply its fix directly - Resume-aware β If continuing prior work, adds
--resume-lastautomatically
Layer 7: RTK (Rust Token Killer) β The Transparent Proxy
RTK is a high-performance CLI wrapper written in Rust. Unlike Headroom (which compresses at the API level), RTK operates at the shell command level β it intercepts git, cat, grep, find, and other CLI tools, strips noise from their output, and returns a token-optimized result.
Step 1: The PreToolUse Hook (Not Aliases)
RTK is wired into Claude Code via a PreToolUse hook β not shell aliases. This is critical: the hook intercepts the Bash tool at the Claude Code level, rewrites the command through rtk rewrite, and returns the optimized version with an automatic permission grant:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
# ~/.claude/hooks/rtk-rewrite.sh
# Read the tool input from Claude Code
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
[ -z "$CMD" ] && exit 0
# Ask RTK to rewrite the command
REWRITTEN=$(rtk rewrite "$CMD" 2>/dev/null) || exit 0
# If unchanged, let it pass through
[ "$CMD" = "$REWRITTEN" ] && exit 0
# Return the rewritten command with auto-allow
ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input')
UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd')
jq -n \
--argjson updated "$UPDATED_INPUT" \
'{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "RTK auto-rewrite",
"updatedInput": $updated
}
}'
What this means in practice: when Claude runs git status, the hook rewrites it to rtk git status. When Claude runs cat schema.rb, the hook rewrites it to rtk read schema.rb. The agent never knows it happened β it just gets smaller, cleaner output.
Step 2: Use RTK Rules to Save Tokens
The ~/.claude/RTK.md file (imported via @RTK.md) teaches Claude when to prefer RTK commands:
- For files exceeding 50KB, use
rtk read <path>to get a structurally filtered view - For pattern search:
rtk grep <pattern> <path>instead ofcat | grep - For file discovery:
rtk findinstead of rawfind
Step 3: Monitor Your Savings
1
2
3
rtk gain # Show cumulative token savings
rtk gain --history # Show per-command savings history
rtk discover # Analyze Claude Code transcripts for missed RTK opportunities
Typical results: 40β90% reduction in tokens on common operations like directory listing, git diffs, and file reads.
Put It All Together: The AI Development Flow
When you ask Claude a complex question like βHow does authentication work inside this microservice?β, here is how the full stack operates:
Conductor created this workspace as an isolated worktree with its own branch. The setup script ran automatically, symlinking
graphify-out/and installing dependencies.Claude reads the instruction cascade: global
~/.claude/CLAUDE.mdβ projectCLAUDE.mdβ@AGENTS.mdβ any subdirectoryAGENTS.mdfiles.The UserPromptSubmit hook fires.
graphify-nudge.shdetects that your question is a behavior/architecture question and injects a reminder: βYour FIRST tool call MUST be/graphify query.βClaude queries Graphify.
/graphify query "How does authentication work?"does a BFS traversal ofgraphify-out/graph.jsonand returns the specific files and relationships involved.Claude reads only the named files. The
PreToolUsehook intercepts everycatandgrepcommand, transparently rewriting them through RTK for token-optimized output.Headroom compresses the entire exchange. Every API call flows through the local proxy on port 8787, where SmartCrusher compresses tool outputs and CodeCompressor strips non-essential code. The model sees 50β90% fewer tokens without losing semantic content.
If Claude encounters an unexpected blocker, it triggers
codex:codex-rescueβ spawning a Codex CLI task for a second opinion, which runs independently and returns its findings.Once the solution is found, Claude uses
/obsidian-saveto write a permanent record in the vault.When the context window eventually fills and gets compacted, the PostCompact hook fires β spawning a background agent that extracts decisions, code changes, and learnings from the transcript into the vault automatically.
Obsidian Git auto-commits the vault changes every few minutes, preserving your progress across sessions.
By combining transparent token optimization at two levels (Headroom at the API layer, RTK at the shell layer) with a structured local knowledge graph (Graphify) and persistent, hook-driven memory (Obsidian), this setup creates a developer workspace that is fast, context-aware, and cost-efficient β with knowledge compounding across sessions instead of evaporating.
