Skip to main content

Reflect on how you actually use AI coding agents. Reads your local Claude Code, Codex, and Gemini CLI traces, builds rich per-session narratives, and synthesizes cross-session patterns you can act on this week — with an interactive HTML dashboard.

Project description

tessera

Reflect on how you actually use AI coding agents.

Reads your local Claude Code, Codex, and Gemini CLI session traces, builds rich per-session narratives, then synthesizes cross-session patterns you can act on this week — surfaced as an interactive HTML dashboard you open in any browser. No API key, no server, no telemetry.

🔍 Live demo → (fictional data, click around to see what tessera produces — no install needed)

Tessera dashboard — Findings view

Adding another agent CLI is one parser function; the narrative + synthesis layers are agent-agnostic.

What you actually get

Run one command, open one HTML file. Two views:

Findings — the cross-session synthesis:

Headline: 40+ atella sessions each rediscover python=.venv/bin/python, git-root≠stella-backend/, PYTHONPATH=src — a single CLAUDE.md would eliminate 200+ wasted events/week

If you do one thing this week: printf '...' >> stella-backend/pyproject.toml AND create stella-backend/CLAUDE.md: …

§3 Missing git fetch before PR diff inflates scope 5-10x high · workflow · 8 sessions · ~46m friction · trend: stable In 6 sessions, diffing a PR against local main without first fetching showed 35-69 files instead of 6-14. Fix: prepend git fetch origin main && to the array-pr-review skill.

Week-over-week: 4 new · 2 continuing · 1 worsening · 3 resolved since last

Plus quick wins (one-line fixes you can copy with a button), per-project drilldowns, and inline [u]/[w]/[k]/[s] rating buttons that feed the next run's prompt.

Explore — browse all the data:

  • Sessions table (sortable, filterable by agent / project / waste signature, click to drill into the full per-session narrative — tasks, friction with quotes, key decisions with retrospectives, dead ends, env issues, deterministic stats)
  • All recurring environmental issues across all sessions, sorted by occurrence count
  • All counterfactuals + lessons in three columns
  • Per-project deep view

Every cited session is verifiable — citations use 4-char ref tokens (S001S{n}) that map deterministically back to real session_ids. Fabrication rate by design: 0%.

The output is also written as synthesis.json (raw) and synthesis.md (shareable markdown).

How it works

~/.claude/projects/        ─┐
~/.codex/sessions/         ─┤    [1] normalize        [2] per-session             [3] cross-session       [4] dashboard
~/.gemini/tmp/             ─┴──▶ symlink into temp ─▶ narrative (1 LLM call ─▶ synthesis (1 LLM call ─▶ synthesis.html
                                  no copies, no       per session, cached by      on all narratives,         (Findings + Explore,
                                  source mods)        content hash)               ref-token citations)       inline rating)

Two LLM stages, both via your local claude CLI:

  1. Per-session narrative — each session's compressed event stream (~30-50K tokens) gets one Sonnet 4.6 call producing structured narrative (goal, tasks, friction moments, key decisions, dead ends, recurring env issues, counterfactual). Cached by content hash; re-runs skip unchanged sessions.
  2. Cross-session synthesis — all narratives compacted to high-signal fields (~150K tokens), one Sonnet 4.6 call producing observations + quick wins + per-project headlines. Validator drops any cited ref not in the input set.

See docs/schema/v1.md for the full per-session schema, docs/ARCHITECTURE.md for module-level flow, and docs/adding-an-agent.md to plug in your own agent CLI (Aider, Cline, Cursor, etc.) as a single Python file in ~/.config/tessera/normalizers/.

Install

Requires Python 3.11+ and at least one of these LLM CLIs authenticated:

  • claude (Anthropic Claude Code) — default backend, no ANTHROPIC_API_KEY needed; routes through your Claude Code auth
  • codex (OpenAI Codex CLI) — works with ChatGPT subscription auth
  • gemini (Google Gemini CLI) — works with gcloud auth
pip install tessera-agents
# or
uv tool install tessera-agents

The PyPI package is tessera-agents (the bare name tessera was taken). The CLI binary, slash command, and import are all just tessera.

Pick a backend

Default is Claude. Switch with --backend:

tessera run --backend codex     # uses your `codex exec` for narrate + synthesis
tessera run --backend gemini    # uses `gemini -p`
tessera weekly --backend codex  # the closed loop on a different model
TESSERA_BACKEND=codex tessera run   # or set the env var globally

tessera doctor shows which backends are installed.

Use

First run (do this once)

