Claude Timestamp
Elk bericht met het tijdstip waarop het gebeurde, en hoelang het duurde.
Een lange sessie leest terug als één lange lap tekst. Een timestamp geeft elke beurt een plaats, en een duur geeft hem gewicht.
Wat het doet
Claude Timestamp is een Claude Code-plugin, geen MCP-server: hooks die op vaste momenten in een sessie draaien, plus het /timestamps-commando om ze aan te passen. Elk assistant-bericht krijgt een timestamp zoals [13:22:13] in je eigen tijdzone, gevolgd door de duur van de beurt, zoals +2m14s, geteld vanaf het moment dat je op enter drukte tot Claude klaar was.
Bij een beurt die een ingestelde drempel overschrijdt, krijgt de duur een andere kleur, zodat je hem opmerkt in plaats van eroverheen te lezen. Staat TOOL_TIMING aan, dan noemt de timestamp er ook bij welke tool de beurt zo lang maakte: [13:22:13 +2m14s · Bash 1m58s]. Een gat tussen twee berichten krijgt een eigen label, zodat een sessie die je de volgende ochtend hervat nog steeds op volgorde staat, en het eerste bericht na middernacht krijgt de datum erbij.
Het model krijgt daarnaast de lokale tijd van elke prompt te horen, zodat het kan redeneren over wanneer iets gebeurde; je kunt dat uitzetten en alleen de zichtbare timestamp houden. Bij het sluiten van een sessie volgt een samenvatting:
claude-timestamp: session lasted 1h30m over 12 turns, 24m18s of it waiting, 35m00s away.
slowest tools: Bash 41.2s (18 calls), WebFetch 8.1s (1 call), Read 2.0s (37 calls). 2 failedWeergave is puur weergave. De timestamp wordt getekend terwijl berichten worden weergegeven, komt nooit in het transcript terecht en bereikt het model nooit.
Snel starten
Vereist jq en bash, verder niets. Ontbreekt jq, dan meldt de plugin dat één keer en doet daarna niets meer.
claude plugin marketplace add https://aranea-development.nl/plugins/marketplace.json
claude plugin install claude-timestamp@araneaHooks worden bij de start van een sessie geregistreerd, dus verschijnen de timestamps pas in een nieuwe sessie. Een sessie die al draait, pikt de plugin niet op.
Instellen hoeft niet. De standaardwaarden werken meteen, en de plugin wijst je bij de eerste sessie waar je ze kunt aanpassen.
Loopt de installatie vast op ssh: connect to host github.com port 22, dan haalt git de plugin uit de GitHub-repository over SSH en lukt dat op die machine niet. De melding wijst naar toegangsrechten, maar de repository is openbaar. Het transport is het probleem. Eén regel zet git op HTTPS, daarna kun je opnieuw installeren:
git config --global --add url."https://github.com/".insteadOf "git@github.com:"In de README staat de uitgebreide versie, inclusief hoe je het terugdraait.
Voorbeelden
Een echte Claude Code-sessie, op ware snelheid afgespeeld, opgenomen met de screenshot-tooling van het project zelf.

Twee snelle beurten worden gedimd weergegeven. De derde overschreed de drempel voor trage beurten, dus krijgt de duur een kleur en, met TOOL_TIMING aan, de naam van de tool die de beurt zo lang maakte.
Instellen
/timestamps toont wat je nu hebt en biedt een handvol presets aan, elk met een voorbeeld van de timestamp die hij oplevert.

Het commando neemt een verzoek ook direct over, dus /timestamps tokyo, /timestamps no colour en /timestamps 12 hour clock zijn elk in één stap klaar. Wijzigingen gelden vanaf je volgende bericht, want elke hook leest het instellingenbestand bij elke call opnieuw. Alleen het installeren zelf vraagt een nieuwe sessie, want dan worden de hooks geregistreerd.
Hier draait geen shellscript voor. /timestamps leest schema.json, dat met de plugin meekomt en elke instelling beschrijft, en bewerkt je configuratiebestand rechtstreeks.
Hoe de timestamp eruitziet
MARKER bepaalt waar de timestamp uit bestaat en in welke volgorde. De onderdelen zijn %time, %elapsed, %tool en %date, en een groep tussen accolades verdwijnt zodra elk onderdeel erin leeg is. Zo houdt een beurt zonder duur geen losse haakjes over:
MARKER= levert op
[{%date }%time{ %elapsed}{ · %tool}] [13:22:13 +2m14s · Bash 1m58s]
%time 13:22:13
%time{ %elapsed} 13:22:13 +2m14s
%time{ → %elapsed} 13:22:13 → +2m14sZelf een sjabloon schrijven hoeft niet. /timestamps kent deze vormen bij naam, en /timestamps no brackets en /timestamps just the clock zetten allebei de bijbehorende MARKER.

