Pin session decisions, questions, constraints, and corrections to a persistent board that survives context compaction.
89
89%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Risky
Do not use without reviewing
Persist decisions, questions, constraints, and corrections to a JSON file that survives context compaction. A companion hook injects the board into every tool call so the model never forgets.
After responding to any user message where a decision was made, a question was asked about a proposal, or a constraint was stated, IMMEDIATELY invoke /pin with the appropriate category. Do not ask permission — just pin it.
Examples of auto-invoke triggers:
/pin ✅ use bun/pin ❓ split services — latency impact?/pin ❌ auth layer — skip for MVP/pin 📌 MVP only, max 3 files/pin 🔧 target = artisans, not developersDo NOT pin:
| Command | Action |
|---|---|
/pin ✅ <text> | Pin approved item |
/pin ❓ <text> | Pin pending question |
/pin ❌ <text> | Pin killed/rejected item |
/pin 📌 <text> | Pin scope constraint |
/pin 🔧 <text> | Pin correction |
/pin show or /pin | Display current board |
/pin rm <n> | Remove pin by number |
/pin clear | Clear all pins |
/pin clear triage | Clear ✅/❓ only, keep 📌/❌/🔧 |
Path: a session-scoped .session-logs/<slug>/pins.json file under a configurable base directory.
Derive slug from CWD:
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
REL_PATH="${PWD#$GIT_ROOT/}"
SLUG=$(echo "$REL_PATH" | tr '/' '-')
PINS_DIR="$PRAXIS_DIR/.session-logs/$SLUG"
PINS_FILE="$PINS_DIR/pins.json"Schema:
{
"items": [
{
"id": 1,
"type": "approved",
"emoji": "✅",
"content": "use bun everywhere",
"detail": "",
"ts": "2026-04-01T14:30:00Z"
}
],
"next_id": 2
}Type mapping: ✅=approved, ❓=pending, ❌=killed, 📌=scope, 🔧=correction
/pin <emoji> <text>)Parse the emoji prefix to determine type. Text after emoji is content. If text contains —, split into content and detail.
PINS_FILE path (see State File above)mkdir -p the directory{"items":[],"next_id":1}⚠️ Already pinned. and stopid=next_id, increment next_id📌 Pinned #N: <emoji> <content> — one line only, then resume prior work/pin show or /pin)PINS_FILE📋 Pin board is empty.📋 Pin Board (5 items)
1. ✅ use bun everywhere (minor: keep fallback for CI)
2. ✅ split the PR into 2
3. ❓ split services — latency impact?
4. ❌ auth rewrite — out of MVP scope
5. 📌 MVP only, max 3 files/pin rm <n>)If no number: ⚠️ Usage: /pin rm <number>
PINS_FILE, find item with id === n⚠️ Pin #N not found.🗑️ Pin #N removed./pin clear){"items":[],"next_id":<keep current next_id>}🗑️ Pin board cleared./pin clear triage)approved or pendingkilled, scope, or correction🗑️ Triage cleared. <N> pins remaining.The pin board is a capture tool, not a management tool. Its only job is to hold decisions and constraints in a persistent, queryable form so that context compaction does not erase them. ALWAYS treat the board as a write-once, append-only record during a session — edits and removals are operations of last resort, not routine cleanup. A well-run session generates fewer than 20 pins; if you hit the limit frequently, the signals are too granular.
next_id always increments, never reuses.📌 MVP only, max 3 files has the emoji as a 2-byte or 4-byte sequence; naive cut -d' ' will misparse on some shells.next_id always increments forward. Why: Stable numbering prevents confusion when users reference pins by number across a session; id recycling silently corrupts that contract.Pinning a scope constraint mid-session:
# User says: "Keep this MVP only, no more than 3 new files"
/pin 📌 MVP only, max 3 files
# Response: 📌 Pinned #1: 📌 MVP only, max 3 files
# Session resumes immediately from where it left offPinning a decision reversal and viewing the board:
# User says: "Actually use PostgreSQL, not SQLite"
/pin 🔧 target database = PostgreSQL, not SQLite
# Response: 📌 Pinned #2: 🔧 target database = PostgreSQL, not SQLite
# Later: review all active pins
/pin show
# Response:
# 📋 Pin Board (2 items)
# 1. 📌 MVP only, max 3 files
# 2. 🔧 target database = PostgreSQL, not SQLitePinning an unresolved question and clearing triage items after resolution:
# Unresolved question surfaces during design
/pin ❓ split services — will latency exceed 200ms SLA?
# Response: 📌 Pinned #3: ❓ split services — will latency exceed 200ms SLA?
# After the question is answered, clear only approved/pending pins
/pin clear triage
# Response: 🗑️ Triage cleared. 1 pin remaining.