Wrapping Claude Code and Codex in Electron: A Stop Bug A solo developer building Refmade, an Electron desktop wrapper that drives the user's own installed Claude Code and Codex binaries via stream-json and JSON-RPC over stdio, found during end-to-end testing that pressing Stop did not terminate background processes spawned by an agent — a detached `rm keep.txt` scheduled with nohup still executed 35 seconds after the task was stopped, deleting a file in a test folder. The app routes permission prompts through `--permission-prompt-tool stdio` for Claude Code and `codex app-server` approval requests for Codex, translating them into plain-language cards, and returns a JSON-RPC -32601 error for any request it does not recognize rather than guessing. I pressed Stop on a task. When I looked 35 seconds later, a file in my test folder was gone. The file was keep.txt , the folder was throwaway, and I had told the agent to set the trap itself: nohup sh -c 'sleep 20; rm keep.txt' /dev/null 2 &1 & . Stop was supposed to end everything the task had started. It ended Claude Code, and the rm ran anyway. Of the bugs my end-to-end runs found in the wrapper app, this is the one that deleted a file. This is part 9 of a series about Refmade, a desktop app I'm building alone. Refmade lets people who don't live in a terminal hand work to the Claude Code or Codex they have already installed, and shows the agents as an office you can watch. It is an independent app, not affiliated with Anthropic or OpenAI. Claude Code and Codex agents wrote most of the code at my direction; I planned, decided and reviewed. The UI is Korean right now; that changes later in this series. This part covers the evening of September 27 through September 29, when the app went from a web dashboard to an Electron shell around two command-line tools. A wrapper that calls the model API itself needs a key, and then it is a different product with a different bill. Refmade starts the claude or codex binary you installed, in the folder you picked, under your login. The header of the Codex runner in the current source says it plainly: the user's own binary and config are used as-is, and the app never reads auth or tokens. Both tools turned out to have a machine-readable mode with a channel for permission questions. That channel is the whole trick. The runner starts one long-lived claude -p per task. Everything on stdin and stdout is one JSON object per line. claude -p --input-format stream-json --output-format stream-json \ --verbose --include-partial-messages --replay-user-messages \ --permission-prompt-tool stdio stdin, first line: {"type":"control request","request id":"init 1","request":{"subtype":"initialize","hooks":null}} answers to the CLI's questions reuse the question's id: {"type":"control response","response":{"subtype":"success","request id":"