De tijd, de duur en de tool krijgen elk hun eigen kleur met TIME_COLOR, ELAPSED_COLOR en TOOL_COLOR. Laat je er een leeg, dan volgt dat onderdeel COLOR. Een trage beurt blijft SLOW_COLOR gebruiken: die wint van ELAPSED_COLOR zodra de beurt over SLOW_AFTER gaat, want opvallen is precies waar hij voor is.
Vanuit een terminal
Wil je de vragen liever zelf beantwoorden, gebruik dan de interactieve wizard van het setup-script. Die heeft een echte TTY nodig, dus draai hem zelf in een terminal.
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh"
Elke vraag toont zijn huidige waarde tussen haakjes, en enter houdt hem. De kleurenlijst en de resultaatregel worden getekend door dezelfde code die de echte timestamp tekent, dus een voorbeeld kan niet gaan afwijken van wat je straks ziet.
Het script accepteert ook flags, zodat je meerdere instellingen in één call kunt zetten:
setup.sh --tz=Asia/Tokyo --display=short --color=dim --slow-after=30Elke flag is optioneel en alles wat je weglaat houdt zijn huidige waarde.
Instellingen per project
Een project kan zijn eigen instellingen meedragen in .claude/claude-timestamp.conf, als laag over die van jou. Alleen de keys die het noemt worden overschreven, dus een repository kan één ding vastzetten en de rest jouw configuratie laten volgen:
cd een-project
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --project --tz=UTCDat schrijft alleen TZ=UTC. De rest komt nog steeds uit je eigen configuratie. Het bestand wordt gevonden door omhoog te lopen vanaf de map waar het gesprek over gaat, dus het werkt ook vanuit submappen, en het zoeken stopt bij je home-map zodat je eigen configuratie nooit voor een projectconfiguratie wordt aangezien.
Waar je tijd heen gaat
Vraag Claude hoe lang je hier al mee bezig bent, of hoeveel daarvan wachten was, en hij leest de totalen zo uit ~/.claude/claude-timestamp-history.tsv en antwoordt in de chat. Daar is geen commando voor nodig.
Voor een overzicht in de terminal draai je het script:
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --stats
Elke afgeronde sessie wordt aan het geschiedenisbestand toegevoegd, en de oudste vallen af zodra er meer dan HISTORY_LIMIT in staan.
Een regel is vijf getallen en een datum. Dat vertelt hoe lang een sessie duurde en hoeveel daarvan wachten was, maar nooit waar hij over ging. PROJECTS=on legt vast bij welk project een sessie hoorde, TOOL_TIMING=on wat elke tool kostte, en daarmee splitst het overzicht de totalen uit:
by project
claude-timestamp 18h02m 28 sessions
ratio 9h15m 14 sessions
(unnamed) 3h55m 5 sessions
slowest tools
Bash 6h20m (1204 calls)
WebFetch 41m ( 88 calls)Sessies van voor je PROJECTS aanzette tellen gewoon mee, gebundeld onder (unnamed). Twee opties versmallen het overzicht, op datum en op project:
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --stats --since=7d
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --stats --project=claude-timestampHet bestand bevat alleen tijden: geen berichttekst, geen tool-argumenten en geen paden. Met PROJECTS=on staat de mapnaam van het project erin, nooit het pad erboven, en ook niet de naam van je home-map als je een sessie daarvandaan draait. Met TOOL_TIMING=on staat erin welke tools hoe lang duurden. Allebei staan ze standaard uit, en met HISTORY=off gaat het vastleggen helemaal uit.
Als er iets niet klopt
Vraag Claude waarom je geen timestamps ziet, en hij legt het feitenbestand en je configuratie naast schema.json om te vertellen wat hij aantreft. De meest voorkomende oorzaak is ENABLED=off, makkelijk te zetten en te vergeten omdat het elke hook stilzet zonder spoor op het scherm.
Voor een controle in de terminal draai je doctor:
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --doctor
Die controleert of jq aanwezig is, of de configuratie te lezen is, of een vastgepinde tijdzone op deze machine echt toegepast kan worden en of de state-map beschrijfbaar is, en eindigt met een foutcode als daar iets van misgaat. Hij meldt ook of ENABLED aanstaat: de plugin bewust uitzetten is op zichzelf geen probleem, dus die regel alleen laat de controle niet falen, maar het is meestal wel waarom je doctor draaide.
Hoe het werkt
Acht events, bediend door zes scripts. Eén ervan praat tegen het model: UserPromptSubmit vertelt Claude de lokale tijd van je bericht, één regel, en dat zet je uit met INJECT_CONTEXT=false. Al het andere blijft in de harness en kost je geen context.
| Hook | Taak |
|---|---|
SessionStart | Controleert jq, ruimt oude state op, wijst je de eerste keer naar /timestamps |
UserPromptSubmit | Legt de start van de beurt vast, vertelt het model de lokale tijd |
MessageDisplay | Tekent de timestamp op de eerste batch van elk bericht |
Stop / StopFailure | Sluiten de beurt af op het moment dat hij klaar is |
SessionEnd | Rapporteert de samenvatting, legt de sessie vast, ruimt de state op |
PostToolUse / PostToolUseFailure | Leggen vast wat elke tool call kostte en tellen mislukkingen, alleen als TOOL_TIMING=on staat |
De duur van een beurt komt van Stop, niet van een gok op basis van welke berichten voorbijkwamen. Dat is het verschil tussen 'het laatste bericht is getekend' en 'Claude is klaar'.
MessageDisplay wordt herhaaldelijk aangeroepen terwijl een bericht binnenstroomt. Alleen de eerste batch krijgt een timestamp; de rest geeft niets terug, wat Claude Code leest als 'toon de originele tekst'. De tekst ongewijzigd teruggeven zou bij elke batch van elk bericht onnodig werk zijn.
Timing-state staat in $TMPDIR/claude-timestamp-<jouw uid>, één klein bestand per sessie, opgeruimd zodra de sessie eindigt en na zeven dagen sowieso. De uid staat in de naam omdat $TMPDIR op een machine met meerdere gebruikers gedeeld terrein is: de map wordt privé aangemaakt, en een map die aan iemand anders toebehoort wordt geweigerd in plaats van beschreven.
Configuratie
Instellingen staan in ~/.claude/claude-timestamp.conf als KEY=value, getoetst aan een lijst bekende keys en nooit uitgevoerd, dus een verdwaalde regel erin kan niets laten draaien.
| Instelling | Standaard | Wat het doet |
|---|---|---|
ENABLED | on | Hoofdschakelaar; off zet elke hook stil zonder te deïnstalleren |
TZ | machine-lokaal | IANA-naam zoals Europe/Amsterdam, of leeg voor lokale tijd |
DISPLAY_FORMAT | 24h | 24h, short, 12h, iso, of een willekeurige strftime-string |
CONTEXT_FORMAT | 24h | Dezelfde waarden, voor de tijd die Claude te horen krijgt |
COLOR | dim | none, dim, gray, red, green, yellow, blue, magenta, cyan |
MARKER | [{%date }%time{ %elapsed}{ · %tool}] | De opbouw, uit %time, %elapsed, %tool en %date |
TIME_COLOR | leeg | Kleur van %time en %date; leeg volgt COLOR |
ELAPSED_COLOR | leeg | Kleur van %elapsed; SLOW_COLOR wint bij een trage beurt |
TOOL_COLOR | leeg | Kleur van %tool; leeg volgt COLOR |
ELAPSED | on | Toont hoe lang de beurt duurde |
INJECT_CONTEXT | true | Vertelt Claude de lokale tijd van elk prompt |
SLOW_AFTER | 60 | Kleurt de duur voorbij dit aantal seconden, 0 schakelt het uit |
SLOW_COLOR | yellow | Kleur voor een trage beurt |
IDLE_AFTER | 3600 | Markeert een gat van deze lengte tussen berichten, 0 schakelt het uit |
DATE_ROLLOVER | on | Toont de datum op het eerste bericht na middernacht |
SUMMARY | on | Rapporteert sessietotalen bij het afsluiten |
SUBAGENTS | on | Voorziet ook berichten van subagents van een timestamp |
TOOL_TIMING | off | Timet losse tool calls en noemt de traagste |
HISTORY | on | Legt elke afgeronde sessie vast, voor /timestamps en --stats |
HISTORY_LIMIT | 200 | Hoeveel opgenomen sessies bewaard blijven |
PROJECTS | off | Noteert het project bij elke sessie; de mapnaam, nooit een pad |
NO_COLOR schakelt kleur uit, wat COLOR ook zegt.
Een waarde die de plugin niet kan gebruiken, wordt vervangen door de standaard, en dat gebeurt niet stilzwijgend: hij noemt het bij de start van de volgende sessie en in --doctor.
De klokformaten leveren 14:03:22 op voor 24h, 14:03 voor short, 2:03 PM voor 12h en 2026-08-19T14:03:22 voor iso. Elke waarde met een % erin wordt als strftime-string behandeld, dus de ontsnappingsroute heeft geen eigen instelling nodig.
TOOL_TIMING staat standaard uit, want het is de enige instelling die iets kost per tool call. Al het andere kost één keer per bericht iets.
Naast de configuratie schrijft de plugin bij elke sessiestart ~/.claude/claude-timestamp.facts.json. Daarin staat wat je niet uit de configuratie kunt afleiden: of deze machine een tijdzone-database heeft, of de state-map beschrijfbaar is, en welke versie er geïnstalleerd staat. Daarmee kan /timestamps vragen over je installatie beantwoorden zonder iets uit te voeren.
Platformnotities
Getest op Linux, macOS en Windows bij elke push. Git Bash op Windows heeft geen tijdzone-database: date valt daar zonder melding terug op UTC voor elke IANA-naam die niet oplosbaar is. De plugin herkent dit, gebruikt in plaats daarvan lokale tijd, meldt het één keer bij de start van de sessie, en weigert een vastgepinde zone te schrijven waarvan hij weet dat die toch niet werkt. UTC en GMT werken nog wel, want die hebben geen database nodig.
Tool-timings meet de plugin niet zelf. Claude Code meldt bij elke call hoe lang die duurde, en de hook leest dat getal alleen uit. Dat die hook ook zonder de meting bij elke call draait, is de reden dat hij standaard uitstaat.