ConductorScore Scanner — Python skill that extracts structural metrics from local Claude Code transcripts (privacy-load-bearing)
翻译准备中
技能Python · ShellGitHub @flatironconsulting自行安装运营者未确认
试用过了吗? 点一下就好,无需登录。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗The open-source scanner behind conductorscore.com.
This is the code that runs on your machine, reads your local Claude Code, Codex, and Cursor transcripts, and uploads a numbers-only payload to the server for scoring. It's public, auditable, and dependency-free on purpose — the whole point of ConductorScore is that you can verify what crosses the wire before you trust the score.
~/.claude/projects/**/*.jsonl (your transcripts)
↓
scanner (this repo) (pure function)
↓
numeric payload (≈38 fields/session)
↓
conductorscore.com (scoring)
Per Claude Code, Codex, or Cursor session in the last 30 days, the client emits ~50 fields (output_schema.py is the source of truth). Every field is one of:
token_data_missing (Cursor-only in practice: set when the device couldn't read a session's token usage, so the server excludes it from cost/efficiency denominators instead of treating it as zero-cost), orBash / Edit, MCP server/tool names in plaintext like mcp__github__create_issue, plugin command names in plaintext like my-plugin:deploy, model IDs like claude-opus-4-7 / gpt-5-codex / composer-2.5, slash-command names like /plan (read from Claude Code's structured <command-name> marker, never scraped from your prose), a closed provider enum (claude / codex / cursor), and plan-signal enums like EnterPlanMode. These are the names you configured — never their arguments, inputs, or outputs.Bash commands contribute their first command token (any leading NAME=value env assignment is stripped first, so a secret value can't ride along; and if the command is invoked by path — e.g. ./deploy.sh, /Users/you/clients/acme/run.sh — the token collapses to the literal path, so the path never crosses) and Edit/Write approvals contribute a one-way hash of the top-level directory — never the path itself.CLAUDE.md content — only the line count.This invariant is enforced in CI on every push and pull request. An integration test feeds synthetic transcripts — seeded with planted secret markers in every place content could leak (user prompts, file paths, tool inputs, slash-command arguments, assistant text, inline Bash environment variables, and Bash commands invoked by path) — through the real scanner, then asserts that none of those planted secrets appears anywhere in the upload payload. A companion sweep re-runs the check for every anti-pattern detector. (Like any sentinel test, it proves the absence of the secrets it plants rather than a mathematical impossibility — but the planting covers every field that crosses the wire, and the client is open source so you can audit the rest.)
For the field-by-field schema, see WIRE_FORMAT.md. A sample payload lives at wire_format_sample.json.
Don't take our word for it — the test that enforces the no-leak guarantee ships in this repo and runs in under a second:
git clone https://github.com/flatironconsulting/conductorscore
cd conductorscore
pip install -e ".[dev]" # the only dev dependency is pytest; the client itself has zero runtime deps
# Run just the privacy-invariant test:
pytest tests/integration/test_extractor_integration.py -v
# Or run the whole suite (unit + integration):
pytest
The privacy test (tests/integration/test_extractor_integration.py) plants unique secret strings into a synthetic ~/.claude transcript tree, runs the actual extract() path the installed skill uses, and fails if any planted secret — or any raw prompt, path, or tool argument — survives into the serialized payload. To convince yourself it's real, edit the scanner to leak something on purpose and watch the test go red.
This is the same pytest invocation our CI runs (.github/workflows/ci.yml), so a green badge means the invariant held on the exact code you're reading.
The same on-device data the scanner reads can be rendered as a timeline you can inspect yourself — no server round-trip, nothing uploaded. Ask the skill to "visualize this session", or run the viewer directly:
# the session you're in (after a `claude --resume` / `/resume`, or `codex resume`)
python3 ~/.claude/skills/conductorscore/scripts/session_viewer.py
# list your local sessions, then render one
python3 ~/.claude/skills/conductorscore/scripts/session_viewer.py --list
python3 ~/.claude/skills/conductorscore/scripts/session_viewer.py --pick 0
It writes a self-contained HTML page — the session timeline, the Interactive / Background leverage table your score is computed from, the longest unattended run, and subagent panels — and opens it in your browser.
Redacted by default: bubbles show only the wire-equivalent view (hashes +
token counts + tool names, exactly what an upload would contain), so a rendered
page is safe to share. Add --no-redact to reveal the real transcript text —
safe locally, since the viewer uploads nothing, and most useful for hands-on
debugging. The viewer reuses the same time accounting (scripts/time_accounting.py,
built on scripts/turn_classifier.py) that produces your score, so the
bars it draws match the numbers you're scored on.
If you're here to verify the data path before installing, these are the files that matter:
| File | What to check |
|---|---|
scripts/scanner.py | Top-level extractor. Reads JSONL, builds the payload, and hashes the session id + project root (sha256[:16], no salts, not reversible). |
scripts/output_schema.py | The exact shape of the upload payload. Every field is named here. |
scripts/agents/*/events.py and scripts/core/ | Per-agent (Claude, Codex, Cursor) transcript parsers and shared helpers — what the client reads off disk. |
scripts/scan.py | Runs the scan and uploads the payload — the score upload (POST /api/ingest) is here. |
scripts/run.py | CLI orchestrator: spawns scan.py, polls a local status file, prints the summary. |
scripts/device_flow.py, scripts/reauth.py | GitHub OAuth device-flow login — identity only, separate from the score upload. |
WIRE_FORMAT.md | Versioned schema, including a per-version changelog. |
Zero runtime dependencies — Python stdlib only (pyproject.toml). The whole package is about 17k lines of Python (scripts/, excluding tests).
Install the skill with the GitHub CLI or skills.sh:
# GitHub CLI (gh) — works for every agent, including Codex and Cursor
gh skill install flatironconsulting/conductorscore conductorscore
# skills.sh — Claude Code and other agents that read ~/.agents/skills/
npx skills add flatironconsulting/conductorscore
Both installers work for Codex: the skill resolves its scripts relative to
wherever it lands (skills.sh installs Codex skills under ~/.agents/skills/, the
GitHub CLI under ~/.codex/skills/). An end-to-end test
(tests/e2e/test_skills_sh_codex_install.py) pins this — it installs via
npx skills add and confirms Codex can actually run the result.
Then run the skill: /conductorscore in a Claude Code session, or
$conductorscore in Codex. On the first run the skill signs you in with GitHub,
scans your transcripts on-device, and uploads only the numbers. First score in
under 60 seconds.
Login uses GitHub's OAuth device flow (it prints a URL and a code to authorize in
your browser), requesting the read:user and user:email scopes only. The
installed client never requests repo scope and never transmits any other GitHub
credential (such as a local gh CLI token). Separately, web sign-in may request
broader GitHub access so the server can count commits across repositories you can
read. The full server-side privacy policy is at conductorscore.com/privacy.
Apache License 2.0 — see LICENSE.
docs/CURSOR_FORMAT.md | Field-name-level notes on the Cursor on-disk formats the Cursor parser reads. |