Inspect Claude Code local transcripts, reminders, and hook-visible lifecycle data.
Project description
neo
Website · Dashboard surface · Security notes
Local workflow forensics for Claude Code. neo indexes text found on disk, transcripts, retained telemetry rows, hook-visible lifecycle events, and memory artifacts into a SQLite database, then exposes them through a dashboard and an MCP server running on the same machine.
What It Does
- Reads local Claude Code artifacts directly from
~/.claude/and~/.neo/instead of relying on export surfaces that strip evidence - Separates measured, estimated, and inferred claims so row counts stay distinct from heuristics and anomaly labels
- Exposes a local operator surface through a browser dashboard, terminal commands, and an MCP server registered inside Claude Code
- Makes local overhead visible by surfacing reminder injections, sidechains, compaction churn, retained telemetry rows, and other traces the UI does not foreground
Install
Recommended — pipx:
pipx install neo-harnesster
neo
With pip:
pip install neo-harnesster
neo
Directly from the repo:
git clone https://github.com/asuramaya/neo.git
cd neo
python3 neo.py
Any of the above runs setup + ingest + dashboard in one step and opens
http://127.0.0.1:7777.
Restart Claude Code after the first run so the installed hooks begin capturing events.
CLI
neo # setup + ingest + dashboard
neo --setup # install hooks + register MCP server
neo --ingest # ingest data only
neo --dashboard # dashboard only
neo --dashboard --no-open # serve without opening a browser
neo --port 8888 # custom port
neo-tokens # data accounting in the terminal
neo-states diagram # state machine diagram
Live event stream:
tail -f ~/.neo/harness_log.jsonl
MCP Surface
neo runs as a single shared daemon per host. That one process serves the
dashboard and the MCP protocol over HTTP at http://127.0.0.1:7777/mcp,
guarded by a per-host bearer token. neo --setup registers it in
~/.claude.json as an http MCP server (not a per-session stdio subprocess),
so every Claude Code session connects to the same URL — one neo process per
host, no per-session fan-out, no version skew. On the next session start,
Claude Code connects automatically and the dashboard opens locally.
Setup also installs a systemd --user service (neo.service) that keeps the
daemon running — auto-start on login, restart on crash. Where systemd --user
is unavailable, start it manually with neo-mcp --http. See
Daemon below.
The server exposes 12 tools:
| Tool | What it returns |
|---|---|
status |
setup health + the live process registry across sessions (roles, code versions, version_skew flag) |
summary |
top-level row counts across all tables |
data_accounting |
full measured/estimated accounting |
tokens_report |
compact accounting totals with the measured-vs-estimated basis |
query_reminders |
reminder rows with file + line provenance |
query_sessions |
session list across projects with agent / compaction counts |
query_agents |
subagent genealogy and messages |
query_probe_events |
raw hook events, filterable by type |
query_telemetry |
retained telemetry rows |
query_memory_files |
persistent memory files per project |
state_model |
inferred state-model labels |
correlations |
cross-signal patterns (hook timeline, totals by type) |
Tools that read hook events filter out neo's own MCP traffic by default
(include_self=false) so observer overhead does not contaminate the picture.
Daemon
neo --setup writes a systemd --user unit at
~/.config/systemd/user/neo.service and enables + starts it. The unit runs the
shared daemon (neo-mcp --http), which owns the dashboard, periodic ingest, and
the HTTP /mcp endpoint. If multiple neo processes start, they elect a single
owner via a per-host lock; followers serve queries against the shared DB and
take over if the owner dies.
systemctl --user status neo # check the daemon
systemctl --user stop neo # stop it
systemctl --user disable neo # stop it auto-starting on login
neo-mcp --http # run the daemon manually (no systemd)
Evidence Model
neo labels its claims on purpose:
- measured — reminder rows, sessions, agents, tasks, memory files, telemetry rows, hook events; hidden-context share, data multiplier, and API call counts when transcripts carry API-reported token usage
- estimated — hidden-context share and data multiplier only when no token usage is recorded, where they fall back to on-disk transcript byte sizes
- inferred — state-model labels and anomaly interpretation from local timing + lifecycle patterns
For exact billable token numbers, use /usage inside Claude Code. neo does not
fabricate token totals.
What It Captures
| Source | Location | What |
|---|---|---|
| session transcripts | ~/.claude/projects/*.jsonl |
full conversations including system reminders |
| subagents and sidechains | ~/.claude/projects/*/subagents/ |
spawned transcripts and context copies |
| compaction events | ~/.neo/harness_log.jsonl |
PostCompact hook events from the probe |
| telemetry | ~/.claude/telemetry/ |
telemetry rows currently retained on disk |
| memory files | ~/.claude/projects/*/memory/ |
persistent context seeded by instances |
| tasks | ~/.claude/tasks/ |
task state across sessions |
| hook events | ~/.neo/harness_log.jsonl |
tool use, notifications, session lifecycle |
What It Cannot Capture
- server-side reasoning or model internals that never land on disk
- the contents of any secondary channel that is not persisted locally
- whether absent telemetry rows were uploaded, deleted, or never written locally
- system prompt assembly inside the compiled binary
- HTTPS request and response bodies without a proxy
Export Boundary
The /export command in Claude Code strips system reminders. The raw JSONL
files in ~/.claude/projects/ retain them. neo reads the raw files.
That boundary is the whole reason the project exists.
Project Layout
src/neo/
app.py setup, ingest, threaded HTTP server, systemd daemon install
mcp_server.py HTTP MCP server (/mcp on the shared daemon); owner election + process registry
db.py SQLite ingest + query layer
tokens.py visible vs hidden channel accounting
states.py inferred state model + anomaly labels
harness_probe.py hook script copied into ~/.neo/ by setup
dashboard.html single-file local dashboard
neo.py repo-clone launcher shim
test.py smoke tests
All data lives in ~/.neo/neo.db. The dashboard binds to 127.0.0.1 only.
Hooks
neo installs async hooks for 20 Claude Code event types:
PreToolUse PostToolUse PostToolUseFailure Notification SessionStart
SessionEnd Stop SubagentStart SubagentStop PreCompact
PostCompact UserPromptSubmit InstructionsLoaded PermissionRequest
PermissionDenied TaskCreated TaskCompleted FileChanged CwdChanged
ConfigChange
Security
- dashboard and
/mcpendpoint bind to127.0.0.1only and validate localHostheaders - the
/mcpendpoint requires a per-host bearer token stored in~/.neo/ POST /api/ingestrequires a same-origin browser request~/.neo/is created with private permissions where the OS allows it- neo does not transmit your data anywhere
- hooks run async and do not block Claude Code operation
- setup installs a
systemd --userservice (neo.service) that auto-starts the local daemon on login and restarts it on crash; remove it withsystemctl --user disable --now neo(see Daemon) - no dependencies beyond Python stdlib
Requirements
- Python 3.10+
- Claude Code installed (
~/.claude/settings.jsonmust exist)
Upgrade Note
If you used the project under its old harnesster name, the first run of neo
or python3 neo.py migrates ~/.harnesster/ to ~/.neo/ and renames
harnesster.db to neo.db. Hook commands in settings.json are rewritten
automatically.
The harnesster command remains as a forwarding shim.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file neo_harnesster-0.2.1.tar.gz.
File metadata
- Download URL: neo_harnesster-0.2.1.tar.gz
- Upload date:
- Size: 62.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e6c4c0692ec4ca39bfb2fa4599fc7b1c573dade5fa7c332615b72465e580177
|
|
| MD5 |
7c8a1ab7f9615a03add1f8456c5c3ecd
|
|
| BLAKE2b-256 |
3b80cc9e14f7bb5db5f8ab5ceba6b43402bc0d61230ee25a2d0a787aa3e898ff
|
Provenance
The following attestation bundles were made for neo_harnesster-0.2.1.tar.gz:
Publisher:
publish.yml on asuramaya/neo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
neo_harnesster-0.2.1.tar.gz -
Subject digest:
2e6c4c0692ec4ca39bfb2fa4599fc7b1c573dade5fa7c332615b72465e580177 - Sigstore transparency entry: 1740559313
- Sigstore integration time:
-
Permalink:
asuramaya/neo@edbbd89c55dd7219b28594b3b87954546f549a62 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/asuramaya
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@edbbd89c55dd7219b28594b3b87954546f549a62 -
Trigger Event:
release
-
Statement type:
File details
Details for the file neo_harnesster-0.2.1-py3-none-any.whl.
File metadata
- Download URL: neo_harnesster-0.2.1-py3-none-any.whl
- Upload date:
- Size: 62.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6fbc96782d046deac86b673a1990887bf8042e39c496b0e6d49584b3fe0a0e7
|
|
| MD5 |
c9c0d7ec8607ff909d2d5949331ae052
|
|
| BLAKE2b-256 |
55bdf9bf32085e771aaaa1fd21bb2a9ad9493b8b79456b1bfe03ef205f8336f9
|
Provenance
The following attestation bundles were made for neo_harnesster-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on asuramaya/neo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
neo_harnesster-0.2.1-py3-none-any.whl -
Subject digest:
a6fbc96782d046deac86b673a1990887bf8042e39c496b0e6d49584b3fe0a0e7 - Sigstore transparency entry: 1740559340
- Sigstore integration time:
-
Permalink:
asuramaya/neo@edbbd89c55dd7219b28594b3b87954546f549a62 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/asuramaya
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@edbbd89c55dd7219b28594b3b87954546f549a62 -
Trigger Event:
release
-
Statement type: