Naar inhoud

Claude Timestamp

Elk bericht met het tijdstip waarop het gebeurde, en hoelang het duurde.

Een lange sessie leest terug als één lange muur tekst. Een tijdstempel 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 tijdstempel 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.

Een beurt die een ingestelde drempel overschrijdt, krijgt voor die duur een andere kleur, zodat je hem opmerkt in plaats van eroverheen te lezen. Staat TOOL_TIMING aan, dan noemt de tijdstempel 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 elk prompt te horen, zodat het kan redeneren over wanneer iets gebeurde; je kunt dat uitzetten en alleen de zichtbare tijdstempel houden. Bij het sluiten van een sessie volgt een samenvatting:

text
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 failed

Weergave is puur weergave. De tijdstempel wordt getekend terwijl berichten renderen, 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.

bash
claude plugin marketplace add https://aranea-development.nl/plugins/marketplace.json
claude plugin install claude-timestamp@aranea

Hooks worden bij de start van een sessie geregistreerd, dus start een nieuwe sessie voordat de tijdstempels verschijnen. 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:

bash
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.

Tijdstempels op assistant-berichten, met een trage beurt gemarkeerd en de tool erbij die hem traag maakte

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 hem veroorzaakte.

Instellen

/timestamps toont wat je nu hebt en biedt een handvol presets aan, elk met een voorbeeld van de tijdstempel die hij oplevert.

Het commando in de chat, met presets en een voorbeeld van elke tijdstempel

Het commando neemt een verzoek ook direct over, dus /timestamps tokyo, /timestamps no colour en /timestamps 12 hour clock landen elk in één stap. Wijzigingen gelden vanaf je volgende bericht, want elke hook leest het instellingenbestand bij elke aanroep 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 tijdstempel eruitziet

MARKER bepaalt waar de tijdstempel uit bestaat en hoe hij is opgebouwd. 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:

text
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 → +2m14s

Zelf een sjabloon schrijven hoeft niet. /timestamps kent een handvol vormen bij naam en toont van elke wat hij oplevert, en het neemt ook gewoon een verzoek aan: /timestamps no brackets en /timestamps just the clock zetten allebei de bijbehorende MARKER.

De vormen die de plugin bij naam kent, elk met de tijdstempel die hij oplevert

De drie onderdelen kunnen elk hun eigen kleur krijgen 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, dan heeft het setup-script een interactieve wizard. Die heeft een echte TTY nodig, dus draai hem in een terminal in plaats van het aan Claude te vragen.

bash
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh"

De setup-wizard, met de kleurkeuzes en een voorbeeld dat meebeweegt

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 tijdstempel tekent, dus een voorbeeld kan niet gaan afwijken van wat je straks ziet.

Het script neemt ook vlaggen, zodat je meerdere instellingen in één aanroep kunt zetten:

bash
setup.sh --tz=Asia/Tokyo --display=short --color=dim --slow-after=30

Elke vlag 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 sleutels die het noemt worden overschreven, dus een repository kan één ding vastzetten en de rest jouw configuratie laten volgen:

bash
cd een-project
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --project --tz=UTC

Dat 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 de zoektocht 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
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --stats

Totalen over de opgenomen sessies

Elke afgeronde sessie wordt aan het geschiedenisbestand toegevoegd, en de oudste vallen af zodra er meer dan HISTORY_LIMIT in staan. Het bestand bevat alleen tijden: vijf getallen en een datum per sessie. Geen berichttekst, geen tool-argumenten en geen paden, dus er staat nergens in waar je aan werkte. Helemaal uitzetten kan met HISTORY=off.

Als er iets niet klopt

Vraag Claude waarom je geen tijdstempels 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
bash "$CLAUDE_PLUGIN_ROOT/hooks/scripts/setup.sh" --doctor

Uitvoer van de doctor-zelfcontrole

Die controleert of jq aanwezig is, of de configuratie parseert, 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 gebeurtenissen, 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=off. Al het andere blijft in de harness en kost je geen context.

HookTaak
SessionStartControleert jq, ruimt oude state op, wijst je de eerste keer naar /timestamps
UserPromptSubmitLegt de start van de beurt vast, vertelt het model de lokale tijd
MessageDisplayTekent de tijdstempel op de eerste batch van elk bericht
Stop / StopFailureSluiten de beurt af op het moment dat hij klaar is
SessionEndRapporteert de samenvatting, legt de sessie vast, ruimt de state op
PostToolUse / PostToolUseFailureLeggen vast wat elke tool-aanroep kostte en tellen mislukkingen, alleen als TOOL_TIMING=on staat

De duur van een beurt komt van Stop, niet uit 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 tijdstempel; 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 geweest.

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 meer gebruikers gedeelde grond 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 sleutels en nooit uitgevoerd, dus een verdwaalde regel erin kan niets laten draaien.

InstellingStandaardWat het doet
ENABLEDonHoofdschakelaar; off zet elke hook stil zonder te deïnstalleren
TZmachine-lokaalIANA-naam zoals Europe/Amsterdam, of leeg voor lokale tijd
DISPLAY_FORMAT24h24h, short, 12h, iso, of een willekeurige strftime-string
CONTEXT_FORMAT24hDezelfde waarden, voor de tijd die Claude te horen krijgt
COLORdimnone, dim, gray, red, green, yellow, blue, magenta, cyan
MARKER[{%date }%time{ %elapsed}{ · %tool}]De opbouw, uit %time, %elapsed, %tool en %date
TIME_COLORleegKleur van %time en %date; leeg volgt COLOR
ELAPSED_COLORleegKleur van %elapsed; SLOW_COLOR wint bij een trage beurt
TOOL_COLORleegKleur van %tool; leeg volgt COLOR
ELAPSEDonToont hoe lang de beurt duurde
INJECT_CONTEXTtrueVertelt Claude de lokale tijd van elk prompt
SLOW_AFTER60Kleurt de duur voorbij dit aantal seconden, 0 schakelt het uit
SLOW_COLORyellowKleur voor een trage beurt
IDLE_AFTER3600Markeert een gat van deze lengte tussen berichten, 0 schakelt het uit
DATE_ROLLOVERonToont de datum op het eerste bericht na middernacht
SUMMARYonRapporteert sessietotalen bij het afsluiten
SUBAGENTSonVoorziet ook berichten van subagents van een tijdstempel
TOOL_TIMINGoffTimet losse tool-aanroepen en noemt de traagste
HISTORYonLegt elke afgeronde sessie vast, voor /timestamps en --stats
HISTORY_LIMIT200Hoeveel opgenomen sessies bewaard blijven

NO_COLOR schakelt kleur uit, wat COLOR ook zegt.

Een waarde die de plugin niet kan gebruiken, wordt vervangen door de standaard; de plugin doet niet stilzwijgend niets, en noemt het bij de start van de volgende sessie en in --doctor.

Klokformaten renderen als 14:03:22 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-aanroep. Al het andere kost één keer per bericht.

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. Dat is wat /timestamps in staat stelt vragen over je installatie te 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 lokale tijd in plaats daarvan, 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 aanroep hoe lang die duurde, en de hook leest dat getal alleen uit. Dat die hook ook zonder de meting bij elke aanroep draait, is waarom hij standaard uit staat.