Skip to content

About

Windows desktop app that keeps a verbatim, timestamped log of every prompt you give Claude Code, with no token cost.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

📝 Claude Code Transcript Builder

CI Release .NET Platform Dependencies Offline License

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.

The app in light mode: the project path and top-bar buttons (Shortcuts, Keep on Top, theme, Reveal in Explorer, Select Project Folder), the status line, the Model, Session, Template and CLAUDE.md groups, and a sample prompt in the compose box The same window in dark mode, including a dark title bar

Contents

🔍 Overview

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.

✨ Features

  • 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.md prompts 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 /model in 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 — /compact and /clear are 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, and F3 jumps to the next. Templates are plain .md files you can also edit, back up or share outside the app.
  • CLAUDE.md change tracking — Log Edits re-logs CLAUDE.md after you edit it (skipped if nothing changed), and Log New File… swaps in a different CLAUDE.md and 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; F1 lists 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.txt pre-selected, once it exists, without depending on whatever (if anything) is set as your default .txt handler.
  • 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.

🚀 Getting started

Option 1: Download the app

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).

Option 2: Build from source

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 as pwsh 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 Bypass is 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

Updating

  • Downloaded app: download the latest release and replace your old ClaudeCodeTranscriptBuilder-win-x64.exe with 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.json first: 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.

📖 Usage

  1. 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).
  2. Click Select Project Folder… and pick a project's root directory.
    • If CLAUDE.md exists at that root and AI_TRANSCRIPT.txt doesn't exist yet (or is empty), it is read and logged automatically as the first entry — no action needed.
    • If CLAUDE.md is 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 as CLAUDE.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 as CLAUDE.md (never overwriting). For a project whose transcript already has entries, cancelling simply proceeds; nothing is created.
    • If AI_TRANSCRIPT.txt already has entries, the app resumes numbering at the correct next Prompt #N.
  3. Type or paste your next Claude Code prompt into the compose box.
  4. Click Log Entry (or Ctrl+Enter). This appends a numbered, dual-timestamped entry to AI_TRANSCRIPT.txt and copies the exact text back to the clipboard.
  5. Switch to the VS Code terminal and paste (Ctrl+V) to continue with Claude Code.
  6. 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 a Session Exit entry 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.
  7. 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 a Model entry 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 /model in 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.
  8. To log a /compact or /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.
  9. 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, press F3 for the next one, then log it like any other prompt. Ctrl+Z removes 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.
  10. 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.
  11. 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 different CLAUDE.md file, click Log New File… and pick it: it replaces the project's CLAUDE.md and 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.
  12. Click Reveal in Explorer (top bar) at any point after the first entry is logged to jump straight to AI_TRANSCRIPT.txt in 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.

⌨️ Keyboard shortcuts

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.

🧾 AI_TRANSCRIPT.txt format

================================================================================
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.

🗂 Project structure

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

✅ Running the tests

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.

⚠️ Known limitations

  • 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 /clear mid-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.

🛣 Roadmap

  • Running the UI checks in CI alongside the unit tests.
  • Optional exclusion of AI_TRANSCRIPT.txt from version control, for projects published publicly.
  • Code-signing the release exe, so SmartScreen stops warning on first run.
  • No /rewind shortcut, deliberately: unlike /compact and /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.

🤝 Contributing

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.

⚖️ License

MIT


See docs/DECISIONS.md for the architectural decisions and trade-offs behind this design.

About

Windows desktop app that keeps a verbatim, timestamped log of every prompt you give Claude Code, with no token cost.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages