From anchor
Initializes Context Companion session: suggests modules from recent git changes, prompts to load project specs or start fresh, checks and optionally reconciles prior unreconciled sessions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/anchor:companionThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Do these things in order. No greeting. No preamble.
Do these things in order. No greeting. No preamble.
First, gather module suggestions:
cat .companion/modules.json 2>/dev/null || echo "[]"
git diff --name-only HEAD~5 2>/dev/null
Match changed files to module paths from modules.json to determine suggestions (modules whose paths appear in recent git changes get the ← suggested label).
Use AskUserQuestion:
question: "What are we working on today?"
options: [
"<module> ← suggested", (modules matching recent git files, up to 4)
"<module>", (remaining modules alphabetically)
"Nothing — start fresh"
]
multiSelect: true
uv run python -c "
import json
from pathlib import Path
p = Path('.companion/product.json')
if not p.exists():
print('0')
else:
ref = json.loads(p.read_text())
config = json.loads(Path(ref['config']).read_text())
spec_loc = Path(config['spec_location'])
cp_path = Path(ref['config']).parent / 'reconciled_sessions.json'
checkpoint = json.loads(cp_path.read_text()) if cp_path.exists() else {}
changes_dir = spec_loc / 'openspec' / 'changes'
unreconciled = []
if changes_dir.exists():
for d in changes_dir.iterdir():
if d.is_dir() and d.name not in checkpoint:
if (d / 'incremental.json').exists():
unreconciled.append(d.name)
print(len(unreconciled))
"
If count > 0, use AskUserQuestion:
question: "Found N unreconciled sessions from previous runs. Reconcile now? (merges captured decisions into your canonical spec)"
options: ["Yes, reconcile now", "Skip — I'll do it later"]
If yes, run reconcile:
uv run python ${CLAUDE_SKILL_DIR}/../seed/scripts/reconcile.py \
"$(uv run python -c "import json; print(json.loads(open('.companion/product.json').read())['config'])")" \
.companion/modules.json
If 0 or skip → continue to Step 2.
If "Nothing — start fresh" selected → skip to Step 3.
If modules selected:
uv run python -c "
import json
from pathlib import Path
ref = json.loads(Path('.companion/product.json').read_text())
config = json.loads(Path(ref['config']).read_text())
modules = json.loads(Path('.companion/modules.json').read_text())
module_names = [m['name'] for m in modules]
print(config['spec_location'])
print(','.join(module_names))
"
question: "<module> doesn't exist yet. Create it as a new module?"
options: ["Yes — create it", "Skip — don't load it"]
If yes, ask the user for a one-line description, then create it:
uv run python -c "
import json
from pathlib import Path
modules = json.loads(Path('.companion/modules.json').read_text())
modules.append({'name': '<module>', 'description': '<user description>', 'paths': []})
Path('.companion/modules.json').write_text(json.dumps(modules, indent=2))
# Create skeleton spec
import sys
ref = json.loads(Path('.companion/product.json').read_text())
config = json.loads(Path(ref['config']).read_text())
spec_dir = Path(config['spec_location']) / 'openspec' / 'specs' / '<module>'
spec_dir.mkdir(parents=True, exist_ok=True)
(spec_dir / 'spec.json').write_text(json.dumps({
'module': '<module>',
'summary': '<user description>',
'business_rules': [],
'non_negotiables': [],
'tradeoffs': [],
'conflicts': [],
'lineage': []
}, indent=2))
print('created')
"
For each selected module read:
<spec_location>/openspec/specs/<module-name>/spec.json
Save selected modules to state:
uv run python -c "
import json, sys
from pathlib import Path
state_path = Path('.companion/state.json')
state = json.loads(state_path.read_text()) if state_path.exists() else {}
state['last_loaded_modules'] = sys.argv[1:]
state_path.write_text(json.dumps(state, indent=2))
print('saved')
" <module1> <module2> ...
Loaded: <module names>Now that state.json has the loaded modules, start the sidebar:
bash ${CLAUDE_SKILL_DIR}/scripts/start_sidebar.sh
The sidebar will start with full context already available.
Report what it prints (started / already running).
Done. The spec is loaded in your context and the sidebar is watching.
npx claudepluginhub nraychaudhuri/anchor --plugin anchorInitializes Claude Code sessions by migrating legacy harness files to .claude-harness/, creating missing state files like memory rules and config, and preparing GitHub sync.
Recalls project context via ctx CLI: loads context packet, reads TASKS.md/DECISIONS.md, lists recent sessions, presents structured readback of last session, active tasks, recent decisions, next steps. For memory questions or session starts.
Presents menu-driven interface to scan, select, and resume saved sessions from CONTEXT files. Extracts headers, summaries next tasks, hot files; supports active/archived.