Agent Activity Panel
Updated August 3, 2026
The Agent Activity Panel does two things: it shows what your agents are doing, and it shows the files they touched. Both live in one panel, split across two tabs, so you can check on a whole workspace without switching between gems and shards one at a time.
Opening the panel
There are two ways in, depending on the scope you want:
- All gems: click the diamond icon at the top (or left end, in top mode) of the crystal rail. This opens the panel across every open gem.
- One gem: click a gem’s tile in the rail once to bring it into focus, then click it again to open the panel scoped to just that gem.
The panel opens on agents │ touches. The agents tab is the live view; the touches tab is the record of what got written where.
agents
The agents tab gathers each agent’s activity and token usage in one place, so you can see at a glance which agents are working, which are idle, and where your tokens are going across the whole workspace.
For a deeper look at how crystl accounts for tokens per turn, including what each plugin and skill costs, see context load tracking.
touches
An isolated shard promises that your agent’s work is a branch you can read, merge, or throw away. Two kinds of activity escape that promise and leave nothing behind: a write that lands outside the worktree (a home dotfile, another project’s directory, a global install) has no diff and no undo, and a credential read is invisible after the fact even though agents are routinely instructed to go and read .env.local for service keys.
Neither is a thing to stop. Both are things you want to be able to look at after an unattended fan-out has been running while you slept. So crystl records them, and the touches tab is where you read them back.
What gets recorded, and what you see by default
Every file an agent writes through a tool call that names it is recorded, and so is every read of a credential path. Reading anything else produces no entry: this is not a history of every file your agent opened. (“Names it” is doing real work in that sentence — see what it cannot see.)
Each recorded path is then classified, and the tab shows you the classes worth looking at. Labels are terse on purpose — the row is one narrow line carrying the gem, the shard, the action, a count, the tool and an age, so each class says verb + target and nothing else:
| Shown by default | What it is |
|---|---|
| wrote credential | A write to a credential path — .env*, ~/.ssh, ~/.aws, ~/.npmrc, *.pem, and the like — wherever it lives, including inside the shard’s own repo. |
| read credential | A read of one of those paths, again wherever it lives. |
| wrote main checkout | An isolated shard writing into its own gem’s mainline checkout — outside its worktree, and in no branch at all. It will not merge when the worktree merges and will not vanish when it is discarded. |
| wrote other worktree | An isolated shard writing into a different worktree of the same gem, so the change lands in another agent’s branch. |
| wrote other gem | A write under a different open gem’s root. |
| wrote shared config | A write through one of the config symlinks crystl manages (CLAUDE.md, AGENTS.md, .mcp.json, .claude/) into the gem that owns it. |
| wrote outside project | A write anywhere else: home dotfiles, system paths, global installs. |
Two more classes are recorded but sit behind the panel’s show all toggle:
| Behind show all | What it is |
|---|---|
| wrote in bounds | A write under the shard’s own root. Fully reversible — it’s in the diff, or you discard the branch — so it doesn’t need your attention. |
| wrote scratch/cache | A write into a scratch or cache location, matched after symlinks are resolved, so /tmp still counts as scratch despite being a symlink to /private/tmp on macOS. |
That split is the whole point. A badge that counts ordinary in-repo edits is a badge nobody believes, so routine work is kept out of the default view rather than out of the record.
A credential write outranks location, deliberately. A write to a .env sitting inside the project is classified as a credential write, not as ordinary in-bounds work, so it surfaces. Reading .env.local is the documented normal workflow and shows up as exactly that; writing ~/.ssh/authorized_keys, ~/.aws/credentials, ~/.npmrc, or a project .env is key injection or a silent credential rotation. Without that precedence an in-repo .env write would be filed as routine and never seen, which would make the record blindest exactly where it matters most.
Reading a row
One row per path, aggregated: repeated edits to the same file raise a count instead of flooding the list.
path · gem · shard · what it did · count · tool · age
“What it did” is the plain-words class from the tables above, so a row reads as a sentence rather than as a category you have to decode. Two actions sit at the end: reveal opens the file in Finder, and seen marks the row reviewed.
Colour ranks the surfaced classes against each other:
- Red — wrote credential. The top of the scale, wherever the file lives.
- Amber — read credential, wrote main checkout, wrote other worktree, or wrote other gem. The rows you most often actually need to look at.
- Plain — wrote shared config, or wrote outside project. Surfaced, but not shouting.
The path is shown both as the tool reported it and as it actually resolved, when those differ. That is what makes a symlink escape legible: worktree/link → ~/.zshrc reads as the escape it is, while still counting as one row per real destination.
The badge and the card
A flag badge (⚑N) below the shard’s tab counts that shard’s unreviewed surfaced entries. It’s tinted to the shard’s own color and sits under the tab beside the ↑N merge badge, following the same grammar, so a shard that did something worth a look says so without the panel open. Click the flag to open this panel on the touches tab and read exactly what it counted.
Reviewed is an explicit action. Opening or scrolling the panel does not clear the badge, because a glance would silently discard the exact count you meant to act on. Click seen on a row and it clears; if that same path is touched again afterwards the row goes back to unreviewed, since the count and the last-seen time both changed.
You get one notification card per shard per app run, on that shard’s first surfaced entry, with a review button. After that the shard stays silent. A card per event would be noise you switch off within a day.
Remote shards say so
crystl classifies paths on local shards. A remote shard over SSH reports remote path coverage unavailable rather than a count of zero. A zero would read as “this worker touched nothing,” which is the one wrong answer this tab must never give. Reveal-in-Finder is local-only for the same reason.
Three things to know
It is in memory, and it clears when crystl restarts. There is no file on disk keeping this. The record is there to answer “what did the fan-out do while I was asleep,” and the app stays running across that; quit crystl and it starts empty. Closing a shard or a gem does not clear it, though. Finishing with a worker is a normal end-of-quest action and it must not erase what that worker did, so entries from closed shards stay readable.
It is a record, not a gate. Nothing here blocks, prompts, or changes what gets approved. The four approval presets keep exactly the meaning they had before, and Auto still means Auto. This is on purpose rather than a limitation: an approval prompt raised at 2am under Auto is not a gate, because nobody is there to answer it. It just parks the worker until morning and turns an unattended run into a stalled one. Recording is the only intervention that still means something when nobody is watching.
Only the count leaves the machine. The bridge carries a shard’s unreviewed count and its coverage state to the phone and to crystl shards. The paths never go anywhere. That is a deliberate line, not an oversight: a list of the paths your agents read is an index of where your credentials live on this machine. It is excluded from crystl report and from --diagnostics, which stays a numbers-only health snapshot. Paths are all that is ever recorded, too, never file contents or tool output.
What it cannot see
Worth knowing, so you read the tab for what it is:
- Arbitrary shell writes are invisible.
cp,>,sed -i,npm install -g, and installer scripts write to unbounded destinations, and a heuristic there would look like coverage while missing most of it. Structured writes are covered: your agent’s ordinary write and edit tools, and Codex’sapply_patch(every file in a patch, checked separately). - Credential reads in shell commands are caught, via a conservative scan for the short list of credential paths, so
cat ~/.ssh/…andsource .envdo register. Variable indirection and generated paths do not. - Only agents running in crystl shards are recorded. This is not machine-wide.
- Remote paths are not classified yet, and say so instead of guessing.
Related
- isolated sessions: the hook-based guard for supported structured writes, plus the narrower Bash self-destruction guard
- approval modes: the four presets, unchanged by any of the above
- context load tracking: per-turn token accounting behind the agents tab