A skill for coding agents that answers "where was I?" by reading the session off disk, rather than asking the model to remember.
You lose the thread for ordinary reasons. The context window filled up and got compacted, the session crashed, you came back the next morning, or you were running four agents and forgot which one this was. At that moment the model's own recollection is the least reliable evidence available, and it is usually the only thing anyone consults.
Everything needed is already on disk: the conversation transcript your harness writes as it goes, the todo list, and git. This reads those and prints a brief.
Run against a demo repo with a two-message session (paths shortened):
# WHERE WAS I cwd=~/code/billing now=2026-08-29 16:20
## SESSION
harness=claude-code id=11111111-2222-3333-4444-555555555555
transcript=~/.claude/projects/-Users-me-code-billing/11111111-....jsonl
last activity=2026-08-29 16:20
## WHAT THE USER SAID (last 2 of 2, oldest first)
- [2026-08-29T15:02:11] rate() returns Infinity when b is 0, fix it and add a test
- [2026-08-29T15:04:40] cover negatives too
## LAST THING I SAID
- [2026-08-29T15:03:04] Guarded the zero case in billing.js. Writing the test now.
## RECENT TOOL CALLS (last 1 of 1)
- [2026-08-29T15:02:20] Edit(file_path=billing.js)
## TODOS
- [completed] Guard division by zero in rate()
- [in_progress] Add tests for zero and negative divisors
## GIT
repo root: ~/code/billing
branch: master
status:
## master
M billing.js
?? billing.test.js
untracked:
billing.test.js
diffstat vs HEAD:
billing.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
log:
075d0f7 add billing helper
## FILES TOUCHED (last 180 min)
16:20 billing.test.js
16:20 billing.js
That is the output of tests/smoke.sh, which builds the repo and the transcript
from scratch so you can see the shape without trusting a screenshot.
SKILL.md then tells the agent to turn that into five lines: what you were
doing, the evidence for it, the state of the tree, the next steps, and anything
the artifacts do not settle.
As a Claude Code plugin:
/plugin marketplace add danieljohnmorris/where-was-i
/plugin install where-was-i@danieljohnmorris
Or clone it, which is what you want for Codex, pi, omp and the rest:
git clone https://github.com/danieljohnmorris/where-was-i.git
cd where-was-i
./install.shinstall.sh symlinks the skill into ~/.claude/skills, ~/.omp/agent/skills
and ~/.pi/agent/skills where those exist, and writes a Codex prompt to
~/.codex/prompts/where-was-i.md. Symlinks mean git pull updates every install.
Use ./install.sh copy if you would rather have copies.
Nothing stops you skipping all that and running python3 skills/where-was-i/bin/where-was-i.py
directly. It is one file, python3 only, no packages to install. Tested on the
python3 that ships with macOS (3.9.6).
claude plugin details where-was-i@danieljohnmorris reports the skill at roughly
150 tokens always-on and 1.8k when it fires.
In Claude Code, say "where was I" or "catch me up" and the skill triggers on the
description. In Codex, /where-was-i. Anywhere else, run the script.
python3 skills/where-was-i/bin/where-was-i.py # this directory, this session
python3 skills/where-was-i/bin/where-was-i.py --list # what it can read on this machine
python3 skills/where-was-i/bin/where-was-i.py --cwd ~/code/other # a different checkout
python3 skills/where-was-i/bin/where-was-i.py --only claude-code --sections transcript,git| Harness | State it reads | Status |
|---|---|---|
| Claude Code | ~/.claude/projects/<slug>/*.jsonl, ~/.claude/history.jsonl, ~/.claude/todos/ |
tested against real sessions |
| Codex | ~/.codex/sessions/**/rollout-*.jsonl |
tested against real sessions |
| pi | ~/.pi/agent/sessions/**/session.jsonl |
tested against real sessions |
| omp | ~/.omp/agent/history.db (sqlite) |
tested, prompts only, no assistant output |
| Kilo Code CLI | ~/.kilocode/cli/global/tasks/<id>/ |
tested against real sessions |
| opencode | ~/.local/share/opencode/storage/{session,message,part} |
format read from real files, no matching session to test with |
| Kilo Code, Cline, Roo in VS Code | ~/Library/Application Support/Code/User/globalStorage/<ext>/tasks/ |
same layout as the CLI, untested |
| kimi, hermes, continue, zed, coworker, gemini, crush, amp, cursor, aider, deepseek | generic reader | gemini tested, the rest by shape only |
Claude Code, Codex, pi, omp, opencode and the Cline-family task directories have dedicated readers. Everything else goes through the generic reader, which finds a transcript by looking for the working directory inside the file, then pulls role and content out of whatever JSON or JSONL shape it finds.
Flags cover one-off runs:
| Flag | Effect |
|---|---|
--cwd PATH |
Reconstruct a different directory |
--session ID |
A specific session. Defaults to the current one where the harness exports its id |
--only a,b |
Read only these harnesses |
--skip a,b |
Ignore these harnesses |
--sections a,b |
Any of transcript,earlier_sessions,todos,git,files |
--minutes N |
Recent-file window, default 180 |
--max-user N |
User messages to print, default 20 |
--max-chars N |
Per-message cap, default 1200 |
--tools N |
Recent tool calls, default 20. 0 drops the section |
--all |
Every harness with history here, not just the most recent |
--list |
Known harnesses, whether installed, on or off |
--init-config |
Write config.json from what is currently detected |
For anything permanent, --init-config writes ~/.config/where-was-i/config.json,
and config.example.json in the repo shows the fields:
{
"harnesses": { "gemini": false, "cursor-agent": false },
"sections": { "files": false },
"generic_roots": { "myharness": "~/.myharness/sessions" },
"limits": { "max_user": 20, "max_chars": 1200, "tools": 20, "minutes": 180 }
}Harnesses absent from the file stay on, so it only needs the ones you are
turning off. WHERE_WAS_I_CONFIG=path points at a different file.
Add one line to generic_roots in config.json with the directory your harness
writes sessions to. If the transcript mentions its own working directory
anywhere, which most do, that is enough. A dedicated reader in skills/where-was-i/bin/where-was-i.py
is only needed when it does not, which is why Kilo Code has one.
Pull requests for new harnesses are welcome. tests/smoke.sh is the check to
run.
Reading the transcript is the obvious approach and it is the one that fails. My current session transcript is 356KB, roughly 90,000 tokens. The script's output is 5.9KB. The skill fires precisely when context is short, so loading the transcript back into the window to work out what was in the window is self-defeating.
Beyond that: one tool call instead of ten, the same five sections every time
rather than a different summary per run, and formats that do not yield to a
shell one-liner. omp keeps prompts in sqlite. opencode splits one message across
message/<id>.json and several part/<id>.json files. Kilo Code records no
working directory at all, so matching means scanning the file for the path.
It reports and stops. It does not resume the work, and SKILL.md tells the
agent not to start.
It reconstructs artifacts, not reasoning. If you decided something and never wrote it down or acted on it, this will not recover it.
Uncommitted changes outrank the transcript. If the transcript says a refactor
finished and git diff shows it half applied, the diff is what you get told.
It writes nothing except config.json when you ask for it, and reads only the
directories listed above.
Sessions run in a parent directory are used only when nothing matches the current directory exactly, and they come with a note saying so.
MIT