transcripto 0.1.5__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- transcripto-0.2.1/PKG-INFO +315 -0
- transcripto-0.2.1/README.md +297 -0
- {transcripto-0.1.5 → transcripto-0.2.1}/pyproject.toml +3 -3
- transcripto-0.2.1/tests/test_harness_backfill.py +203 -0
- transcripto-0.2.1/tests/test_public_flow.py +351 -0
- transcripto-0.2.1/tests/test_replay.py +612 -0
- transcripto-0.2.1/transcripto.egg-info/PKG-INFO +315 -0
- {transcripto-0.1.5 → transcripto-0.2.1}/transcripto.egg-info/SOURCES.txt +5 -0
- transcripto-0.2.1/transcripto.egg-info/top_level.txt +3 -0
- {transcripto-0.1.5 → transcripto-0.2.1}/transcripto.py +1003 -860
- transcripto-0.2.1/transcripto_core.py +440 -0
- transcripto-0.2.1/transcripto_replay.py +185 -0
- transcripto-0.1.5/PKG-INFO +0 -411
- transcripto-0.1.5/README.md +0 -393
- transcripto-0.1.5/transcripto.egg-info/PKG-INFO +0 -411
- transcripto-0.1.5/transcripto.egg-info/top_level.txt +0 -1
- {transcripto-0.1.5 → transcripto-0.2.1}/LICENSE +0 -0
- {transcripto-0.1.5 → transcripto-0.2.1}/setup.cfg +0 -0
- {transcripto-0.1.5 → transcripto-0.2.1}/transcripto.egg-info/dependency_links.txt +0 -0
- {transcripto-0.1.5 → transcripto-0.2.1}/transcripto.egg-info/entry_points.txt +0 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: transcripto
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Instant replay for coding agents. Inspect requests, tool calls, and recorded results across Claude Code, Codex, and Cursor. Local, stdlib-only.
|
|
5
|
+
Author: Oscar Morke
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Morkeeth/transcripto
|
|
8
|
+
Project-URL: Source, https://github.com/Morkeeth/transcripto
|
|
9
|
+
Keywords: claude-code,coding-agents,transcripts,local-first,analytics
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Topic :: Utilities
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# Transcripto
|
|
20
|
+
|
|
21
|
+
**You might already be keeping a journal. Read your side of it.**
|
|
22
|
+
|
|
23
|
+
Your agent transcripts contain what you asked for, what you changed your mind
|
|
24
|
+
about, and what you kept coming back to. Transcripto helps you find those words
|
|
25
|
+
and read the recorded work around them.
|
|
26
|
+
|
|
27
|
+
Claude Code · Codex · Cursor. Local files. No account. No runtime dependencies.
|
|
28
|
+
|
|
29
|
+
## Start with something you remember saying
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
uvx --from transcripto==0.2.1 transcripto ask "retry"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Replace `retry` with a word you remember using. `ask` searches messages identified
|
|
36
|
+
as yours and shows dated snippets, newest first. It refreshes the local index
|
|
37
|
+
automatically. The first search indexes the selected history; a large archive
|
|
38
|
+
can take minutes. Add `--harness claude`, `--harness codex`, or `--harness cursor`
|
|
39
|
+
to limit that scan. It does not generate a diary or interpret your personality.
|
|
40
|
+
|
|
41
|
+
Each hit prints an `Open:` command. Run that command to open the exact request
|
|
42
|
+
and its recorded work. This also works when search matches a word variant
|
|
43
|
+
(such as `retry` matching `retried`) or several requests share the same words.
|
|
44
|
+
|
|
45
|
+
You can also search replay directly:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
uvx --from transcripto==0.2.1 transcripto replay "retry"
|
|
49
|
+
|
|
50
|
+
# Or open your latest human session:
|
|
51
|
+
uvx --from transcripto==0.2.1 transcripto
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Replay puts your request, tool calls and recorded results in order. Failed edits
|
|
55
|
+
stay failed. Missing results stay unknown. Status describes tool execution,
|
|
56
|
+
not whether the task was done correctly.
|
|
57
|
+
|
|
58
|
+
Or install with `python3 -m pip install transcripto==0.2.1`, then run
|
|
59
|
+
`transcripto ask "retry"`. Requires Python 3.9 or newer.
|
|
60
|
+
|
|
61
|
+
## Try the stranger flow without your transcripts
|
|
62
|
+
|
|
63
|
+
The bundled public example is synthetic. It works in an isolated home and does
|
|
64
|
+
not depend on agent dotfiles:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
INSTALL="$(mktemp -d)"
|
|
68
|
+
python3 -m pip install --no-deps --no-build-isolation --target "$INSTALL" .
|
|
69
|
+
export HOME="$(mktemp -d)"
|
|
70
|
+
transcripto() { PYTHONPATH="$INSTALL" python3 -m transcripto "$@"; }
|
|
71
|
+
|
|
72
|
+
transcripto import-example
|
|
73
|
+
transcripto ask "What changed about the forecast cache?"
|
|
74
|
+
transcripto changes
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`ask` cites the imported JSONL line for every hit. `changes` is a focused view
|
|
78
|
+
of the request that was revised, the correction, and its recorded follow-up.
|
|
79
|
+
It labels missing results rather than turning a change of mind into a score.
|
|
80
|
+
|
|
81
|
+
To carry that correction to a different receiver:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
transcripto handoff "30 seconds" \
|
|
85
|
+
--to-harness codex --output "$HOME/codex-inbox/correction.json"
|
|
86
|
+
transcripto receive-handoff \
|
|
87
|
+
"$HOME/codex-inbox/correction.json" --as-harness codex \
|
|
88
|
+
--output "$HOME/codex-work/receiver-brief.md"
|
|
89
|
+
cat "$HOME/codex-work/receiver-brief.md"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The brief includes the cited correction, recorded follow-up statuses
|
|
93
|
+
(failed / succeeded / unknown), and an `Open:` command for the exact request.
|
|
94
|
+
If the source moved, disappeared, or no longer holds the cited request, the brief
|
|
95
|
+
marks evidence uncertain and shows only the packet's own statuses as provisional. It does not invoke a receiver agent or prove
|
|
96
|
+
adoption. Synthetic provenance stays visible in search, changes, and handoffs.
|
|
97
|
+
Handoff files are local and mode `0600`; they can contain transcript text and
|
|
98
|
+
paths, so review them before sharing.
|
|
99
|
+
|
|
100
|
+
### Cross-harness lab (failed / succeeded / unknown)
|
|
101
|
+
|
|
102
|
+
For a receiving agent that needs to find a prior episode and reopen exact
|
|
103
|
+
evidence without private history:
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
transcripto import-lab
|
|
107
|
+
transcripto ask "retry"
|
|
108
|
+
# run each printed Open: command
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
All lab records are labelled synthetic. Claude shows a failed edit, Codex a
|
|
112
|
+
succeeded check, Cursor an unknown missing result.
|
|
113
|
+
|
|
114
|
+
### Offline flight card
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
transcripto quickstart --wheel /absolute/path/to/transcripto-0.2.1-py3-none-any.whl
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Prints install, `import-lab`, search, and reopen commands for a built wheel
|
|
121
|
+
without PyPI. See also `docs/OFFLINE-QUICKSTART.md`.
|
|
122
|
+
|
|
123
|
+
**Your files remain yours.** Transcripto does not upload transcript content or
|
|
124
|
+
execute commands found in it. Search output, replay and JSON can contain private
|
|
125
|
+
words and paths; review anything you choose to share. It reads existing files,
|
|
126
|
+
not deleted history. Check your agent's retention settings and keep your own
|
|
127
|
+
backup if you want a lasting record. Authorship detection differs by harness;
|
|
128
|
+
[see the limits below](#what-each-harness-supports).
|
|
129
|
+
|
|
130
|
+
## Find the thing you remember
|
|
131
|
+
|
|
132
|
+
Search automatically refreshes a local index. No setup command is required.
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
transcripto ask "retry" # your submitted words
|
|
136
|
+
transcripto search "retry" # prompts, replies, and tool text
|
|
137
|
+
transcripto find parser.py # recorded file operations and attempts
|
|
138
|
+
transcripto trace "retry" # an alias into result-aware replay
|
|
139
|
+
transcripto sessions # sessions with submitted prompts
|
|
140
|
+
transcripto stats # activity counts
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
A failed or unconfirmed file change is labelled an **attempt**, never `WROTE`.
|
|
144
|
+
Queries with `--harness` or `--root` are scoped to that selection even if the
|
|
145
|
+
index already contains another corpus. `index` and `watch` remain available for
|
|
146
|
+
explicit refresh and background polling.
|
|
147
|
+
|
|
148
|
+
## The replay
|
|
149
|
+
|
|
150
|
+
This is output from `replay --demo`. **All prompts and results in this example
|
|
151
|
+
are invented.** The demo goes through the same parser as a real transcript.
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
THE COMEBACK · claude · request 1
|
|
155
|
+
You asked: "Fix the login redirect and run its tests."
|
|
156
|
+
|
|
157
|
+
1 FAIL edit src/login.py
|
|
158
|
+
Tool error: Error: text not found [call L2 → result L3]
|
|
159
|
+
2 OK edit src/login.py
|
|
160
|
+
Tool reported success. [call L4 → result L5]
|
|
161
|
+
3 FAIL check pytest tests/test_login.py
|
|
162
|
+
Tool error: Process exited with code 1 [call L6 → result L7]
|
|
163
|
+
4 OK edit src/login.py
|
|
164
|
+
Tool reported success. [call L8 → result L9]
|
|
165
|
+
5 OK check pytest tests/test_login.py
|
|
166
|
+
Tool reported success. [call L10 → result L11]
|
|
167
|
+
|
|
168
|
+
Agent said: "The redirect is fixed and the tests pass."
|
|
169
|
+
|
|
170
|
+
Recorded: 3 succeeded · 2 failed · 0 unknown
|
|
171
|
+
Status describes a tool result, not task correctness. Missing results stay unknown.
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The headings have rules. **The comeback** means a recorded failure was followed
|
|
175
|
+
by success for the same operation and target, without a later failed or unknown
|
|
176
|
+
attempt on that target. **The snag** means a failure is
|
|
177
|
+
present. **The missing receipt** means a result is unknown. **The answer** means
|
|
178
|
+
there were no recorded tool calls; an explanation may have been the whole task.
|
|
179
|
+
These are descriptions of the sequence, not grades for you or your agent.
|
|
180
|
+
|
|
181
|
+
On your own history, each replay names its source file and line numbers, plus a
|
|
182
|
+
command that reopens that exact request. Long sequences open around the first
|
|
183
|
+
failure or change and tell you what was omitted. `--all` shows the full sequence.
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
transcripto # latest session you submitted a request in
|
|
187
|
+
transcripto replay --failures # most recent request with a recorded failure
|
|
188
|
+
transcripto replay "login redirect" # find requests containing these words
|
|
189
|
+
transcripto replay path/to/session.jsonl # inspect one transcript
|
|
190
|
+
transcripto replay --session 3f9c1a2b # explicitly select a session prefix
|
|
191
|
+
transcripto replay path/to/session.jsonl --episode 3 --all
|
|
192
|
+
transcripto replay path/to/session.jsonl --line 42 # exact request from an ask hit
|
|
193
|
+
transcripto replay latest --json # structured events, evidence, source lines
|
|
194
|
+
transcripto replay latest --share # counts + caveat; no prompts or paths
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
`--share` is intentionally small. Full replay output and JSON contain your own
|
|
198
|
+
words and local paths. The tool does not upload either.
|
|
199
|
+
|
|
200
|
+
## What each harness supports
|
|
201
|
+
|
|
202
|
+
| Feature | Claude Code | Codex | Cursor |
|
|
203
|
+
|---|---|---|---|
|
|
204
|
+
| Replay, search, ask, find, trace, sessions, stats | Yes | Yes | Yes |
|
|
205
|
+
| Tool attempts | Native tool calls | Direct calls and supported static wrappers | `StrReplace`, `Shell`, `Write`, and other calls |
|
|
206
|
+
| Execution status | Matched results | Matched results; ambiguous wrappers stay unknown | Unknown when the export omits results or call IDs |
|
|
207
|
+
| Authorship | `promptSource` typed/queued, excluding injected/tool records | User messages with known injected context excluded | `<user_query>` wrapper; a weaker signal |
|
|
208
|
+
| Coach, export-run | Yes | Yes | Yes, with missing evidence preserved |
|
|
209
|
+
| API-equivalent cost | Yes | Not supported | Not supported |
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
transcripto replay --harness claude
|
|
213
|
+
transcripto replay --harness codex
|
|
214
|
+
transcripto replay --harness cursor
|
|
215
|
+
transcripto search "retry" --harness codex
|
|
216
|
+
transcripto replay --root /path/to/transcripts
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Default roots are `~/.claude/projects`, `~/.codex`, and `~/.cursor`.
|
|
220
|
+
Codex reads sessions and archived sessions. Cursor reads the per-session files
|
|
221
|
+
under `projects/*/agent-transcripts/*/`. Latest-session replay skips subagents
|
|
222
|
+
and files without a submitted human request.
|
|
223
|
+
|
|
224
|
+
Cursor exports often contain calls without results. That is useful evidence
|
|
225
|
+
of an attempt, but not enough to claim success. Transcripto does not substitute
|
|
226
|
+
an assistant's closing message or a `turn_ended` record for the missing result.
|
|
227
|
+
|
|
228
|
+
## The evidence contract
|
|
229
|
+
|
|
230
|
+
1. A tool call is an **attempt**.
|
|
231
|
+
2. A matching result may establish **succeeded** or **failed** execution.
|
|
232
|
+
3. A missing result, a running command, or an ambiguous result is **unknown**.
|
|
233
|
+
4. An exit code of zero is not proof that the requested task is correct.
|
|
234
|
+
5. A later human request opens a new episode. Its work is never absorbed into
|
|
235
|
+
the previous request because the words happen to overlap.
|
|
236
|
+
6. A command mentioning `git commit` is not necessarily a commit. Quoted text,
|
|
237
|
+
dry runs, and compound shell commands are not promoted to commit evidence.
|
|
238
|
+
|
|
239
|
+
The tool never executes transcript commands. It parses a limited set of static
|
|
240
|
+
Codex wrapper forms; arbitrary JavaScript and multiple nested child calls are
|
|
241
|
+
not reconstructed. A long-running call can remain unknown when completion is
|
|
242
|
+
only present in a later polling call. Cross-session durability, semantic task
|
|
243
|
+
completion, and live repository state are not inferred from transcript text.
|
|
244
|
+
|
|
245
|
+
## Coach without invented grades
|
|
246
|
+
|
|
247
|
+
`transcripto coach` shows descriptive request history. It no longer recommends
|
|
248
|
+
prompt habits, labels a no-edit answer a bad prompt, or applies one person's
|
|
249
|
+
correction-rate calibration to someone else's data.
|
|
250
|
+
|
|
251
|
+
Habit proportions include **change attempts with known outcomes**. Unknown
|
|
252
|
+
outcomes and read-only tasks are excluded. The groups overlap and the requests
|
|
253
|
+
can be correlated, so these proportions are not significance tests or causal
|
|
254
|
+
advice. No best/worst ranking is printed. Correction markers are a lexical
|
|
255
|
+
estimate with false positives and misses, not a guaranteed lower bound.
|
|
256
|
+
|
|
257
|
+
Coach JSON is marked `transcripto.coach/2`. Legacy `durable`/`survived` fields
|
|
258
|
+
refer only to observed successful change results, not lasting work. Unknown
|
|
259
|
+
request outcomes have `survived: null`. `durable_rate` uses only known change
|
|
260
|
+
requests as its denominator and is null when there are none. `best_prompt` and `worst_prompt` are
|
|
261
|
+
retained as null compatibility fields. Use `successful_request`,
|
|
262
|
+
`failed_request`, and replay's event status to inspect evidence.
|
|
263
|
+
|
|
264
|
+
`export-run latest` always prints JSON. Its
|
|
265
|
+
existing `transcripto.export-run/1` keys remain available. `records` counts
|
|
266
|
+
normalized message records. `files_touched` lists attempted file targets,
|
|
267
|
+
including reads; it is not a successful-change count. Reflog commits are local
|
|
268
|
+
working-tree events inside the available timestamp window, not proof that this
|
|
269
|
+
agent caused them. Without a usable window, the commit fields are null.
|
|
270
|
+
|
|
271
|
+
## Privacy and limits
|
|
272
|
+
|
|
273
|
+
The three runtime modules contain no network client, telemetry, account flow,
|
|
274
|
+
or process execution. Package installation (`pip` or `uvx`) is a separate
|
|
275
|
+
operation that may contact a package registry and write a package cache.
|
|
276
|
+
|
|
277
|
+
Replay and coach read transcripts without making an index. Search writes text
|
|
278
|
+
and file metadata to `~/.trace/trace.db`. A new index directory is private;
|
|
279
|
+
database and WAL files use mode `0600`. The index stays after the command exits.
|
|
280
|
+
Schema upgrades rebuild it locally. `replay --demo` briefly writes an invented
|
|
281
|
+
transcript to a temporary directory and removes it afterward.
|
|
282
|
+
|
|
283
|
+
Malformed records and unreadable files produce diagnostics. Search indexes the
|
|
284
|
+
valid records of partially malformed files and repeats the warning on later
|
|
285
|
+
queries until the source is repaired. A wholly unreadable file keeps any prior
|
|
286
|
+
indexed copy, with an explicit warning; replay always reads the source. Files larger than
|
|
287
|
+
128 MiB are skipped before parsing; lines larger than 8 MiB are discarded as
|
|
288
|
+
whole records. Split larger files into smaller JSONL files to inspect them.
|
|
289
|
+
Individual displayed text fields are bounded at 16,000 characters. Replay's
|
|
290
|
+
source references let you inspect the original. Terminal control sequences are
|
|
291
|
+
removed from rendered transcript content.
|
|
292
|
+
|
|
293
|
+
## Development
|
|
294
|
+
|
|
295
|
+
Python 3.9+, standard library only. The CLI remains in `transcripto.py`;
|
|
296
|
+
`transcripto_core.py` owns normalization and evidence; `transcripto_replay.py`
|
|
297
|
+
owns replay selection and presentation. All fixtures committed here are synthetic.
|
|
298
|
+
|
|
299
|
+
```sh
|
|
300
|
+
python3 -m unittest discover -s tests -v
|
|
301
|
+
for test in test_*.sh; do bash "$test" || exit; done
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
`test_distribution.sh` requires the development-only `build` package. It builds
|
|
305
|
+
an sdist, builds the wheel from that archive, installs without dependencies in a
|
|
306
|
+
fresh virtual environment, and exercises discovery, search and exact replay
|
|
307
|
+
across all three harnesses in an isolated synthetic HOME.
|
|
308
|
+
|
|
309
|
+
The regression cases include failed edits and commits, missing/mismatched
|
|
310
|
+
results, Cursor call shapes, Codex wrappers, result attribution across prompts,
|
|
311
|
+
rollback order, malformed JSON, a sparse 2 GiB file, terminal controls, private
|
|
312
|
+
index permissions, incremental search, and cross-harness retrieval.
|
|
313
|
+
|
|
314
|
+
MIT. Open an issue with the **record shape** that fails, or a synthetic
|
|
315
|
+
reproduction. Your real prompt text is not needed.
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# Transcripto
|
|
2
|
+
|
|
3
|
+
**You might already be keeping a journal. Read your side of it.**
|
|
4
|
+
|
|
5
|
+
Your agent transcripts contain what you asked for, what you changed your mind
|
|
6
|
+
about, and what you kept coming back to. Transcripto helps you find those words
|
|
7
|
+
and read the recorded work around them.
|
|
8
|
+
|
|
9
|
+
Claude Code · Codex · Cursor. Local files. No account. No runtime dependencies.
|
|
10
|
+
|
|
11
|
+
## Start with something you remember saying
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
uvx --from transcripto==0.2.1 transcripto ask "retry"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Replace `retry` with a word you remember using. `ask` searches messages identified
|
|
18
|
+
as yours and shows dated snippets, newest first. It refreshes the local index
|
|
19
|
+
automatically. The first search indexes the selected history; a large archive
|
|
20
|
+
can take minutes. Add `--harness claude`, `--harness codex`, or `--harness cursor`
|
|
21
|
+
to limit that scan. It does not generate a diary or interpret your personality.
|
|
22
|
+
|
|
23
|
+
Each hit prints an `Open:` command. Run that command to open the exact request
|
|
24
|
+
and its recorded work. This also works when search matches a word variant
|
|
25
|
+
(such as `retry` matching `retried`) or several requests share the same words.
|
|
26
|
+
|
|
27
|
+
You can also search replay directly:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
uvx --from transcripto==0.2.1 transcripto replay "retry"
|
|
31
|
+
|
|
32
|
+
# Or open your latest human session:
|
|
33
|
+
uvx --from transcripto==0.2.1 transcripto
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Replay puts your request, tool calls and recorded results in order. Failed edits
|
|
37
|
+
stay failed. Missing results stay unknown. Status describes tool execution,
|
|
38
|
+
not whether the task was done correctly.
|
|
39
|
+
|
|
40
|
+
Or install with `python3 -m pip install transcripto==0.2.1`, then run
|
|
41
|
+
`transcripto ask "retry"`. Requires Python 3.9 or newer.
|
|
42
|
+
|
|
43
|
+
## Try the stranger flow without your transcripts
|
|
44
|
+
|
|
45
|
+
The bundled public example is synthetic. It works in an isolated home and does
|
|
46
|
+
not depend on agent dotfiles:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
INSTALL="$(mktemp -d)"
|
|
50
|
+
python3 -m pip install --no-deps --no-build-isolation --target "$INSTALL" .
|
|
51
|
+
export HOME="$(mktemp -d)"
|
|
52
|
+
transcripto() { PYTHONPATH="$INSTALL" python3 -m transcripto "$@"; }
|
|
53
|
+
|
|
54
|
+
transcripto import-example
|
|
55
|
+
transcripto ask "What changed about the forecast cache?"
|
|
56
|
+
transcripto changes
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`ask` cites the imported JSONL line for every hit. `changes` is a focused view
|
|
60
|
+
of the request that was revised, the correction, and its recorded follow-up.
|
|
61
|
+
It labels missing results rather than turning a change of mind into a score.
|
|
62
|
+
|
|
63
|
+
To carry that correction to a different receiver:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
transcripto handoff "30 seconds" \
|
|
67
|
+
--to-harness codex --output "$HOME/codex-inbox/correction.json"
|
|
68
|
+
transcripto receive-handoff \
|
|
69
|
+
"$HOME/codex-inbox/correction.json" --as-harness codex \
|
|
70
|
+
--output "$HOME/codex-work/receiver-brief.md"
|
|
71
|
+
cat "$HOME/codex-work/receiver-brief.md"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The brief includes the cited correction, recorded follow-up statuses
|
|
75
|
+
(failed / succeeded / unknown), and an `Open:` command for the exact request.
|
|
76
|
+
If the source moved, disappeared, or no longer holds the cited request, the brief
|
|
77
|
+
marks evidence uncertain and shows only the packet's own statuses as provisional. It does not invoke a receiver agent or prove
|
|
78
|
+
adoption. Synthetic provenance stays visible in search, changes, and handoffs.
|
|
79
|
+
Handoff files are local and mode `0600`; they can contain transcript text and
|
|
80
|
+
paths, so review them before sharing.
|
|
81
|
+
|
|
82
|
+
### Cross-harness lab (failed / succeeded / unknown)
|
|
83
|
+
|
|
84
|
+
For a receiving agent that needs to find a prior episode and reopen exact
|
|
85
|
+
evidence without private history:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
transcripto import-lab
|
|
89
|
+
transcripto ask "retry"
|
|
90
|
+
# run each printed Open: command
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
All lab records are labelled synthetic. Claude shows a failed edit, Codex a
|
|
94
|
+
succeeded check, Cursor an unknown missing result.
|
|
95
|
+
|
|
96
|
+
### Offline flight card
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
transcripto quickstart --wheel /absolute/path/to/transcripto-0.2.1-py3-none-any.whl
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Prints install, `import-lab`, search, and reopen commands for a built wheel
|
|
103
|
+
without PyPI. See also `docs/OFFLINE-QUICKSTART.md`.
|
|
104
|
+
|
|
105
|
+
**Your files remain yours.** Transcripto does not upload transcript content or
|
|
106
|
+
execute commands found in it. Search output, replay and JSON can contain private
|
|
107
|
+
words and paths; review anything you choose to share. It reads existing files,
|
|
108
|
+
not deleted history. Check your agent's retention settings and keep your own
|
|
109
|
+
backup if you want a lasting record. Authorship detection differs by harness;
|
|
110
|
+
[see the limits below](#what-each-harness-supports).
|
|
111
|
+
|
|
112
|
+
## Find the thing you remember
|
|
113
|
+
|
|
114
|
+
Search automatically refreshes a local index. No setup command is required.
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
transcripto ask "retry" # your submitted words
|
|
118
|
+
transcripto search "retry" # prompts, replies, and tool text
|
|
119
|
+
transcripto find parser.py # recorded file operations and attempts
|
|
120
|
+
transcripto trace "retry" # an alias into result-aware replay
|
|
121
|
+
transcripto sessions # sessions with submitted prompts
|
|
122
|
+
transcripto stats # activity counts
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
A failed or unconfirmed file change is labelled an **attempt**, never `WROTE`.
|
|
126
|
+
Queries with `--harness` or `--root` are scoped to that selection even if the
|
|
127
|
+
index already contains another corpus. `index` and `watch` remain available for
|
|
128
|
+
explicit refresh and background polling.
|
|
129
|
+
|
|
130
|
+
## The replay
|
|
131
|
+
|
|
132
|
+
This is output from `replay --demo`. **All prompts and results in this example
|
|
133
|
+
are invented.** The demo goes through the same parser as a real transcript.
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
THE COMEBACK · claude · request 1
|
|
137
|
+
You asked: "Fix the login redirect and run its tests."
|
|
138
|
+
|
|
139
|
+
1 FAIL edit src/login.py
|
|
140
|
+
Tool error: Error: text not found [call L2 → result L3]
|
|
141
|
+
2 OK edit src/login.py
|
|
142
|
+
Tool reported success. [call L4 → result L5]
|
|
143
|
+
3 FAIL check pytest tests/test_login.py
|
|
144
|
+
Tool error: Process exited with code 1 [call L6 → result L7]
|
|
145
|
+
4 OK edit src/login.py
|
|
146
|
+
Tool reported success. [call L8 → result L9]
|
|
147
|
+
5 OK check pytest tests/test_login.py
|
|
148
|
+
Tool reported success. [call L10 → result L11]
|
|
149
|
+
|
|
150
|
+
Agent said: "The redirect is fixed and the tests pass."
|
|
151
|
+
|
|
152
|
+
Recorded: 3 succeeded · 2 failed · 0 unknown
|
|
153
|
+
Status describes a tool result, not task correctness. Missing results stay unknown.
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The headings have rules. **The comeback** means a recorded failure was followed
|
|
157
|
+
by success for the same operation and target, without a later failed or unknown
|
|
158
|
+
attempt on that target. **The snag** means a failure is
|
|
159
|
+
present. **The missing receipt** means a result is unknown. **The answer** means
|
|
160
|
+
there were no recorded tool calls; an explanation may have been the whole task.
|
|
161
|
+
These are descriptions of the sequence, not grades for you or your agent.
|
|
162
|
+
|
|
163
|
+
On your own history, each replay names its source file and line numbers, plus a
|
|
164
|
+
command that reopens that exact request. Long sequences open around the first
|
|
165
|
+
failure or change and tell you what was omitted. `--all` shows the full sequence.
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
transcripto # latest session you submitted a request in
|
|
169
|
+
transcripto replay --failures # most recent request with a recorded failure
|
|
170
|
+
transcripto replay "login redirect" # find requests containing these words
|
|
171
|
+
transcripto replay path/to/session.jsonl # inspect one transcript
|
|
172
|
+
transcripto replay --session 3f9c1a2b # explicitly select a session prefix
|
|
173
|
+
transcripto replay path/to/session.jsonl --episode 3 --all
|
|
174
|
+
transcripto replay path/to/session.jsonl --line 42 # exact request from an ask hit
|
|
175
|
+
transcripto replay latest --json # structured events, evidence, source lines
|
|
176
|
+
transcripto replay latest --share # counts + caveat; no prompts or paths
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`--share` is intentionally small. Full replay output and JSON contain your own
|
|
180
|
+
words and local paths. The tool does not upload either.
|
|
181
|
+
|
|
182
|
+
## What each harness supports
|
|
183
|
+
|
|
184
|
+
| Feature | Claude Code | Codex | Cursor |
|
|
185
|
+
|---|---|---|---|
|
|
186
|
+
| Replay, search, ask, find, trace, sessions, stats | Yes | Yes | Yes |
|
|
187
|
+
| Tool attempts | Native tool calls | Direct calls and supported static wrappers | `StrReplace`, `Shell`, `Write`, and other calls |
|
|
188
|
+
| Execution status | Matched results | Matched results; ambiguous wrappers stay unknown | Unknown when the export omits results or call IDs |
|
|
189
|
+
| Authorship | `promptSource` typed/queued, excluding injected/tool records | User messages with known injected context excluded | `<user_query>` wrapper; a weaker signal |
|
|
190
|
+
| Coach, export-run | Yes | Yes | Yes, with missing evidence preserved |
|
|
191
|
+
| API-equivalent cost | Yes | Not supported | Not supported |
|
|
192
|
+
|
|
193
|
+
```sh
|
|
194
|
+
transcripto replay --harness claude
|
|
195
|
+
transcripto replay --harness codex
|
|
196
|
+
transcripto replay --harness cursor
|
|
197
|
+
transcripto search "retry" --harness codex
|
|
198
|
+
transcripto replay --root /path/to/transcripts
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Default roots are `~/.claude/projects`, `~/.codex`, and `~/.cursor`.
|
|
202
|
+
Codex reads sessions and archived sessions. Cursor reads the per-session files
|
|
203
|
+
under `projects/*/agent-transcripts/*/`. Latest-session replay skips subagents
|
|
204
|
+
and files without a submitted human request.
|
|
205
|
+
|
|
206
|
+
Cursor exports often contain calls without results. That is useful evidence
|
|
207
|
+
of an attempt, but not enough to claim success. Transcripto does not substitute
|
|
208
|
+
an assistant's closing message or a `turn_ended` record for the missing result.
|
|
209
|
+
|
|
210
|
+
## The evidence contract
|
|
211
|
+
|
|
212
|
+
1. A tool call is an **attempt**.
|
|
213
|
+
2. A matching result may establish **succeeded** or **failed** execution.
|
|
214
|
+
3. A missing result, a running command, or an ambiguous result is **unknown**.
|
|
215
|
+
4. An exit code of zero is not proof that the requested task is correct.
|
|
216
|
+
5. A later human request opens a new episode. Its work is never absorbed into
|
|
217
|
+
the previous request because the words happen to overlap.
|
|
218
|
+
6. A command mentioning `git commit` is not necessarily a commit. Quoted text,
|
|
219
|
+
dry runs, and compound shell commands are not promoted to commit evidence.
|
|
220
|
+
|
|
221
|
+
The tool never executes transcript commands. It parses a limited set of static
|
|
222
|
+
Codex wrapper forms; arbitrary JavaScript and multiple nested child calls are
|
|
223
|
+
not reconstructed. A long-running call can remain unknown when completion is
|
|
224
|
+
only present in a later polling call. Cross-session durability, semantic task
|
|
225
|
+
completion, and live repository state are not inferred from transcript text.
|
|
226
|
+
|
|
227
|
+
## Coach without invented grades
|
|
228
|
+
|
|
229
|
+
`transcripto coach` shows descriptive request history. It no longer recommends
|
|
230
|
+
prompt habits, labels a no-edit answer a bad prompt, or applies one person's
|
|
231
|
+
correction-rate calibration to someone else's data.
|
|
232
|
+
|
|
233
|
+
Habit proportions include **change attempts with known outcomes**. Unknown
|
|
234
|
+
outcomes and read-only tasks are excluded. The groups overlap and the requests
|
|
235
|
+
can be correlated, so these proportions are not significance tests or causal
|
|
236
|
+
advice. No best/worst ranking is printed. Correction markers are a lexical
|
|
237
|
+
estimate with false positives and misses, not a guaranteed lower bound.
|
|
238
|
+
|
|
239
|
+
Coach JSON is marked `transcripto.coach/2`. Legacy `durable`/`survived` fields
|
|
240
|
+
refer only to observed successful change results, not lasting work. Unknown
|
|
241
|
+
request outcomes have `survived: null`. `durable_rate` uses only known change
|
|
242
|
+
requests as its denominator and is null when there are none. `best_prompt` and `worst_prompt` are
|
|
243
|
+
retained as null compatibility fields. Use `successful_request`,
|
|
244
|
+
`failed_request`, and replay's event status to inspect evidence.
|
|
245
|
+
|
|
246
|
+
`export-run latest` always prints JSON. Its
|
|
247
|
+
existing `transcripto.export-run/1` keys remain available. `records` counts
|
|
248
|
+
normalized message records. `files_touched` lists attempted file targets,
|
|
249
|
+
including reads; it is not a successful-change count. Reflog commits are local
|
|
250
|
+
working-tree events inside the available timestamp window, not proof that this
|
|
251
|
+
agent caused them. Without a usable window, the commit fields are null.
|
|
252
|
+
|
|
253
|
+
## Privacy and limits
|
|
254
|
+
|
|
255
|
+
The three runtime modules contain no network client, telemetry, account flow,
|
|
256
|
+
or process execution. Package installation (`pip` or `uvx`) is a separate
|
|
257
|
+
operation that may contact a package registry and write a package cache.
|
|
258
|
+
|
|
259
|
+
Replay and coach read transcripts without making an index. Search writes text
|
|
260
|
+
and file metadata to `~/.trace/trace.db`. A new index directory is private;
|
|
261
|
+
database and WAL files use mode `0600`. The index stays after the command exits.
|
|
262
|
+
Schema upgrades rebuild it locally. `replay --demo` briefly writes an invented
|
|
263
|
+
transcript to a temporary directory and removes it afterward.
|
|
264
|
+
|
|
265
|
+
Malformed records and unreadable files produce diagnostics. Search indexes the
|
|
266
|
+
valid records of partially malformed files and repeats the warning on later
|
|
267
|
+
queries until the source is repaired. A wholly unreadable file keeps any prior
|
|
268
|
+
indexed copy, with an explicit warning; replay always reads the source. Files larger than
|
|
269
|
+
128 MiB are skipped before parsing; lines larger than 8 MiB are discarded as
|
|
270
|
+
whole records. Split larger files into smaller JSONL files to inspect them.
|
|
271
|
+
Individual displayed text fields are bounded at 16,000 characters. Replay's
|
|
272
|
+
source references let you inspect the original. Terminal control sequences are
|
|
273
|
+
removed from rendered transcript content.
|
|
274
|
+
|
|
275
|
+
## Development
|
|
276
|
+
|
|
277
|
+
Python 3.9+, standard library only. The CLI remains in `transcripto.py`;
|
|
278
|
+
`transcripto_core.py` owns normalization and evidence; `transcripto_replay.py`
|
|
279
|
+
owns replay selection and presentation. All fixtures committed here are synthetic.
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
python3 -m unittest discover -s tests -v
|
|
283
|
+
for test in test_*.sh; do bash "$test" || exit; done
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
`test_distribution.sh` requires the development-only `build` package. It builds
|
|
287
|
+
an sdist, builds the wheel from that archive, installs without dependencies in a
|
|
288
|
+
fresh virtual environment, and exercises discovery, search and exact replay
|
|
289
|
+
across all three harnesses in an isolated synthetic HOME.
|
|
290
|
+
|
|
291
|
+
The regression cases include failed edits and commits, missing/mismatched
|
|
292
|
+
results, Cursor call shapes, Codex wrappers, result attribution across prompts,
|
|
293
|
+
rollback order, malformed JSON, a sparse 2 GiB file, terminal controls, private
|
|
294
|
+
index permissions, incremental search, and cross-harness retrieval.
|
|
295
|
+
|
|
296
|
+
MIT. Open an issue with the **record shape** that fails, or a synthetic
|
|
297
|
+
reproduction. Your real prompt text is not needed.
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "transcripto"
|
|
7
|
-
version = "0.1
|
|
8
|
-
description = "
|
|
7
|
+
version = "0.2.1"
|
|
8
|
+
description = "Instant replay for coding agents. Inspect requests, tool calls, and recorded results across Claude Code, Codex, and Cursor. Local, stdlib-only."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
license = { text = "MIT" }
|
|
@@ -28,4 +28,4 @@ Source = "https://github.com/Morkeeth/transcripto"
|
|
|
28
28
|
transcripto = "transcripto:main"
|
|
29
29
|
|
|
30
30
|
[tool.setuptools]
|
|
31
|
-
py-modules = ["transcripto"]
|
|
31
|
+
py-modules = ["transcripto", "transcripto_core", "transcripto_replay"]
|