tessera doctor             # ~2s. checks `claude` CLI, agent trace dirs, gives a cost estimate.
tessera run --lookback-days 30 --min-events 10
# → prompts you to confirm estimated cost before the LLM stage
# → opens synthesis.html when done

A heavy first run (250+ sessions) can hit $10-15. The pre-flight prompt tells you the number before you commit; pass --limit 100 to bound it.

The closed loop: tessera weekly (the main habit)

tessera weekly             # last 7 days, ~5 min cached
# 1. Narrates new sessions + synthesizes patterns
# 2. Evaluates every active experiment from prior weeks:
#    "did the user actually try this? did dead-ends drop?"
# 3. Opens the dashboard

What you do on the dashboard each Monday (~10 min):

  1. Read the "Last week's experiments" verdicts at top (graduated / not tried / inconclusive)
  2. Skim "Since last run" deltas (new / escalating / resolved)
  3. Click [useful] on 1–3 behavioral patterns you commit to trying this week
  4. Click SAVE, paste the one-liner — those patterns are now active experiments

Next week, tessera will evaluate whether the patterns you committed to actually moved the needle. This is the self-improving loop: insight → commitment → measured outcome → next insight, every week.

Automate it via launchd (Mondays 9am):

cp launchd/com.tessera.weekly.plist ~/Library/LaunchAgents/
sed -i '' "s|YOUR_USERNAME|$(whoami)|g" ~/Library/LaunchAgents/com.tessera.weekly.plist
launchctl load ~/Library/LaunchAgents/com.tessera.weekly.plist

Auditing the loop

Every recommendation, every rating, every evaluation lands in an append-only logbook at ~/.config/tessera/logbook.jsonl. View it:

tessera logbook --summary           # aggregate stats: acceptance + graduation rate
tessera logbook --event insight.surfaced --tail 20
tessera logbook --json | jq '...'   # programmatic queries

One-off retrospective (the original mode)

tessera run                # last 30 days, ~5min cached / ~50min cold
open synthesis.html        # read findings, drill in, rate inline

After rating: click the floating SAVE button on the dashboard, paste the resulting one-liner in your terminal. Ratings feed the next run's synthesis prompt and the in-session coach (see below).

tessera run --all-time            # full history, no time filter
tessera run --lookback-days 60    # custom window
tessera run --min-events 5        # include shorter sessions (default 20)

In-session real-time nudges (sibling tool)

The tessera-live plugin watches your live sessions for known waste patterns (browser spirals, blind retries, runaway call rates, etc.) and nudges Claude with a short note when one appears. Silent on the happy path. Reads your dashboard ratings to enrich nudges with your validated playbook.

Power-user subcommands

tessera narrate              # per-session extraction only (no synthesis)
tessera synthesize           # synthesis only (reads existing narratives)
tessera synthesize --project atella   # filter to one project
tessera dashboard            # re-render the HTML from existing synthesis + narratives
tessera rate                 # interactive CLI rating (alternative to inline)
tessera rate-import < ratings.json  # apply ratings from dashboard
tessera eval                 # quality metrics (fabrication rate, etc.)

Slash command (inside Claude Code)

/tessera            # 30-day window
/tessera 60         # 60-day window
/tessera all-time   # everything

Common options

--lookback-days N         Window in days. Default 30. Use --all-time for no cap.
--min-events N            Skip sessions with fewer events. Default 20.
--limit N                 Cap to N most-recent sessions. 0 = no limit.
--model NAME              Claude model. Default claude-sonnet-4-6.
--concurrency N           Per-session extraction concurrency. Default 10.
--force                   Bypass narrative cache (still writes).
--output PATH             Where to write synthesis JSON. Default ./synthesis.json.
--narratives-dir DIR      Per-session JSON output dir. Default ./narratives.
--format text|json|markdown   Terminal output format. Default text.
--no-history              Don't read or save to history.
--prior-runs N            How many prior runs to feed back as context. Default 3.
--claude-projects DIR     Override Claude Code projects dir.
--codex-sessions DIR      Override Codex sessions dir.
--gemini-tmp DIR          Override Gemini CLI tmp dir.

Cost

Scenario Sessions Cost (Sonnet 4.6) Wall clock
Weekly run, cache hits 50-100 ~$1-3 5-10 min
Cold run on a new machine 50-100 ~$5-12 30-50 min
Full historical backfill 1000-2000 ~$15-30 (one-time) 4-6 hours
Re-synthesis only (no narrate) any ~$0.50 5-15 min

