A standalone Windows desktop app that keeps a verbatim, chronologically-ordered record of every prompt you type into Claude Code — without spending tokens or asking the assistant to maintain a log itself.
- Overview
- Features
- Getting started (download, build from source, updating)
- Usage
- Keyboard shortcuts
- AI_TRANSCRIPT.txt format
- Project structure
- Running the tests
- Known limitations
- Roadmap
- Contributing
- License
Keeping a record of the prompts you gave an AI assistant is genuinely useful — for reconstructing why a
design went the way it did, for writing up work afterwards, and for auditing what was actually asked. The
obvious approach, telling the assistant to append each prompt to a file via CLAUDE.md, costs tokens on
every single turn and degrades as the session grows.
This app moves that job out of the conversation entirely. You paste each prompt into it before sending
the prompt to Claude Code; it appends the text verbatim to AI_TRANSCRIPT.txt in the project root and
puts it straight back on your clipboard, so the extra step costs one keystroke. It runs fully offline,
talks to no network or service, and reads and writes nothing but local files. Composing there first also
means Enter just starts a new line instead of submitting anything — draft a longer prompt without the
usual worry, typing straight into a terminal, of firing it off half-finished.
Why not just use Claude Code's own session history? It exists, but it isn't a project record:
- It expires. Claude Code deletes session transcripts after 30 days by default (
cleanupPeriodDays). - It's fragmented. Each session is a separate JSONL file (a new one after every
/clear), stored on one machine, outside the project. - It's noisy. Your prompts are interleaved with tool calls, tool output and system messages.
This app keeps one continuous, plain-text record per project that lives with the code it explains and can
be committed alongside it — including which CLAUDE.md was in force at each point, and every model
switch and compaction, in order.
- Verbatim logging — every prompt stored exactly as written, under a numbered, dual-timestamped heading (UTC + your machine's own local time, auto-detected, DST-aware).
- Dark mode — a toggle in the top bar switches the whole app, including the window chrome, between light and dark. Defaults to light; your choice is remembered across launches.
- Window size remembered — resize the window however suits you; it reopens at that size next time, centered on screen. A fresh install launches wide enough for all four control groups to sit on one line, or as wide as your screen allows; narrower, the groups wrap onto a second row. The window can't be made so narrow that a top-bar button is cut off, and hovering the project path shows it in full when it's shortened.
- Clipboard hand-off — logging copies the text back, so the next action is a single paste into the terminal.
- Resume anywhere — the next entry number is re-derived from the file on disk, never from app state, so closing, reopening and switching projects are all safe.
- CLAUDE.md seeding — a project without a
CLAUDE.mdprompts you for one, copies it in byte-for-byte, and logs it as the first entry. - Session Exit markers — paste Claude Code's
claude --resume <id>line and it is recognised, normalised and logged without consuming a prompt number. - Model logging — pick or type a model and click Log to record it with one click; the app copies the exact
/model <value>command to switch, and logs the same way whether it's your first model for the session or a later switch. The combo box shows the model this project's transcript last recorded, so a glance next to/modelin Claude Code tells you whether the record is up to date; while it holds anything else (a pick you haven't logged, or for a project with no model logged yet, the last one logged anywhere) its text is italic, and its tooltip says what was last logged. Opening the list shows the same thing: the option last logged in this project carries a dimmed "last logged" label. If a model hasn't been logged yet for a fresh project you'll see a status nudge and a brief one-off highlight on its Log button before your first prompt — never a block, and both clear themselves for good the moment you log one or move past that first prompt. - Session commands —
/compactand/clearare exact, argument-free Claude Code commands, so picking one and clicking Log logs it with a single click and copies it to the clipboard, the same way Model logging does. The same combo box leaves room for Claude Code adding more commands worth a shortcut later, without needing more window space. - Prompt templates — save prompts you reuse and insert one into the compose box in a click, as a single undoable edit. Two come built in: CLAUDE.md Compliance checks the project against
CLAUDE.md's rules (a long session drifts from them as context is compacted or cleared), and Wrap-Up Check verifies the project by running it — clean build, tests, linter, dependency audit, stale artifacts, the README's own setup steps — at the end of a round of changes, release or not. Write<placeholders>in a template: after inserting, the first is selected to type over, andF3jumps to the next. Templates are plain.mdfiles you can also edit, back up or share outside the app. - CLAUDE.md change tracking — Log Edits re-logs
CLAUDE.mdafter you edit it (skipped if nothing changed), and Log New File… swaps in a differentCLAUDE.mdand logs it, logging any unlogged edits to the old one first so no version goes unrecorded. Whenever the window regains focus with unlogged edits on disk, the status line says so and Log Edits pulses briefly; nothing is ever logged without your click. - Editor keys — Tab/Shift+Tab indent and unindent (4 spaces, whole selections too), Enter keeps the indent, Alt+Up/Down moves lines and Ctrl+Shift+K deletes them, in the compose box and the template editor. See Keyboard shortcuts;
F1lists them in the app. - Global hotkey —
Ctrl+Shift+Alt+Space(changeable, or off) brings the app forward from anywhere with the compose box ready; after you log, focus goes straight back to the window you came from, ready to paste. - Keep on Top — pin the window above the terminal on a small screen.
- Drafts kept per project — close the app or switch projects with a prompt half-written and nothing is lost or asked: the draft is saved and comes back the next time you open that project. Logging it clears it.
- Windows named by project — the title starts with the project's folder name (
example-project - Claude Code Transcript Builder), so several open windows are told apart in the taskbar and Alt+Tab. - One window per project — a second window refuses a project already open in another, so two windows can never both log the same prompt number.
- Reveal in Explorer — opens a File Explorer window with
AI_TRANSCRIPT.txtpre-selected, once it exists, without depending on whatever (if anything) is set as your default.txthandler. - Safe with messy files — unrecognised existing content is preserved and separated; whitespace-only files are cleaned; prompt text that looks like a heading is never mistaken for one.
- Crash-safe writes — each entry is a single flushed append with no file handle held between actions.
Download ClaudeCodeTranscriptBuilder-win-x64.exe
from the latest release and
run it. It's a single self-contained file for Windows 10/11 x64 — no .NET install and no installer needed.
Each release also lists the exe's SHA-256 in SHA256SUMS.txt; to check a download against it, run
certutil -hashfile ClaudeCodeTranscriptBuilder-win-x64.exe SHA256 in the download folder.
The exe is not code-signed, so Windows SmartScreen may warn that it's from an unknown publisher the first time you run it. Click More info → Run anyway to start it. If you'd rather not run an unsigned binary, build it from source instead (Option 2).
Requires the free .NET 10 SDK (current LTS) on
Windows. The app and core library use only the .NET base class library and WPF; the sole NuGet
dependency is MSTest, in the test project. The .csproj files are the dependency manifests.
The build and release scripts in scripts/ (used below, and optional for just building and running)
need PowerShell. Use either:
- PowerShell 7 (
pwsh, install it): run a script aspwsh scripts/release.ps1, as shown in this README. - Windows PowerShell 5.1, built into Windows, with nothing to install: run a script as
powershell -ExecutionPolicy Bypass -File scripts\release.ps1. The-ExecutionPolicy Bypassis needed because Windows PowerShell blocks script files by default; it applies to that one run only.
git clone https://github.com/mkim87404/claude-code-transcript-builder.git
cd claude-code-transcript-builder
dotnet build TranscriptBuilder.slnx
dotnet run --project TranscriptBuilder
To produce the same single-file exe as the release, with its SHA-256 checksum (it builds and runs the
tests first, then writes publish/release/ClaudeCodeTranscriptBuilder-win-x64.exe and SHA256SUMS.txt):
pwsh scripts/release.ps1
or, in Windows PowerShell:
powershell -ExecutionPolicy Bypass -File scripts\release.ps1
- Downloaded app: download the latest release
and replace your old
ClaudeCodeTranscriptBuilder-win-x64.exewith it (close the app first). Your settings, templates and drafts live in%AppData%\TranscriptBuilder, not beside the exe, so they carry over. - From v1.0.0: read the v2.0.0 release notes
before the first launch. If you reworded the audit prompt, copy it out of
settings.jsonfirst: v2.0.0 replaces the audit prompt with templates and doesn't carry the wording over. - Built from source: from the repository folder,
git pull dotnet build TranscriptBuilder.slnx dotnet run --project TranscriptBuilder
No configuration or environment variables are needed. The last project you opened and the last
CLAUDE.md you picked, along with your last model, template, theme, global hotkey, Keep on Top and
window size, are remembered in settings.json under %AppData%\TranscriptBuilder. Templates are kept
alongside it, one .md file each, in %AppData%\TranscriptBuilder\templates, and each project's unsent
draft in %AppData%\TranscriptBuilder\drafts.
- Launch the app alongside VS Code. It reopens the last project you pointed it at, in whichever theme you last left it in (🌙 Dark Mode / ☀️ Light Mode, top right — light by default).
- Click Select Project Folder… and pick a project's root directory.
- If
CLAUDE.mdexists at that root andAI_TRANSCRIPT.txtdoesn't exist yet (or is empty), it is read and logged automatically as the first entry — no action needed. - If
CLAUDE.mdis missing from the root, a native file picker opens (preselecting the last CLAUDE.md you used). The chosen file is copied byte-for-byte into the root asCLAUDE.md, and logged as the first entry if the transcript still needs one. Cancelling falls back to pasting it as the first entry, which is then also written to the root asCLAUDE.md(never overwriting). For a project whose transcript already has entries, cancelling simply proceeds; nothing is created. - If
AI_TRANSCRIPT.txtalready has entries, the app resumes numbering at the correct nextPrompt #N.
- If
- Type or paste your next Claude Code prompt into the compose box.
- Click Log Entry (or
Ctrl+Enter). This appends a numbered, dual-timestamped entry toAI_TRANSCRIPT.txtand copies the exact text back to the clipboard. - Switch to the VS Code terminal and paste (
Ctrl+V) to continue with Claude Code. - When you exit Claude Code, copy its
claude --resume <session-id>line and paste it into the compose box. The app detects it (the "Next entry" label changes to Session Exit), and Log Entry appends aSession Exitentry and copies the command back to the clipboard so you can resume immediately. Only a paste that is entirely the resume line is treated this way; anything else is a normal prompt. - To log the model you're on — at session start or after switching — pick or type it in the Model
combo box (aliases like
opus,sonnet,haiku, or a full ID) and click its Log. This logs aModelentry immediately (no prompt number consumed) and copies the exact/model <value>command to the clipboard, ready to paste into the terminal. The box shows the model this project last logged (in italics while it holds anything else, such as a pick you haven't logged), so to cross-check, compare it with/modelin Claude Code, which is always the source of truth, and log or switch on either side if they differ. An unlogged pick is dropped the next time the project opens. Skipping this entirely is fine; if you haven't logged one yet before your first prompt, the status line says so, and the reminder goes away on its own once you either log one or move past that first prompt. - To log a
/compactor/clear, pick it in the Session combo box and click Log — this logs the entry immediately (no prompt number consumed) and copies the exact command to the clipboard, ready to paste into the terminal, the same way Model logging does. - To use a template, pick it in the Template combo box and click Insert. It goes into the compose
box — appended after a blank line if you already had a draft there — with its first
<placeholder>selected: type over it, pressF3for the next one, then log it like any other prompt.Ctrl+Zremoves the whole insert in one step. In the built-in CLAUDE.md Compliance, the placeholder is<the whole project>: leave it, or type the area to audit. Its report ends by suggesting a Wrap-Up Check once you've made the fixes; insert that template when you're ready. - Click Edit… beside it to manage templates: New and Duplicate create one straight away with its name selected for renaming, Delete moves it to the Recycle Bin, and Open Templates Folder shows the files. The built-in templates can be reworded (Restore Default Wording undoes that) but not renamed or deleted.
- After editing
CLAUDE.md, click Log Edits (CLAUDE.md group) to re-log its current content under its own heading; if nothing's changed since it was last logged, nothing is written. To switch to a differentCLAUDE.mdfile, click Log New File… and pick it: it replaces the project'sCLAUDE.mdand is logged, after any unlogged edits to the old one. Insert and both CLAUDE.md buttons are enabled once CLAUDE.md has been logged for the project. - Click Reveal in Explorer (top bar) at any point after the first entry is logged to jump straight
to
AI_TRANSCRIPT.txtin a File Explorer window, pre-selected.
Fewer Alt+Tabs. From the terminal (or anywhere), press Ctrl+Shift+Alt+Space: the app comes forward
with the compose box focused. Log from there and focus returns to the window you came from, so the next
step is Ctrl+V. The return happens once, only after a log that put text on the clipboard, and only if
you arrived by the hotkey; switching away yourself cancels it, and if that window has since closed or
been minimized, focus simply stays in the app. Change or turn off the hotkey in ⌨ Shortcuts (F1).
📌 Keep on Top pins the window above others instead.
Closing and reopening the app, or pointing it at a different project, is always safe — the next-entry
state is re-derived from AI_TRANSCRIPT.txt on disk, never from in-memory app state.
Note
Publishing a project publicly? AI_TRANSCRIPT.txt contains your full prompt history. Add it to that
project's .gitignore if you don't want your prompts published along with the code.
In the compose box and the template editor:
| Keys | Action |
|---|---|
Ctrl+Enter |
Log the compose box |
Tab / Shift+Tab |
Indent / unindent the line, or every selected line (4 spaces) |
Backspace in an indent |
Delete back to the previous indent stop (at most 4 spaces); Delete still removes single spaces |
Enter |
New line, keeping the current indent |
Alt+Up / Alt+Down |
Move the line, or the selected lines, up / down |
Ctrl+Shift+K |
Delete the line, or the selected lines |
F3 / Shift+F3 |
Select the next / previous <placeholder> |
Up on the first line / Down on the last |
Jump to the start / end of the text |
Ctrl+Tab / Ctrl+Shift+Tab |
Move keyboard focus out of the text box |
Standard Windows text keys work as usual (Ctrl+A, Ctrl+C/X/V, Ctrl+Z/Y, Shift+arrows, …);
each edit made by a key above, and each template insert, is undone by a single Ctrl+Z. The table lists only keys the app adds or
changes. Because Tab indents, it no longer moves focus out of the text box; use Ctrl+Tab for that.
Anywhere in the app, F1 opens the shortcuts window. From any app, Ctrl+Shift+Alt+Space (the global
hotkey, changeable there) brings this window forward.
================================================================================
CLAUDE.md (or "Prompt #<N>")
UTC: 2026-09-19T14:35:42Z
Local: 2026-09-20 02:35:42 +13:00 (your machine's own zone and offset, auto-detected)
================================================================================
<verbatim entry text>
Session exits use the heading Session Exit (no number, so prompt numbering is unaffected) and a
normalized body: claude --resume <session-id>. Model, Compact, Clear, and CLAUDE.md Update
entries follow the same non-numbered pattern — a Model body is the exact /model <value> command, a
Compact/Clear body is the exact /compact//clear command, and a CLAUDE.md Update body is the
file's full current content, same as the original CLAUDE.md entry.
TranscriptBuilder.slnx Solution (app, core library, tests)
TranscriptBuilder/ WPF app (net10.0-windows): UI only
App.xaml(.cs) Application entry point: applies the saved theme, global crash/exception logging
MainWindow.xaml(.cs) Main window: project picker, compose box, logging, status
TemplatesWindow.xaml(.cs) Template editor: list, rename, new/duplicate/delete, restore default
ShortcutsWindow.xaml(.cs) Keyboard shortcut list (F1) and global hotkey settings
EditorKeys.cs Maps editing keys to Core's TextEditing and applies each edit as one undo step
GlobalHotkey.cs Registers the system-wide hotkey on the main window's message loop
FocusReturn.cs One-time focus return to the window the hotkey was pressed in
RecycleBin.cs Deletes a file to the Recycle Bin
TitleBarTheme.cs Matches each window's native title bar to the light/dark theme
NativeBackground.cs Paints a window's native background in the theme until its first frame, so it never flashes white
Assets/app.ico App/window icon (multi-resolution, 16-256px)
TranscriptBuilder.Core/ UI-free logic (net10.0), referenced by the app and the tests
Models/
SessionState.cs Next entry kind/number, entry count + state transitions
EntryHeadings.cs Single source of truth for entry heading text
AppSettings.cs Everything remembered between launches (project, CLAUDE.md source, model, theme, …)
AppThemePreference.cs Light/Dark, independent of WPF's own System.Windows.ThemeMode
PromptTemplate.cs A named template, and the built-in templates' wording
HotkeyCombination.cs The global hotkey's keys: parse, display, and reject unsafe combinations
Services/
TranscriptService.cs Inspect/resume from AI_TRANSCRIPT.txt, append entries, detect CLAUDE.md changes
ClaudeMdService.cs Read, copy into, create and atomically replace the project's root CLAUDE.md
TemplateStore.cs Template files: load, save/rename atomically, unique names, name validation
DraftStore.cs Each project's unsent compose-box text, saved and restored per project
AtomicFile.cs Write-to-temp-then-replace, shared by settings, templates, drafts and CLAUDE.md replacement
SmallFile.cs Size-capped, failure-tolerant read of the app's own drafts and templates
ProjectKey.cs A stable hash of a project path, naming its lock and its draft file
WindowTitle.cs The window title: the project's folder name, then the app name
ModelCommand.cs The "/model <value>" entry body: written, and read back from the transcript
ModelBox.cs The Model box's pre-fill, and whether it shows what the transcript last recorded
TextEditing.cs The editing keys and template insert as pure text-in, edit-out functions
ProjectLock.cs Per-project named mutex, so only one window has a project open
EntryClassifier.cs Decide whether a paste logs as Prompt, CLAUDE.md, or Session Exit
SessionMarker.cs Strict detection/normalization of a pasted `claude --resume <id>` line
TimestampService.cs UTC + auto-detected local (DST-aware) timestamp pair for each entry
ThemePreferenceService.cs Parses the persisted light/dark preference, and computes a toggle
WindowSizing.cs Launch size from the remembered size, the default, and the screen
SettingsService.cs Best-effort load, atomic save of settings.json under %AppData%\TranscriptBuilder
TranscriptBuilder.Tests/ MSTest: unit tests for pure helpers + real-filesystem integration tests
scripts/
build.ps1 Release build + full test suite (what CI runs)
release.ps1 Single-file release exe under its asset name, plus SHA256SUMS.txt
.github/workflows/ci.yml CI: scripts/build.ps1 on every push/PR to main (windows-latest)
tools/ Standalone helper programs and the UI checks (see tools/README.md)
docs/DECISIONS.md Decision log: why things are the way they are, newest first
.github/screenshot-*.png Light and dark screenshots embedded in this README
LICENSE MIT
dotnet test TranscriptBuilder.Tests
or, exactly as CI runs it (Release build, then the tests; -Clean clears earlier build outputs first):
pwsh scripts/build.ps1
(or powershell -ExecutionPolicy Bypass -File scripts\build.ps1 in Windows PowerShell; see
Build from source).
Unit tests cover the pure helpers (including the exact daylight-saving boundary, against a fixed zone so the test is deterministic on any machine); integration tests exercise the real filesystem in temporary folders — first launch, CLAUDE.md copy, paste-create and replace, resume-from-disk matching in-memory state, messy and hostile transcript content, template files, the project lock across threads, and handle release. Every editing key is tested as a pure function. Tests never build or lock the WPF exe, so they can run while the app is open.
UI checks (disruptive, run separately). The window itself is checked end to end by the PowerShell
scripts in tools/ui-checks/ (and tools/undo-spike/app-keys-check.ps1): drafts, the global hotkey and
focus return, hotkey settings, window titles, the Model box, and real mouse clicks in every drop-down. They
launch the built app, take focus, and type or click, so leave the keyboard and mouse alone while one runs.
Each says what it does in its header, and tools/README.md lists them all. Run them against a demo project
through tools/ui-checks/with-demo-settings.ps1, which backs up and restores your real settings. They aren't
part of dotnet test or CI yet.
- Windows only. WPF; there is no macOS or Linux build.
- Dark mode's native title bar needs Windows 11 (Build 22000+). The rest of dark mode works on older Windows 10 builds too; only the title bar itself stays the default color there.
- A
/clearmid-session hides a session ID — it never appears in an exit line, so it can't be captured as a Session Exit marker. - The window's end-to-end checks don't run in CI. The UI layer is deliberately thin and its logic is unit-tested in Core; the window itself is checked by the scripts in
tools/ui-checks/, which drive the real app with keystrokes and clicks and are run locally (see Running the tests). - The global hotkey belongs to the first window that registers it. A second app window (on another project) says the combination is taken; it can use a different one. The same goes for any other app already using the combination.
- Long lines don't keep their indent when they wrap. WPF's text box can't do a hanging indent; the indent itself is stored and logged correctly.
- Logged resume commands expire. Claude Code keeps session transcripts for 30 days by default, so older markers may no longer resolve.
- Running the UI checks in CI alongside the unit tests.
- Optional exclusion of
AI_TRANSCRIPT.txtfrom version control, for projects published publicly. - Code-signing the release exe, so SmartScreen stops warning on first run.
- No
/rewindshortcut, deliberately: unlike/compactand/clear, it opens an interactive checkpoint picker rather than completing as one fixed command, so it doesn't fit the one-click "log and copy the exact command" pattern Session commands uses without its own separate design.
Issues and pull requests are welcome. Before opening a PR, make sure pwsh scripts/build.ps1 (the same
build and tests CI runs; the Windows PowerShell form is under Build from source) finishes with no warnings and every test passes, and add tests alongside any
new logic — the pure parts belong in TranscriptBuilder.Core, where they can be tested without the UI.
docs/DECISIONS.md records why things are the way they are; it's worth a skim before changing established behavior.
See docs/DECISIONS.md for the architectural decisions and trade-offs behind this design.

