chronos-skill
v2.0.2
Published
Your AI coding agent has no idea what time it is. chronos reads the transcript it already writes, puts a live clock on your Claude Code statusline, catches it retrying the same failed command, and tells you where the last six hours went.
Maintainers
Keywords
Readme
Your coding agent will re-run the command that failed nine seconds ago. It will reason about a file it edited twenty minutes after it read it. It will tell you it "just" checked something it checked before lunch. Then it will do all of that again, because nothing in its context tells it that time has passed.
If you run one agent, that is annoying. If you run four at once on a deadline, it is a hole in your week, and you cannot even point at it, because nothing in Claude Code will tell you which session is stuck, which one is looping, or where the last six hours actually went.
chronos closes the hole. It reads the transcript your agent already writes, puts a live clock on your statusline, hands the model a real number every turn, and shouts the moment it catches the model repeating itself.
⏱ 1h50m · 413 tools · ✗16 · ⚠ 3x BashInstall it in thirty seconds. It adds no dependency, spawns no daemon, phones nothing home, and identifies its own hooks by entry point rather than by name, so uninstalling it leaves everything else where it was.
The thing that pays for itself
An agent stuck in a retry loop is the single most expensive failure mode in long-running agentic work. Same command, same arguments, same failure, three times, while you were in a meeting. chronos catches it on the argument hash and tells the model directly, in its own context, on the very next turn:
That LOOP: line is not a log entry you have to go and read. It lands in the
model's context and changes what it does next. So does STALE:, which fires when
a file changed after the agent last read it, which is how agents end up
confidently editing a version of a file that stopped existing half an hour ago.
Where did my session go
Active time, not wall clock. A session you resumed after two days has not been running for two days, and a tool that claims it has is a tool you stop believing. Gaps over five minutes are idle and are counted as idle.
How long have you actually been doing this today
Nobody else will tell you. Every session, every project, one number.
If you bill by the hour, or you are trying to work out why a "quick afternoon" ate the whole day, this is the command.
When did I last run that
Real timestamp, how long ago, whether it worked, how long it took. Stop scrolling back through the transcript.
Prove it is working
Hook tools rot silently. chronos v1 sat broken on the author's own machine for
nineteen days writing a ten megabyte file of nothing, and nobody noticed, because
nothing ever asked it to prove itself. So chronos doctor checks the registration
in settings.json and then actually runs each hook, against a synthetic
payload pointed at your newest real transcript, and prints what each one emitted.
It also parses a live transcript and times it, so a green result means the whole
path worked just now rather than that the config looked plausible.
Install
Node 18 or newer. Claude Code ships on npm, so you already have it.
git clone https://github.com/OthmanAdi/chronos
cd chronos
node bin/chronos.mjs install
node bin/chronos.mjs doctorRestart Claude Code. Done.
As a plugin:
/plugin marketplace add OthmanAdi/chronos
/plugin install chronos@chronosJust the decision rules, for any agent that reads skills:
npx skills add OthmanAdi/chronos --skill chronos -gOr from npm, for PI and anything that consumes npm skill packages:
pi install npm:chronos-skillThe package is chronos-skill. The bare chronos name on npm belongs to an unrelated project.
The installer will not wreck your setup. It concatenates per event instead of
replacing the event's array, takes a timestamped backup of settings.json first,
supports --dry-run, is idempotent, and chains whatever statusline you already
had rather than replacing it. Uninstall puts it back.
It recognises its own hooks by matching the entry point they invoke, not by
looking for the string chronos anywhere in the command. A tool called
chronoscope, or a hook of yours that merely writes to chronos.log, is not
chronos and is left alone. Two tests assert exactly that, plus the case v1's
uninstall got wrong: a matcher group holding both a chronos hook and somebody
else's, where only ours may be removed.
uninstall --purge refuses to delete a directory that is not named .chronos
and does not contain chronos state, so pointing CHRONOS_HOME at a repo cannot
turn an uninstall into a recursive delete.
Commands
| Command | What it answers |
|---|---|
| chronos report | Where did this session's time go |
| chronos today | How long have I actually worked today, across every session |
| chronos week | The same, over seven days |
| chronos sessions | Which sessions are running hot, and which are failing |
| chronos when <text> | When did I last run that |
| chronos doctor | Is this actually wired up right now |
| chronos install | Wire it into Claude Code |
| chronos uninstall | Take it back out. --purge also drops the state directory |
| chronos statusline | Render the statusline segment. Reads stdin |
| chronos cache-clear | Drop the incremental parse cache |
--json works on report, today and week. --session <id> and
--transcript <path> aim report at one specific session; the other commands
choose their own scope and ignore them. when takes --days and --limit.
With no selector, report resolves the session in this order: CLAUDE_SESSION_ID
if the host set it, then the newest transcript belonging to the current directory,
then the newest anywhere. That matters when several agents are running, which was
the point of building this.
In Claude Code: /chronos, /chronos-today, /chronos-when, /chronos-doctor.
Why your agent is like this
From arxiv 2510.23853, "Your LLM Agents are Temporally Blind" (October 2025): even with timestamps sitting in context, the strongest frontier models reach only 65% alignment with human temporal judgment, and timestamps appear in fewer than 4% of reasoning traces.
Putting a clock in the context is not enough. The model has to be told when to
look at it, and it has to be handed a real number when it does. That is what
chronos ships: seven decision rules in SKILL.md, and the measured facts to apply
them to.
How it works, and why it is fast
Claude Code writes a JSONL transcript of every session to
~/.claude/projects/<slug>/<session-id>.jsonl. Every tool call is already in
there twice: a tool_use block on an assistant record, and a tool_result on the
next user record. Both carry an ISO timestamp to the millisecond, and the result
carries is_error.
That is a complete, exact record. chronos reads it. It registers no PreToolUse
and no PostToolUse hook, because there is nothing left to intercept.
SessionStart ─────┐
UserPromptSubmit ─┼──> chronos ──> ~/.claude/projects/…/<session>.jsonl
Stop ─────────────┘ │
├──> context injected into the model
statusLine ────────────────┴──> the clock you see| | v1 | v2 | |---|---|---| | Processes per tool call | 2 PowerShell | 0 | | Reading a 45.8 MB transcript | full re-parse, per call | 291 ms cold, 3 ms warm | | Duration resolution | whole seconds | milliseconds | | Failures recorded | 0 out of 36,243 | all of them | | Runtime dependencies | bash, PowerShell, jq, gzip, sha256sum | node |
chronos keeps a byte offset and a rolling aggregate per session, so only new bytes are ever parsed. The statusline is one Node process, once per assistant message.
State
| Path | What |
|---|---|
| ~/.chronos/config.json | Install record, and the statusline command chronos chained |
| ~/.chronos/cache/ | Byte offsets and aggregates. Delete any time |
It never writes to your transcripts and never sends anything anywhere.
Configuration
| Variable | Default | Effect |
|---|---|---|
| CHRONOS_HOME | ~/.chronos | State directory |
| CHRONOS_IDLE_NOTICE_SEC | 60 | Seconds away before the ◌ idle segment appears. 0 shows it immediately |
| CHRONOS_STATUSLINE_ASCII | unset | T, !, x instead of ⏱, ⚠, ✗ |
| NO_COLOR | unset | Drop ANSI colour everywhere |
Platform support, honestly
| Platform | State |
|---|---|
| Claude Code | Full. Hooks, statusline, slash commands, reports. This is what it is built for |
| Any agent that reads SKILL.md | The seven decision rules and shell fallbacks. No hooks, no reports |
v1 advertised eight platforms. Four of those ports were a README telling you to
copy a file, two shipped code labelled a stub, and the OpenCode plugin targeted an
API shape that does not match the published SDK. All of it now sits in
legacy/v1/ alongside a full account of what was wrong with
it. Two things that work beat eight that mostly do not.
Compared to everything else
| | Current date | Elapsed time | Per-tool timing | Loop detection | Statusline | Session report | Cross-session totals |
|---|---|---|---|---|---|---|---|
| chronos | ★ | ★ | ★ | ★ | ★ | ★ | ★ |
| hodgesmr/temporal-awareness | ★ | | | | | | |
| Temporal MCP servers | ★ | | | | | | |
| Nothing at all | | | | | | | |
Uninstall
node bin/chronos.mjs uninstall # hooks and statusline out, state kept
node bin/chronos.mjs uninstall --purge # also delete ~/.chronosContributing
npm test # 53 tests, nothing to installCONTRIBUTING.md has the rules this codebase lives by, every one of them learned by shipping the opposite. The research is in findings.md. The postmortem on v1, including the PowerShell automatic-variable bug that made it write 73,713 lines of nothing, is in legacy/v1/README.md.
License
MIT.
Keywords: Claude Code time tracking, AI agent observability, agent session analytics, retry loop detection, temporal awareness for LLM agents, parallel agent monitoring, Claude Code statusline, agent telemetry, developer time tracking, agent hooks.