All token usage routes through your claude CLI auth — no separate billing.

What it doesn't do

  • Doesn't run continuously. Call it when you want a reflection.
  • Doesn't score your work. No leaderboard, no "healthy %."
  • Doesn't hallucinate evidence. Every cited ref maps to a real session; fabricated refs are dropped with a visible count in the dashboard's "Fabrications" stat.
  • Doesn't classify with keywords. Task types and waste signatures come from LLM judgment grounded in event evidence, validated against a closed vocabulary.
  • Doesn't send your data anywhere. Local read of trace files; LLM calls go through your existing auth; output stays on disk.

Privacy

Everything runs locally. Trace files are read from ~/.claude/projects/, ~/.codex/sessions/, and ~/.gemini/tmp/ (or wherever you've configured those agents). The two LLM calls (per-session narrative + cross-session synthesis) route through your existing authenticated claude CLI — no separate API key, no telemetry, no analytics. Cached narratives, synthesis output, and run history live under ~/.cache/tessera/ and ~/.config/tessera/.

The dashboard quotes verbatim text from your sessions — friction moments, error messages, decision rationale. Review before sharing screenshots or synthesis.md — they may contain code snippets, file paths, secrets you typed into prompts, or other content from your sessions.

Repo layout

tessera/
├── .claude-plugin/plugin.json     # Claude Code plugin manifest
├── commands/tessera.md            # /tessera slash command
├── docs/
│   ├── schema/v1.md               # per-session narrative schema spec
│   └── ARCHITECTURE.md            # module-level pipeline overview
├── pyproject.toml                 # publishes tessera to PyPI
├── src/tessera/
│   ├── cli.py                     # `tessera <command>` entry points
│   ├── pipeline.py                # symlink-based normalize orchestrator
│   ├── _normalize_script.py       # cross-agent event schema normalizer
│   ├── history.py                 # ratings + prior-run context store
│   ├── narratives/
│   │   ├── deterministic.py       # event-stream metadata extraction
│   │   ├── compressor.py          # event stream → compact narrative
│   │   ├── extractor.py           # per-session LLM call
│   │   ├── validator.py           # schema validation rules
│   │   ├── cache.py               # per-session content-hash cache
│   │   ├── pipeline.py            # per-session orchestrator
│   │   ├── synthesis.py           # cross-session LLM call + ref-citation validator
│   │   ├── render.py              # text + markdown renderers
│   │   ├── dashboard.py           # interactive HTML dashboard
│   │   └── eval.py                # quality metrics
│   └── coach/                     # in-session hook (separate plugin: ../tessera-live/)
├── tests/                         # pytest
├── CONTRIBUTING.md
├── LICENSE                        # MIT
└── README.md

One repo, three distribution paths. The Claude Code plugin and the pip package share the same source.

Contributing

See CONTRIBUTING.md. The most useful PR is probably a parser for a new agent CLI — drop a normalize_<agent>() function into _normalize_script.py matching the existing event schema, and the entire downstream pipeline (narratives, synthesis, dashboard) works on it for free.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tessera_agents-0.7.2.tar.gz (188.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tessera_agents-0.7.2-py3-none-any.whl (169.3 kB view details)

Uploaded Python 3

File details

Details for the file tessera_agents-0.7.2.tar.gz.

File metadata

  • Download URL: tessera_agents-0.7.2.tar.gz
  • Upload date:
  • Size: 188.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tessera_agents-0.7.2.tar.gz
Algorithm Hash digest
SHA256 a50696f42093231e6b47a690735775fa78bb42ca5e08a460e99b94c6636946b2
MD5 665cc26f774e09e05aa029845575b164
BLAKE2b-256 b8cf9f05c40c318883deab9ed96bbf13f9ac0eb53f70d158bca038e1811ee0d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tessera_agents-0.7.2.tar.gz:

Publisher: publish.yml on annasba07/tessera

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tessera_agents-0.7.2-py3-none-any.whl.

File metadata

  • Download URL: tessera_agents-0.7.2-py3-none-any.whl
  • Upload date:
  • Size: 169.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tessera_agents-0.7.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c7f5148cee15c54789cf751a593c5f98627b639d4ed62e80a44b777062345f9f
MD5 33316ee81611e33d7e73defd220ebeef
BLAKE2b-256 ad236f71717477c8ebb2f69cad42a98f29c481cb764cb700167b12fe1d4b3ca9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tessera_agents-0.7.2-py3-none-any.whl:

Publisher: publish.yml on annasba07/tessera

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page