Skip to content

Claude Code Telemetry

Every time a Claude Code session starts on this project, a shell hook captures the context (branch, issue, repo) and forwards it to N8N. When the session ends, a second hook collects the Prometheus metrics (active time, cost, tokens, lines of code), reconstructs the branch segments traversed, and syncs everything to the matching Odoo tasks.

The result: every Odoo task shows the Claude time spent on it, the API cost, the number of tokens, and the lines changed — automatically, without manual entry.

WorkflowNodesTriggerRole
Session Start4Webhook POSTRecords the active session
Session End (main)30Webhook POSTMetrics + Odoo sync
Orphan Detection~20Schedule 12 hRecovers crashed sessions
Session Categorizer17Sunday 11 PMCategorises unsorted sessions
Session Metrics Updater7Webhook POSTEnriched update (backfill)

Session End · 30 nodes

Session Start · 4 nodes

Claude Code · starts

SessionStart hook

Dedup

Register Active Session

work · commits · branch switches

Claude Code · ends

SessionEnd hook · git reflog + git log

Dedup

Prometheus Query

Split Metrics per segment

Save Data Table

Loop per issue

Find/Create Odoo Task → Update

Create Session Detail

Cleanup Active Session

Orphan Detection · scheduled


Without telemetry, there is no way to know how much time and money Claude Code consumes per task. You know the tool was used, but not on what or for how much. For a freelancer billing time, that is a blind spot.

ProblemWithout telemetryWith telemetry
Cost per taskRead it manually from the API consoleUSD cost per issue, per model
Time spentEstimate from memoryActive time from Prometheus + Odoo timesheets
Attribution”I worked on the project”Segments per branch, per issue
Lost sessionsCrash = data lostOrphan Detection recovers metrics
Categorisationdev branches without contextAI categorises into dev/docs/refactor/fix/test
MetricSourceGranularity
Active time (seconds)Prometheus OTELPer session, per model
API cost (USD)Prometheus OTEL4 decimals, per model
Tokens (input/output/cache)Prometheus OTELPer type, per model
Lines added/removedgit logPer commit

This is the most complex hook. When Claude Code exits, it:

  1. Reads the state file written at start (frozen issue_id, timestamp)
  2. Rebuilds branch segments through git reflog --since
  3. Collects commits with git log --since --all
  4. Enriches each commit with its branch and matching issue
  5. Builds a TLDR (changed files, insertions, deletions, dominant type)
  6. Sends the enriched payload to N8N

The key point: the issue_id is frozen when the session starts. Even if the user switches branches mid-session, the system knows which task to attribute the work to.

When a session crosses several branches (for example feature/176-fix for 40 minutes then dev for 20 minutes), metrics are split proportionally:

Total session: 60 minutes
Branch feature/176: 40 min → 66% of metrics
Branch dev: 20 min → 33% of metrics
If total cost = 0.15 USD:
Issue #176 → 0.10 USD
Branch dev → 0.05 USD (generic task)

Sessions without an issue (work on dev, main, or branches without a number) are routed to generic tasks: one per (repo + category) combination. The category is derived from the dominant commit type:

Dominant commitsCategoryGeneric task
feat, choredev”Dev without issue (features & chores)“
docsdocs”Documentation maintenance”
refactorrefactor”Refactoring”
fixfix”Fixes (no issue)“
testtest”Testing”

Each Odoo task receives 11 enriched fields automatically:

FieldTypeDescription
x_claude_time_totalFloatCumulative active hours
x_claude_cost_totalFloatCumulative USD cost
x_claude_token_totalIntegerCumulative tokens
x_claude_sessionsIntegerNumber of sessions
x_claude_lines_addedIntegerLines added
x_claude_lines_removedIntegerLines removed
x_claude_cost_by_modelJSONBreakdown per model
x_claude_tokens_inputIntegerInput tokens
x_claude_tokens_outputIntegerOutput tokens
x_claude_tokens_cacheIntegerCache tokens
x_claude_last_sessionDatetimeLast session

Fields are cumulative: each session adds its metrics on top of those already on the task.

Every 12 hours, a workflow checks whether sessions remain stuck in the active sessions table (a sign of a Claude Code crash). Sessions older than 6 hours are considered orphans.

The workflow fetches the Prometheus metrics (if still available — 15-day retention), saves them with status orphaned, and updates the matching Odoo task. Nothing is lost.

Every Sunday at 11 PM, the Session Categorizer uses Claude to analyse uncategorised sessions. The AI receives a batch of sessions with their “topic” (first user message) and can:

  • Assign a category (dev, docs, refactor, fix, test)
  • Rename the Odoo task with a more descriptive name
  • Re-link a session to an issue task if it was misattributed

LimitImpactMitigation
Prometheus 15-day retentionMetrics lost after 15 daysSaved into a Data Table at session end
No metrics per branchPrometheus only knows session_idProportional split by segment duration
Shell hook onlyDepends on bash and gitScripts tested and shipped through scripts/claude-hooks/

If a real-time dashboard is needed:

  • Prometheus metrics already exist in Grafana
  • Add a “Claude Code Sessions” dashboard with cost, tokens, and active sessions
  • Alert if cost crosses a daily threshold

If multi-user support is required:

  • Add a user_id field in the payload
  • Split costs per developer
  • Comparative dashboard inside Odoo

If finer analysis is needed:

  • Store full transcripts (only the “topic” is kept today)
  • Analyse usage patterns: which prompts cost the most
  • Optimise caches and model choice