Conversation
The embedded Claude session was POSIX-only: the command was looked up with /bin/sh, spawned through a /bin/bash watchdog and killed by process group. On Windows the panel failed at once with "File not found". - which(): `where` instead of `command -v`, keeping the first hit with a runnable extension - npm installs an extensionless sh shim next to claude.cmd, and CreateProcess cannot run it - spawn claude directly in the pty (no bash, no process groups); a hard Electron death closes the pseudoconsole, which ends what is attached - close kills the whole tree (shim -> claude -> MCP servers) with taskkill /t - Ctrl+V pastes instead of sending ^V, right-click copies a selection or pastes (Electron has no context menu), as in Windows Terminal Verified on Windows 10 with Electron 42: the panel opens the claude TUI, arguments incl. the quoted system hint arrive intact through claude.cmd, the kadr MCP bridge answers kadr_state, no process survives a close or a hard kill, and Ctrl+V / right-click deliver the clipboard as bracketed paste. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The embedded assistant forgot everything between panel sessions: every open
started a blank claude, and its transcripts lived only in Claude Code's own
folder for whatever cwd the panel happened to run in. The AI editor had no
memory of the edits it had made to the project.
Now a project owns its chats:
R-1 Project.claudeChats holds the Claude Code session ids; sanitizeProject
cleans it, undo/redo carry the current list over (a chat is not an edit)
R-2 both writers (save and autosave) embed the transcripts into the file
as claudeTranscripts: { id: jsonl }; ids with nothing to resume are
dropped
R-3 project:read takes them out again and keeps them in main - they never
reach the renderer, whose project is deep-copied on every edit
R-4 the panel resumes the newest chat (claude --resume), first writing the
longest known copy to <config>/projects/<slug of cwd>/<id>.jsonl, where
resume looks - so a chat begun in an unsaved project, in another
folder or on another machine resumes; with no chats a new one starts
with a known id (--session-id). A chat joins the project on the user's
first key or paste, as a new project object, so the unsaved dot and
autosave see that the file's transcript is behind - and a panel opened
and closed again leaves no empty chat behind
R-5 the panel header gets a chat picker (title + date) and a New chat
button; the usage hint moves into the header's tooltip. The panel is
keyed by project id: opening another project brings up ITS chats.
On Windows a close now waits for taskkill, so a quick A->B->A switch
never has two claudes writing one transcript
R-6 electron/chats.ts, checked by scripts/check-chats.mjs (no app, no
network, a temp CLAUDE_CONFIG_DIR)
R-8 CLAUDE.md documents it, together with the Windows notes of the
previous commit
Not tracked, by design and documented: a session switched inside the TUI
(/clear, /resume) gets an id the panel never sees - New chat is the way.
An args override in claude-env.json gets no chat flags: it may run
something that is not claude.
Checks: node scripts/check-chats.mjs -> all passed (16); the other four
check-*.mjs pass; tsc on both configs clean. Live walk over CDP on Windows
with a crafted transcript (no tokens spent), 14/14: save embeds it, open
keeps it out of the renderer, the panel lists and resumes it after Claude's
own copy was deleted, the first key marks the project unsaved, New chat
starts --session-id and is recorded only after input, a quick A->B->A
switch leaves one claude, undo keeps the list, another project restarts
the panel on its own chats, nothing survives a close; autosave embeds too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two commits, reviewable separately.
1. Claude panel: run on Windows, paste into the terminal
The embedded session was POSIX-only (
/bin/sh -c command -v, a/bin/bashwatchdog,kill(-pgid)), so on Windows the panel failed at once withFile not found.where, taking the first hit with a runnable extension — npm puts an extensionless sh shim next toclaude.cmd, and CreateProcess cannot run ittaskkill /t /f^V, and right-click copies a selection or pastes (Electron has no context menu), as in Windows Terminal2. Per-project chat history, saved inside the
.kadrUntil now every panel open started a blank claude, so the assistant had no memory of the edits it had made. Now a project owns its chats:
Project.claudeChatsholds the session ids. The panel resumes the newest one (--resume), or starts a new one with a known id (--session-id).claudeTranscripts: {id: jsonl}.project:readtakes them out again and keeps them in main, so they never reach the renderer, whose project is deep-copied on every edit.<config>/projects/<slug of cwd>/<id>.jsonl, so right before a resume the longest known copy is written there. A chat begun in an unsaved project, in another folder or on another machine therefore still resumes.taskkill, so a quick A→B→A switch never has two claudes writing one transcript.Heads-up — privacy: a
.kadrnow carries its chat transcripts, so sharing the project file shares the conversations too.Not tracked (documented in CLAUDE.md): a session switched inside the TUI (
/clear,/resume) gets an id the panel never sees, so New chat is the supported way to start a new conversation. With an args override inclaude-env.jsonno chat flags are added, because the override may run something that is not claude.Checks
node scripts/check-chats.mjs(new; no app, no network, uses a tempCLAUDE_CONFIG_DIR) → 16/16 passcheck-*.mjspass;tscis clean on both configsFile not found; after it, the TUI opens and the kadr MCP bridge answerskadr_state. Ctrl+V and right-click deliver the clipboard as a bracketed paste, where before they sent^Vand nothing.Not run: the
e2e*.mjssuites. They are Linux-oriented (/tmp,$HOME/.config/kadr,gen-test-media.sh) and were not run here.🤖 Generated with Claude Code