Skip to content

Repository files navigation

trajectoriz

Library and CLI to search, browse, and analyze past agent trajectory files. Supports Claude Code, Codex, OpenCode, Copilot, Hermes and more.

Installation

pip install trajectoriz

Search

trajectoriz-cli search lets you find past agent sessions — by what started them, or with --content, by everything that was discussed, run and edited inside them.

By default it searches first messages, IDs and agent names, which needs no trajectory parsing and answers the common question ("which session was that?") immediately. --content searches every step instead: slower, exhaustive.

# Locate a session (default: first messages and metadata)
trajectoriz-cli search "refactor auth"

# Search inside every step: tool calls, their results, all messages
trajectoriz-cli search "salary KTH overhead" --content

# AND semantics: all words must appear
trajectoriz-cli search "telegram send_message bot_token" --content

# OR semantics: use \| between alternatives
trajectoriz-cli search "pytest\|unittest" --content

# Restrict to the current project
trajectoriz-cli search "fix login bug" --local

With --content, results are a paginated Markdown table with trajectory ID, agent, date, step number, and a context snippet:

## Search: `salary KTH overhead` — 8 match(es)

| ID           | Agent  | Date       | Step | Snippet                                              |
|---|---|---|---|---|
| `cl-4d72f7b5`| claude | 2026-05-15 | 73   | …kth_salary = ws["E8"].value  # KTH  Direkt lön…   |
| `cl-4ef313e6`| claude | 2026-05-04 | 93   | …Organization: KTH Royal Institute of Technology…  |

Then inspect any result:

trajectoriz-cli show cl-4d72f7b5 --step 73

Search backends

Backends apply to --content searches only.

Backend Setup Semantics
sqlite (default) builds itself; trajectoriz-cli refresh --no-recoll to rebuild whole-word FTS5
grep none substring, in-process, always fresh
recoll trajectoriz-cli refresh --no-sqlite full Xapian index
trajectoriz-cli search "openssl handshake" --content --backend sqlite
trajectoriz-cli search "openssl handshake" --content --backend recoll

CLI

# List trajectories in the current directory
trajectoriz-cli list

# Show a trajectory (markdown, paginated)
trajectoriz-cli show cl-1234abcd
trajectoriz-cli show cl-1234abcd --last         # jump to the last page
trajectoriz-cli show cl-1234abcd --step 42      # jump to the page containing step 42
trajectoriz-cli show cl-1234abcd --html > out.html   # self-contained HTML export

# Trajectory metadata (JSON)
trajectoriz-cli info cl-1234abcd

# Blame a file — every agent edit in chronological order with line deltas
trajectoriz-cli blame src/main.py

# Aggregate statistics across all trajectories
trajectoriz-cli stats --all

# Aggregate shell-invoked programs across a repo
trajectoriz-cli advanced tools --dir /path/to/repo

Memory filesystem

trajectoriz-cli memory mounts a read-only FUSE filesystem where every local trajectory shows up as an ATIF v1.7 JSON file — so any tool that reads files (grep, an agent's own file tools, etc.) can browse past sessions directly, without going through this CLI.

pip install trajectoriz[fuse]   # requires libfuse (Linux) or macFUSE (macOS)

trajectoriz-cli memory                          # mounts ./memory (created if missing), daemonizes
trajectoriz-cli memory ~/mnt/traj-memory        # or mount elsewhere
trajectoriz-cli memory --foreground             # or run attached

ls memory
cat memory/README.md                            # what the directory is, in the directory
cat memory/2026-05-15_claude_cl-4d72f7b5.atif.json

trajectoriz-cli memory --unmount                # unmount (or: fusermount -u memory)

Use --dir PATH to expose a different repo's trajectories instead of the current directory's. If the mountpoint sits inside a git repo, it's added to that repo's .gitignore automatically.

The mount is built for tools that walk and read files: one store scan serves the whole directory listing (refreshed every couple of seconds, so new sessions still show up), and each trajectory's ATIF payload is rendered once per open, then served from memory. Reading every file in a mount of 30 trajectories takes ~0.1s.

If a mount ever stops responding — a killed daemon leaves the mountpoint attached but unserviced, which hangs anything that walks the tree it sits in — recover it with:

trajectoriz-cli memory --unmount ./memory       # lazily unmounts if it is wedged

Features

  • Search — metadata by default (no parsing), --content for full-content search across messages, tool calls and results with three backends (sqlite / grep / recoll); space-separated words are AND, \| is OR
  • Unified record API — iterate and parse sessions from Claude Code, Codex, Copilot, OpenCode, Hermes and more through a single iter_records() / parse_record() interface
  • Blame — trace every agent edit to a file across all trajectory sources, with line/char deltas
  • HTML exporttrajectoriz-cli show <id> --html renders a trajectory as a self-contained HTML page
  • ATIF exporttrajectoriz.atif translates parsed trajectories to ATIF v1.7 (Claude Code, Codex, Copilot, agentknit, or any iter_records()/parse_record() result)
  • Memory filesystemtrajectoriz-cli memory <mountpoint> mounts a read-only FUSE view where every local trajectory is one ATIF JSON file

Python API

from trajectoriz import iter_records, parse_record

# Iterate sessions across all supported agents (Claude, Codex, Copilot, OpenCode, …)
for record in iter_records():
    print(record.agent, record.timestamp[:10], record.first_msg[:60])

# Iterate sessions for the current project only
for record in iter_records(cwd="/path/to/repo"):
    trajectory = parse_record(record)
    if trajectory is not None:
        print(f"{record.agent}: {len(trajectory.steps)} steps, {trajectory.total_tokens} tokens")

License

MIT

About

Agentic tool to view, search and browse agent trajectories

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages