Citadel telemetry
git clone https://github.com/SethGammon/Citadel
T=$(mktemp -d) && git clone --depth=1 https://github.com/SethGammon/Citadel "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/telemetry" ~/.claude/skills/sethgammon-citadel-telemetry && rm -rf "$T"
skills/telemetry/SKILL.md/telemetry — Telemetry Hub
Identity
/telemetry is the discovery and control surface for Citadel's telemetry system. One command that shows you everything, tells you where to dig deeper, and lets you tune or disable any part of it.
When to Use
- "What does Citadel track?" / "What telemetry does it have?"
- "What did this session cost?" / "How much have I spent?"
- "How do I turn off the cost alerts?" / "Can I disable telemetry?"
- "Show me hook activity" / "What hooks fired?"
- "What trust level am I at?"
- Directly:
/telemetry
Routed here by
/do for: "telemetry", "what did this cost", "session stats",
"session cost", "how much did that cost", "what hooks fired", "trust level",
"show me telemetry", "cost breakdown", "spending".
Commands
| Command | Behavior |
|---|---|
| Full hub — stats + command directory + settings |
| Cost section only: session, today, all-time, by campaign |
| Hook activity only: last 20 fires with timing and outcomes |
| Show current telemetry settings from harness.json |
| Disable session summary, reduce hook verbosity |
| Re-enable all telemetry |
| Set cost alert threshold step (e.g. = alert every $10) |
Protocol
Step 1: COLLECT DATA
Read the following in parallel. All are optional — treat missing files as zero/empty.
Live session cost:
- Run
— captures real token datanode scripts/session-tokens.js --today 2>/dev/null - If unavailable, read
for burn rate.planning/telemetry/cost-tracker-state.json - Real cost is always preferred over estimated. Mark clearly:
vs$X.XX$X.XX (est)
Historical costs:
- Run
for all-time real totalsnode scripts/session-tokens.js --all 2>/dev/null - Read last 20 lines of
for recent sessions.planning/telemetry/session-costs.jsonl - For each entry: prefer
>real_cost
>override_costestimated_cost
Hook activity:
- Read last 20 lines of
.planning/telemetry/hook-timing.jsonl - For each
entry: extractevent: "timing"
,hook
,duration_mstimestamp - For each
entry: extractevent: "counter"
,hookmetric - Check
(last 20 lines) for recent blocks.planning/telemetry/hook-errors.jsonl
Trust level:
- Read
→.claude/harness.json
objecttrust - Compute: novice (sessions < 5), familiar (5-19), trusted (20+ with 2+ campaigns)
- If
set, use thattrust.override
Settings:
- Read
→.claude/harness.json
objecttelemetry - Show current values with defaults if missing
Step 2: RENDER HUB
Output this format. Omit a section only if the data source is completely unavailable.
=== Citadel Telemetry === CURRENT SESSION Cost: $X.XX [real] | $X.XX (est) Duration: N min | $X.XX/min burn rate Tokens: NNK input | NK output | NK cache read | NK cache write Messages: N Agents: N spawned Hooks fired: N (today) TODAY $X.XX across N sessions Most expensive: {slug or "unattached"} — $X.XX ALL TIME $X.XX across N sessions, N campaigns Cache savings: ~$X.XX (cache reads vs full input price) BY CAMPAIGN (recent 5) {slug}: $X.XX — N sessions _unattached: $X.XX — N sessions HOOK ACTIVITY (last 10 fires) {relative time} | {hook} | {duration_ms}ms | {outcome} (no hook timing recorded yet) TRUST LEVEL Level: {novice | familiar | trusted} Sessions: N completed Campaigns: N completed (novice = 0-4 sessions | familiar = 5-19 | trusted = 20+ with 2+ campaigns) TELEMETRY SETTINGS Enabled: {true | false} Session summary: {auto | always | off} ← the [session] line at session end Cost alerts: {on | off} at thresholds: {list or "default ($5,$15,$30...)"} Hook timing: {on | off} Audit log: {on | off} — or, when harness.json is absent — (harness.json not found — defaults active) → Run /do setup to unlock cost tracking, configure thresholds, and register your install. COMMAND DIRECTORY /telemetry This screen /telemetry --costs Cost breakdown only /telemetry --hooks Hook activity only /cost Deep cost exploration by session/campaign/week /dashboard Full harness state (campaigns, fleet, all costs) node scripts/session-tokens.js --today Today's sessions with exact token counts node scripts/session-tokens.js --all All-time totals (real data, not estimates) cat .planning/telemetry/session-costs.jsonl Raw session cost log cat .planning/telemetry/hook-timing.jsonl Raw hook execution log cat .planning/telemetry/audit.jsonl Raw tool call audit log CONTROLS /telemetry off Disable session summary + reduce verbosity /telemetry on Re-enable /telemetry --threshold N Alert every $N (writes to harness.json) /telemetry --config Edit settings interactively
Step 3: SUB-COMMAND HANDLING
:/telemetry off
- Read
.claude/harness.json - Set
andtelemetry.sessionSummary = "off"telemetry.costAlerts = false - Write back to harness.json via Bash (
)node -e "..." - Output: "Telemetry summary disabled. Hook safety checks remain active. Run
to restore."/telemetry on - Note: disabling telemetry never disables safety hooks (protect-files, circuit-breaker, external-action-gate)
:/telemetry on
- Read
.claude/harness.json - Set
andtelemetry.sessionSummary = "auto"telemetry.costAlerts = true - Write back
- Output: "Telemetry re-enabled. Session summaries will appear at session end."
:/telemetry --threshold N
- Validate N is a positive number
- Generate threshold array:
(capped at 500)[N, N*2, N*5, N*10, N*20, N*50, N*100] - Write to
underharness.jsonpolicy.costTracker.thresholds - Output: "Cost alerts will fire at: ${thresholds.join(', $')}"
:
Show current settings with edit instructions for each. Don't auto-apply — show the
/telemetry --config
node -e "..." command the user can run to change each setting.
Step 4: ACCURACY BADGES
Always mark data source clearly:
— data from Claude Code's native session JSONL (exact)[real]
— estimated from the fallback model ($1 base + $0.50/agent + $0.10/min)(est)
— manually entered by the user(override)
Never blend real and estimated in the same total without flagging it.
What Telemetry Covers (and What It Doesn't)
Covered:
- Session cost (real token data from Claude Code JSONL when available)
- Session duration, burn rate, message count
- Agent/subagent spawn count
- Hook execution timing and outcomes
- Campaign cost attribution
- Trust level progression
Not covered (by design):
- Per-tool-call cost breakdown (Claude Code doesn't expose this)
- Per-subagent cost isolation (session JSONL is session-level, not agent-level)
- Real-time streaming token count (snapshot-based, not streaming)
Safety hooks always on (cannot be disabled via
):/telemetry off
- protect-files — prevents accidental overwrites of sensitive config
- external-action-gate — gates git push / PR creation
- circuit-breaker — prevents failure spirals
- quality-gate — catches violations at session end
Quality Gates
- Never show raw JSONL to the user — always parse and format
- Cost totals must be labeled with their source (real / est / mixed)
must NOT disable safety hooks — make this explicit in output/telemetry off- Relative timestamps required — no raw ISO strings in output
- If all data sources are missing, show the empty-state version with setup hint
Fringe Cases
missing: Show empty state. Note: "Run.planning/telemetry/
to initialize telemetry."/do setup
unavailable: Fall back to session-costs.jsonl, mark assession-tokens.js
.(est)- harness.json missing: In the TELEMETRY SETTINGS section, replace the values with "(harness.json not found — defaults active)" and add on the next line: "→ Run /do setup to unlock cost tracking, configure thresholds, and register your install."
in harness.json: Show a banner: "Telemetry is disabled. Runtelemetry.enabled: false
to re-enable."/telemetry on
Exit Protocol
/telemetry does not produce a HANDOFF block. It is a read-only observability tool (except for
--threshold, off, on, --config which write harness.json).
After displaying output, wait for the next user command.