<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eren Çolak</title>
    <description>The latest articles on DEV Community by Eren Çolak (@erenxcolakx).</description>
    <link>https://dev.to/erenxcolakx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3571094%2F70cb1d18-a12a-4c44-b993-2184ae28fe3a.jpeg</url>
      <title>DEV Community: Eren Çolak</title>
      <link>https://dev.to/erenxcolakx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erenxcolakx"/>
    <language>en</language>
    <item>
      <title>How to get notified when Claude Code finishes or needs permission</title>
      <dc:creator>Eren Çolak</dc:creator>
      <pubDate>Wed, 11 Nov 2026 10:49:45 +0000</pubDate>
      <link>https://dev.to/erenxcolakx/how-to-get-notified-when-claude-code-finishes-or-needs-permission-3e0k</link>
      <guid>https://dev.to/erenxcolakx/how-to-get-notified-when-claude-code-finishes-or-needs-permission-3e0k</guid>
      <description>&lt;p&gt;If you run Claude Code in the VS Code or Cursor terminal, you get no alert when it finishes or stops for a permission prompt. Claude Code sends a desktop notification on its own only in a few terminals (Ghostty, Kitty, iTerm2). In the VS Code terminal, Warp and most others it sends nothing by default.&lt;/p&gt;

&lt;p&gt;So you keep checking the tab, or you switch away and come back twenty minutes later to a session that has been waiting for a "yes" the whole time.&lt;/p&gt;

&lt;p&gt;Here are three fixes, from a one-line setting to a hook that tells you which session it is. Checked against Claude Code 2.1.x on macOS, Linux and Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. One line: the terminal bell
&lt;/h2&gt;

&lt;p&gt;Tell Claude Code to ring the terminal bell whatever terminal you use. In &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"preferredNotifChannel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"terminal_bell"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In VS Code and Cursor, the bell is silent until you turn on its sound. Open Settings, search for &lt;strong&gt;Terminal Bell&lt;/strong&gt; (under Accessibility Signals) and set the sound to &lt;strong&gt;on&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Good: zero scripts. Not so good: it's a short beep, you have to be in earshot, and it doesn't say which session rang.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A hook that pops a desktop notification
&lt;/h2&gt;

&lt;p&gt;Hooks are commands Claude Code runs at points in its lifecycle. Two events matter here:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;When it fires&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Right when Claude finishes its turn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Notification&lt;/code&gt; with &lt;code&gt;permission_prompt&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Claude needs you to approve something and the prompt has waited about six seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Notification&lt;/code&gt; with &lt;code&gt;idle_prompt&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;About 60 seconds after a finished turn, if you haven't typed since&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Stop&lt;/code&gt; is the one you want for "it's done". &lt;code&gt;idle_prompt&lt;/code&gt; repeats the same news a minute later, so if you hook both you get two alerts for one finished turn.&lt;/p&gt;

&lt;p&gt;Add this to &lt;code&gt;~/.claude/settings.json&lt;/code&gt; (macOS shown; other systems below):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;"Stop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"osascript -e 'display notification \"Your turn\" with title \"Claude Code\"'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;"async"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"Notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"permission_prompt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"osascript -e 'display notification \"Needs permission\" with title \"Claude Code\"'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;"async"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;"async": true&lt;/code&gt; matters more than it looks. Hooks are synchronous by default: Claude waits for each one. A notification command that takes a second or three (PowerShell's startup alone is about that on Windows) slows every turn down. With &lt;code&gt;async&lt;/code&gt;, it runs in the background.&lt;/p&gt;

&lt;p&gt;The command for other systems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt; (needs a notification daemon, so not over plain SSH):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;notify-send &lt;span class="s1"&gt;'Claude Code'&lt;/span&gt; &lt;span class="s1"&gt;'Your turn'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt; (plays the system chime; a message box would block until you click it):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;powershell.exe -NoProfile -Command &lt;span class="s2"&gt;"(New-Object Media.SoundPlayer 'C:/Windows/Media/chimes.wav').PlaySync()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The forward slashes are on purpose: they work in Windows paths and need no escaping inside JSON. Inside &lt;code&gt;settings.json&lt;/code&gt;, escape the double quotes as &lt;code&gt;\"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sound only, macOS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;afplay /System/Library/Sounds/Glass.aiff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If nothing shows on macOS, &lt;code&gt;osascript&lt;/code&gt; notifications go through Script Editor. Run &lt;code&gt;osascript -e 'display notification "test"'&lt;/code&gt; once in Terminal so Script Editor appears in System Settings &amp;gt; Notifications, then allow it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Say which session it is
&lt;/h2&gt;

&lt;p&gt;With one session, "Your turn" is enough. With three or four, you need to know which one. Every hook gets a JSON object on stdin, and it includes &lt;code&gt;cwd&lt;/code&gt;, the folder the session runs in. Put that in the notification (macOS, needs &lt;code&gt;jq&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"osascript -e \"display notification \\\"$(jq -r '.cwd' | xargs basename)\\\" with title \\\"Claude Code: your turn\\\"\""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"async"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the notification says &lt;code&gt;api&lt;/code&gt; or &lt;code&gt;web&lt;/code&gt; instead of just "Claude Code". On Linux, the same idea is &lt;code&gt;notify-send "Claude Code: your turn" "$(jq -r '.cwd' | xargs basename)"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things that tripped me up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hooks add up, they don't replace.&lt;/strong&gt; Your user, project and local settings all contribute hooks, and they all run, in parallel. If a project's &lt;code&gt;.claude/settings.json&lt;/code&gt; already has a &lt;code&gt;Stop&lt;/code&gt; hook, yours runs next to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The permission alert is delayed on purpose.&lt;/strong&gt; &lt;code&gt;permission_prompt&lt;/code&gt; waits about six seconds, so a prompt you answer right away never pings you. Don't "fix" it by hooking &lt;code&gt;PermissionRequest&lt;/code&gt; instead unless you want an alert for every single approval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Being in the window doesn't mean you're looking.&lt;/strong&gt; The hook can't tell whether you're watching that terminal. If the alerts get annoying while you're at your desk, keep only the permission one and drop &lt;code&gt;Stop&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some terminals show status by themselves.&lt;/strong&gt; Terminals that support the OSC 7501 status protocol show whether each session is working or waiting, with no setup, from Claude Code 2.1.295 on. Check your terminal's docs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When there are more than a few sessions
&lt;/h2&gt;

&lt;p&gt;Past three or four sessions, notifications help but you still have to find the right tab. That's the problem I built &lt;a href="https://marketplace.visualstudio.com/items?itemName=paneherd.paneherd" rel="noopener noreferrer"&gt;Paneherd&lt;/a&gt; for: a VS Code / Cursor extension that opens each session as a terminal in a grid and labels every pane Working, Needs permission or Your turn, using the same hooks as above. Notifications and sounds are in the free version. There are other extensions for this in the Marketplace too, and for a single session the setting in step 1 is all you need.&lt;/p&gt;

&lt;p&gt;What do you use: the bell, a hook, or something else?&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>11 things I learned building a tool on Claude Code hooks</title>
      <dc:creator>Eren Çolak</dc:creator>
      <pubDate>Wed, 11 Nov 2026 08:19:19 +0000</pubDate>
      <link>https://dev.to/erenxcolakx/11-things-i-learned-building-a-tool-on-claude-code-hooks-ojc</link>
      <guid>https://dev.to/erenxcolakx/11-things-i-learned-building-a-tool-on-claude-code-hooks-ojc</guid>
      <description>&lt;p&gt;I usually have four or five Claude Code sessions open at once, and my problem was never the agents. It was me: a session would sit on a permission prompt for twenty minutes in a tab I wasn't looking at, or two sessions would edit the same file and one would quietly undo the other.&lt;/p&gt;

&lt;p&gt;So I built a VS Code / Cursor extension that runs each session as a terminal in a grid and shows, at all times, whether it is working, waiting for a permission or waiting for me. Early on I tried reading the terminal output to guess the state. It was fragile, so everything below comes from Claude Code's hooks instead.&lt;/p&gt;

&lt;p&gt;These are the notes I wish I'd had at the start. They were checked against Claude Code 2.1.x; hook behavior changes between versions, so test against yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Give each session its own hooks with &lt;code&gt;--settings&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You don't have to touch &lt;code&gt;~/.claude/settings.json&lt;/code&gt;. Start a session with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude --settings /path/to/session-1.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hooks from &lt;code&gt;--settings&lt;/code&gt; are &lt;strong&gt;added&lt;/strong&gt; to the user's and the project's hooks, not swapped in for them. So each session can report to your tool, and whatever hooks the user already has keep working.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Use command hooks that run curl, with an args array
&lt;/h2&gt;

&lt;p&gt;Each hook in my settings file is a command hook that POSTs the hook's JSON input (which arrives on stdin) to a local server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;"Stop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/usr/bin/curl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"--silent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"--output"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/dev/null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"--connect-timeout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"--max-time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"--request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"--header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"X-My-Token: &amp;lt;per-window token&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"--header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"--data-binary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"@-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"http://127.0.0.1:7777/hook/session-1/Stop"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing &lt;code&gt;args&lt;/code&gt; as an array means no shell is involved, so the same file works under Git Bash, PowerShell and sh. That saved me a whole class of Windows quoting bugs. I also tried &lt;code&gt;type: "http"&lt;/code&gt; hooks; in my testing they did not fire for &lt;code&gt;SessionStart&lt;/code&gt;, so I stayed with command hooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Put the routing in the URL, not the body
&lt;/h2&gt;

&lt;p&gt;The URL says which session and which event: &lt;code&gt;/hook/&amp;lt;session&amp;gt;/&amp;lt;event&amp;gt;&lt;/code&gt;. The server never has to parse the body to know who is talking. It only listens on 127.0.0.1 and rejects requests without the per-window token.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Be careful what reaches stdout
&lt;/h2&gt;

&lt;p&gt;For some events, &lt;code&gt;SessionStart&lt;/code&gt; and &lt;code&gt;UserPromptSubmit&lt;/code&gt; among them, &lt;strong&gt;the hook's stdout becomes part of Claude's context.&lt;/strong&gt; Picture this: the editor is closed, something else now owns your port, and its error page gets injected into the prompt.&lt;/p&gt;

&lt;p&gt;So hooks that don't make decisions send curl's output to &lt;code&gt;/dev/null&lt;/code&gt; (&lt;code&gt;NUL&lt;/code&gt; on Windows). Hooks that do make decisions (&lt;code&gt;PreToolUse&lt;/code&gt;, &lt;code&gt;PermissionRequest&lt;/code&gt;) use &lt;code&gt;--fail&lt;/code&gt;, so an error page never reaches Claude. The server answers everything else with an empty 204 right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Hooks are synchronous, and that is useful
&lt;/h2&gt;

&lt;p&gt;Claude waits for each hook, so events reach your server in the order Claude emits them, and you never have to reorder. The cost is that slow hooks slow Claude down. Keep the connect timeout at a second and the total time at a few seconds for everything except permission decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Waiting on PermissionRequest blocks nothing
&lt;/h2&gt;

&lt;p&gt;This one surprised me. While a &lt;code&gt;PermissionRequest&lt;/code&gt; hook is waiting, Claude is already showing its own permission dialog in the terminal. So the hook can wait a long time (mine waits up to an hour) for an answer from somewhere else, such as a sidebar inbox or a phone, and the user can still answer in the terminal. Whichever answer comes first wins.&lt;/p&gt;

&lt;p&gt;One catch: when the prompt is answered outside the terminal, no hook event arrives until the tool finishes. Mark the session as working yourself, or it looks stuck on "needs permission".&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Map events to states, and read the Notification type
&lt;/h2&gt;

&lt;p&gt;This is the mapping that ended up working:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;UserPromptSubmit&lt;/code&gt;, &lt;code&gt;PreToolUse&lt;/code&gt;, &lt;code&gt;PostToolUse&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;working&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;PermissionRequest&lt;/code&gt;, or &lt;code&gt;Notification&lt;/code&gt; with &lt;code&gt;permission_prompt&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;needs permission&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Notification&lt;/code&gt; with &lt;code&gt;elicitation_dialog&lt;/code&gt; / &lt;code&gt;agent_needs_input&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;asking a question&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;your turn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;SessionEnd&lt;/code&gt; (except reason &lt;code&gt;clear&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;exited&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;idle_prompt&lt;/code&gt; deserves a note: it arrives about 60 seconds after a finished turn. Use it only as a fallback when you missed the &lt;code&gt;Stop&lt;/code&gt;. Otherwise you alert the user a second time about something they already saw.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. SessionStart fires before the prompt is ready
&lt;/h2&gt;

&lt;p&gt;If your tool types a first prompt into a new session right after &lt;code&gt;SessionStart&lt;/code&gt;, the Enter can get swallowed and the text just sits in the input box. No hook tells you "the prompt is ready now."&lt;/p&gt;

&lt;p&gt;What works for me is to wait about two seconds after &lt;code&gt;SessionStart&lt;/code&gt;. If no &lt;code&gt;UserPromptSubmit&lt;/code&gt; follows within a couple of seconds, press Enter again, up to four times. Enter on an empty prompt does nothing, so retrying is safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Your usage limits only reach the status line
&lt;/h2&gt;

&lt;p&gt;Claude Code passes &lt;code&gt;rate_limits&lt;/code&gt; (&lt;code&gt;five_hour&lt;/code&gt; and &lt;code&gt;seven_day&lt;/code&gt;, each with &lt;code&gt;used_percentage&lt;/code&gt; and &lt;code&gt;resets_at&lt;/code&gt;) to your &lt;strong&gt;status line command&lt;/strong&gt; on stdin. As far as I can tell, that is the only place they are available locally. Post the status line input to your server the same way as the hooks, and you have live limit data with no API calls.&lt;/p&gt;

&lt;p&gt;Two more things about the status line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is the only place inside the terminal you can draw. Use plain ANSI colors so the user's theme decides how they look, light or dark.&lt;/li&gt;
&lt;li&gt;Unlike exec-form hooks, the status line command runs through a shell (Git Bash, cmd or PowerShell on Windows), so quote it to mean the same in all of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. Sessions outlive your tool
&lt;/h2&gt;

&lt;p&gt;After a window reload or an extension update, the Claude processes are still running and still posting to the old address. So my server comes back on the same port with the same token, and per-session settings files are deleted only once the process is gone, not when the extension stops.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. A file-conflict guard from PostToolUse + PreToolUse
&lt;/h2&gt;

&lt;p&gt;To stop two sessions from silently overwriting each other:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On &lt;code&gt;PostToolUse&lt;/code&gt; of &lt;code&gt;Edit&lt;/code&gt;, &lt;code&gt;MultiEdit&lt;/code&gt; and &lt;code&gt;Write&lt;/code&gt;, record which session wrote which file. Using the post event means only edits that actually ran are counted.&lt;/li&gt;
&lt;li&gt;On &lt;code&gt;PreToolUse&lt;/code&gt; of a write, check whether another live session wrote the same file in the last ten minutes, after this session's own last write. If so, return &lt;code&gt;{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "ask", "permissionDecisionReason": "..."}}&lt;/code&gt;, and Claude asks the user before writing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest limitation: files changed through Bash are invisible to this. Git worktrees per session solve most of the problem anyway. The guard is for what's left.&lt;/p&gt;




&lt;p&gt;All of this ships in &lt;a href="https://paneherd.com" rel="noopener noreferrer"&gt;Paneherd&lt;/a&gt;, the extension I built along the way. It's free for unlimited sessions, notifications and usage limits, and a one-time $2.99 Pro adds a shared permission inbox, the file-conflict guard and approving from your phone. It runs locally, with no telemetry.&lt;/p&gt;

&lt;p&gt;If you're building on Claude Code hooks too, I'd like to hear what tripped you up. What did you have to learn the hard way?&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>vscode</category>
      <category>devtools</category>
    </item>
    <item>
      <title>How to run multiple Claude Code sessions at once</title>
      <dc:creator>Eren Çolak</dc:creator>
      <pubDate>Wed, 04 Nov 2026 09:35:53 +0000</pubDate>
      <link>https://dev.to/erenxcolakx/how-to-run-multiple-claude-code-sessions-at-once-3ema</link>
      <guid>https://dev.to/erenxcolakx/how-to-run-multiple-claude-code-sessions-at-once-3ema</guid>
      <description>&lt;p&gt;&lt;em&gt;I make &lt;a href="https://paneherd.com/" rel="noopener noreferrer"&gt;Paneherd&lt;/a&gt;, which is option 4 below. Originally published at &lt;a href="https://paneherd.com/guides/multiple-claude-code-sessions" rel="noopener noreferrer"&gt;paneherd.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Claude Code works best on one focused task at a time, so the way to get more done is to run several sessions in parallel: one fixes a bug, one writes tests, one updates the docs. Doing that well comes down to three things: keeping the sessions from overwriting each other, noticing when one of them is waiting for you, and not running out of usage halfway through.&lt;/p&gt;

&lt;p&gt;Here are four ways to do it, and what each one leaves to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Separate terminals
&lt;/h2&gt;

&lt;p&gt;The simplest way: open a terminal per task and run &lt;code&gt;claude&lt;/code&gt; in each, or use split panes in tmux, Windows Terminal or your editor. It costs nothing and works everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it leaves to you:&lt;/strong&gt; every session asks for permission in its own terminal, so you have to look at each one to see which is stuck. If two sessions work in the same folder, they can edit the same file without knowing about each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Git worktrees
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://git-scm.com/docs/git-worktree" rel="noopener noreferrer"&gt;git worktree&lt;/a&gt; is a second checkout of the same repository in another folder, on its own branch. Give each session that changes code its own worktree and they cannot overwrite each other; you merge their branches when they are done. Claude Code can create one for you with &lt;code&gt;claude --worktree&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it leaves to you:&lt;/strong&gt; each worktree needs its own dependencies installed and its own dev server port, and you still watch each session separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Claude Code's agent view
&lt;/h2&gt;

&lt;p&gt;Claude Code has its own view of running sessions (&lt;code&gt;claude agents&lt;/code&gt;), and the official VS Code extension shows the status of each session. Agent view lists background sessions by state (working, needs input, completed) and, inside a git repository, moves each session into its own worktree before it edits. The extension runs several conversations in tabs and queues a message you send while Claude works. Permission prompts are still answered in each session. Check the &lt;a href="https://code.claude.com/docs" rel="noopener noreferrer"&gt;Claude Code documentation&lt;/a&gt; for what your version includes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A grid in VS Code or Cursor
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://paneherd.com/" rel="noopener noreferrer"&gt;Paneherd&lt;/a&gt; is an extension that opens each session as a real terminal in the editor area and lays them out in a grid. The sidebar shows each session's status from Claude Code's own hook events, counts the ones waiting for you, and jumps to the next one. On top of that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One permission inbox&lt;/strong&gt; (Pro): prompts from every session collect in the sidebar, with the command or file, and you answer them there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conflict guard&lt;/strong&gt; (Pro): when sessions share a folder, Claude asks before editing a file another session changed in the last ten minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broadcast and queue:&lt;/strong&gt; send one prompt to several sessions, or queue the next prompt for a busy one (queue is Pro).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage limits:&lt;/strong&gt; the five-hour and weekly limits of your plan, at the top of the sidebar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It works alongside worktrees: open a session per worktree and see them all in one window. The free version runs up to four sessions at once.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frg6gsjs0reojt6rciz4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frg6gsjs0reojt6rciz4s.png" alt="Four Claude Code sessions in a grid in VS Code, with the Paneherd sidebar showing three permission requests and a queued prompt." width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips that apply whichever way you choose
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One task per session,&lt;/strong&gt; stated in the first prompt. Sessions that wander are the ones that collide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't let two sessions edit the same files.&lt;/strong&gt; Split work by area, or use worktrees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep permission prompts on&lt;/strong&gt; for anything that touches the outside world. Answer them quickly so sessions don't sit idle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch your limits.&lt;/strong&gt; Parallel sessions use your plan's limits several times faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More on this: &lt;a href="https://paneherd.com/guides/claude-code-permission-prompts-multiple-sessions" rel="noopener noreferrer"&gt;handling permission prompts across sessions&lt;/a&gt; and &lt;a href="https://paneherd.com/guides/claude-code-usage-limits-parallel-sessions" rel="noopener noreferrer"&gt;how parallel sessions use your usage limits&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;How do you run your sessions? I'd like to hear what works for you in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Claude Code usage runs out so fast, and what is using it</title>
      <dc:creator>Eren Çolak</dc:creator>
      <pubDate>Wed, 21 Oct 2026 12:51:50 +0000</pubDate>
      <link>https://dev.to/erenxcolakx/why-claude-code-usage-runs-out-so-fast-and-what-is-using-it-5cec</link>
      <guid>https://dev.to/erenxcolakx/why-claude-code-usage-runs-out-so-fast-and-what-is-using-it-5cec</guid>
      <description>&lt;p&gt;Hitting your session or weekly limit sooner than your activity suggests is one of the most common complaints about Claude Code. The cause is usually not one big thing: a session that has been open for hours spends far more than the work you typed into it. Anthropic's &lt;a href="https://code.claude.com/docs/en/costs" rel="noopener noreferrer"&gt;cost documentation&lt;/a&gt; (checked 21 October 2026) lists the usual reasons. This guide goes through them, then shows how to find which one is yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find out first: &lt;code&gt;/usage&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before changing habits, look. On a Pro, Max, Team or Enterprise plan, &lt;code&gt;/usage&lt;/code&gt; shows your plan limits and a breakdown of what counts against them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Attribution:&lt;/strong&gt; recent usage attributed to skills, subagents, plugins and individual MCP servers, each as a share of the total.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavior flags:&lt;/strong&gt; long context or cache misses, flagged when one accounts for 10% or more of recent usage, each with a tip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loops:&lt;/strong&gt; your heaviest &lt;code&gt;/loop&lt;/code&gt; and other scheduled tasks, by total tokens (newer versions of Claude Code).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Press d or w to switch between the last 24 hours and 7 days. The figures are approximate and come from the session history on that machine, so usage from other devices or claude.ai is not in them. Newer versions also add a prompt cache line to the Session block, showing the share of input served from cache and how many misses there were.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight reasons usage climbs
&lt;/h2&gt;

&lt;p&gt;These are the causes the documentation names for a long session using more of your limit than it seems to deserve.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. A long conversation is re-read on every request
&lt;/h3&gt;

&lt;p&gt;Claude Code sends your whole conversation with each request, and every round of tool use sends it again with the results. Prompt caching re-reads that history at the cheaper cached rate, but a one-line question at the end of a day-long session still draws on the entire conversation. &lt;strong&gt;Fix:&lt;/strong&gt; run &lt;code&gt;/clear&lt;/code&gt; when you switch to unrelated work (use &lt;code&gt;/rename&lt;/code&gt; first and &lt;code&gt;/resume&lt;/code&gt; later if you want to come back), and &lt;code&gt;/compact&lt;/code&gt; with instructions about what to keep when you need continuity.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Cache misses after a break
&lt;/h3&gt;

&lt;p&gt;Your first message after a pause longer than the cache lifetime misses the cache and reprocesses the whole context at full rate. &lt;strong&gt;Fix:&lt;/strong&gt; if you know you are done with a session for a while, start fresh later rather than resuming a huge context after the break.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Scheduled tasks keep firing
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;/loop&lt;/code&gt; or other session-scoped scheduled task fires on its interval even while the session is idle, sending the full context each time. &lt;strong&gt;Fix:&lt;/strong&gt; check the Loops rows in &lt;code&gt;/usage&lt;/code&gt; and stop tasks you forgot.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Messages from your other sessions
&lt;/h3&gt;

&lt;p&gt;When another of your sessions sends a message to an idle one, it starts a new turn that sends the full context. The &lt;code&gt;crossSessionInbound&lt;/code&gt; setting can be set to &lt;code&gt;hold&lt;/code&gt; to keep inbound messages from being delivered.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Goal check-ins
&lt;/h3&gt;

&lt;p&gt;While background work keeps an active goal waiting, Claude Code can start idle check-ins, each a new turn with your full context. Recent versions cap them at three per goal between your prompts; &lt;code&gt;CLAUDE_CODE_GOAL_CHECKIN_MINUTES=0&lt;/code&gt; turns them off.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Subagents and workflows
&lt;/h3&gt;

&lt;p&gt;Every subagent, and every agent a workflow spawns, sends its own requests on top of the main conversation's. The attribution breakdown in &lt;code&gt;/usage&lt;/code&gt; shows their share. &lt;strong&gt;Fix:&lt;/strong&gt; give simple subagent tasks a smaller model (&lt;code&gt;model: haiku&lt;/code&gt; in the subagent's configuration), and keep verbose work such as running tests in a subagent so only a summary returns.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Agent teams
&lt;/h3&gt;

&lt;p&gt;Each active teammate keeps its own context window and keeps consuming tokens until it exits. The documentation says teams use roughly seven times the tokens of a standard session when teammates run in plan mode. &lt;strong&gt;Fix:&lt;/strong&gt; keep teams small, give them focused tasks and shut teammates down when their work is done.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Compaction is a big request too
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/compact&lt;/code&gt; has to read the conversation it summarizes, so compacting a large context is itself a large request. When you want a clean start rather than continuity, &lt;code&gt;/clear&lt;/code&gt; costs nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smaller levers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model and effort.&lt;/strong&gt; Sonnet handles most coding tasks for less than Opus; switch with &lt;code&gt;/model&lt;/code&gt;. Lower the effort level with &lt;code&gt;/effort&lt;/code&gt; for simple tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP servers.&lt;/strong&gt; Run &lt;code&gt;/context&lt;/code&gt; to see what fills your context and &lt;code&gt;/mcp&lt;/code&gt; to disable servers you are not using.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A big CLAUDE.md.&lt;/strong&gt; It loads at the start of every session. Anthropic suggests moving workflow-specific instructions into skills, which load only when used, and keeping CLAUDE.md under 200 lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vague prompts.&lt;/strong&gt; "Improve this codebase" triggers broad scanning; naming the file and the change does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan mode and early course-correction.&lt;/strong&gt; Press Shift+Tab for plan mode before big changes, and Esc as soon as Claude heads the wrong way.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When you run several sessions
&lt;/h2&gt;

&lt;p&gt;Every session draws on the same allowance, each with its own conversation, so four sessions spend it faster than one, and a long-lived one spends more than a fresh one. &lt;code&gt;/usage&lt;/code&gt; works per machine, not per session. &lt;a href="https://paneherd.com/" rel="noopener noreferrer"&gt;Paneherd&lt;/a&gt; shows the five-hour and weekly figures at the top of its sidebar and estimates each open pane's approximate share of the current window from its transcript, so the heavy session stands out. It also flags a pane that repeats the same failing call, which spends usage and gets nothing done. The shares are an estimate based on Paneherd's own weights, not Anthropic's accounting. More in &lt;a href="https://paneherd.com/guides/claude-code-usage-limits-parallel-sessions" rel="noopener noreferrer"&gt;how parallel sessions use your usage limits&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the numbers in view
&lt;/h2&gt;

&lt;p&gt;If you only want the limits in front of you, without a sidebar or panes, the free &lt;a href="https://marketplace.visualstudio.com/items?itemName=paneherd.usage-meter" rel="noopener noreferrer"&gt;Claude Code &amp;amp; Codex Usage Meter&lt;/a&gt; puts the five-hour and weekly percentages, and Codex's, in the VS Code status bar and warns at 85% by default. It reads what Claude Code and Codex already report on your computer and sends nothing anywhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=paneherd.paneherd" rel="noopener noreferrer"&gt;Install Paneherd free&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://paneherd.com/guides/claude-code-usage-running-out-fast" rel="noopener noreferrer"&gt;paneherd.com/guides/claude-code-usage-running-out-fast&lt;/a&gt;. I make Paneherd, a VS Code extension for running coding agents side by side.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vscode</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How to control Claude Code and Codex from your phone</title>
      <dc:creator>Eren Çolak</dc:creator>
      <pubDate>Wed, 21 Oct 2026 11:50:59 +0000</pubDate>
      <link>https://dev.to/erenxcolakx/how-to-control-claude-code-and-codex-from-your-phone-2o07</link>
      <guid>https://dev.to/erenxcolakx/how-to-control-claude-code-and-codex-from-your-phone-2o07</guid>
      <description>&lt;p&gt;A coding agent that needs you while you are away from your desk just waits: for a permission, an answer, or its next prompt. There are now several ways to reach it from your phone. They differ in which agents they cover, what the phone can do, and what they ask of your setup. In every one of them the agent keeps running on your computer, so your computer has to stay on and awake.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Claude Code Remote Control
&lt;/h2&gt;

&lt;p&gt;Anthropic's own option. &lt;a href="https://code.claude.com/docs/en/remote-control" rel="noopener noreferrer"&gt;Remote Control&lt;/a&gt; connects the Claude app on iOS or Android, or &lt;a href="https://claude.ai/code" rel="noopener noreferrer"&gt;claude.ai/code&lt;/a&gt;, to a Claude Code session on your machine. There are three ways to start it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;claude remote-control&lt;/code&gt; runs a server in the current folder that you start sessions from on the phone. Press the spacebar to show a QR code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;claude --remote-control&lt;/code&gt; starts an ordinary interactive session that the phone can join too.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/remote-control&lt;/code&gt; (or &lt;code&gt;/rc&lt;/code&gt;) connects a session that is already running, including in the Claude Code extension for VS Code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the phone you can send messages, attach photos and files, and answer permission prompts. With &lt;strong&gt;Push when actions required&lt;/strong&gt; turned on in &lt;code&gt;/config&lt;/code&gt;, the Claude app notifies you when a session needs a decision. It needs a Pro, Max, Team or Enterprise plan and a claude.ai login: it does not work with an API key, or with &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; pointing at a gateway. On Team and Enterprise an Owner has to turn it on first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Claude Code on a Claude subscription. It is the most complete option for Claude, and it is built in.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Codex in the ChatGPT app
&lt;/h2&gt;

&lt;p&gt;OpenAI added Codex control to the ChatGPT app for iPhone and Android in 2026. You pair the phone with Codex on your computer by scanning a QR code shown by the &lt;a href="https://developers.openai.com/codex/app" rel="noopener noreferrer"&gt;Codex app&lt;/a&gt;, then start tasks, follow their progress and approve commands from the phone. Newer Codex CLI versions also have an experimental &lt;code&gt;codex remote-control&lt;/code&gt; command for machines without the desktop app. Which plans, regions and host systems are covered has changed during the rollout, so check OpenAI's current documentation before you count on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Codex on a ChatGPT plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Happy, an open-source app for both
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/slopus/happy" rel="noopener noreferrer"&gt;Happy&lt;/a&gt; is an open-source mobile and web client for Claude Code and Codex. You start the agent through its wrapper (&lt;code&gt;happy claude&lt;/code&gt; or &lt;code&gt;happy codex&lt;/code&gt;) instead of the bare command, and switch to the phone when you leave. Its makers say the connection is end-to-end encrypted, and it notifies you when the agent needs permission. Sessions you start without the wrapper are not covered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; one app for Claude Code and Codex, if you are happy to launch them through it.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. SSH and tmux
&lt;/h2&gt;

&lt;p&gt;The tool-independent way. Run your agents inside &lt;code&gt;tmux&lt;/code&gt; on your computer and attach to the same tmux session from an SSH app on the phone (Termius, Blink and others), usually over a VPN such as Tailscale so the computer is not exposed to the internet. You see the real terminal of any agent, whatever its maker. A phone keyboard is a hard place to drive a terminal UI, though, and nothing tells you when an agent starts waiting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; people who already work in tmux, and agents no app supports.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Paneherd's phone remote, for every pane in your editor
&lt;/h2&gt;

&lt;p&gt;If you run several agents of different kinds side by side in VS Code or Cursor, &lt;a href="https://paneherd.com/" rel="noopener noreferrer"&gt;Paneherd&lt;/a&gt; runs each one as a pane in an editor grid, and its phone remote shows all of them on one page. Run &lt;em&gt;Pair a Phone…&lt;/em&gt;, scan the QR code and click &lt;em&gt;Allow&lt;/em&gt; in the editor. Your phone opens &lt;a href="https://paneherd.com/remote" rel="noopener noreferrer"&gt;paneherd.com/remote&lt;/a&gt; in the browser, with no app to install, and lists every editor window's panes with their status: working, waiting for permission, asking a question, or done. You can send a prompt to one pane or to several at once. With Pro you also answer Claude Code's permission prompts from the phone (Allow, Always, Deny).&lt;/p&gt;

&lt;p&gt;It works for Claude Code, Codex, Copilot, Gemini and Cursor panes alike (Gemini and Cursor panes take prompts but report no status), whatever plan or API key each one uses, because it talks to the editor rather than to Anthropic or OpenAI. Messages go through Paneherd's relay sealed with a key only your phone and your editor have, so the relay cannot read them. It only covers agents running as Paneherd panes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; a mixed herd of agents in your editor, seen and prompted from one page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side by side
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Agents&lt;/th&gt;
&lt;th&gt;On the phone&lt;/th&gt;
&lt;th&gt;Needs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code Remote Control&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Claude app or browser&lt;/td&gt;
&lt;td&gt;Pro, Max, Team or Enterprise; no API keys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codex in ChatGPT&lt;/td&gt;
&lt;td&gt;Codex&lt;/td&gt;
&lt;td&gt;ChatGPT app&lt;/td&gt;
&lt;td&gt;A ChatGPT plan; Codex app on the host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Happy&lt;/td&gt;
&lt;td&gt;Claude Code, Codex&lt;/td&gt;
&lt;td&gt;Happy app or browser&lt;/td&gt;
&lt;td&gt;Starting agents through its wrapper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH and tmux&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;td&gt;An SSH app&lt;/td&gt;
&lt;td&gt;tmux, SSH access, usually a VPN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paneherd phone remote&lt;/td&gt;
&lt;td&gt;Claude Code, Codex, Copilot, Gemini, Cursor&lt;/td&gt;
&lt;td&gt;Browser&lt;/td&gt;
&lt;td&gt;VS Code or Cursor with Paneherd&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Which one to pick
&lt;/h2&gt;

&lt;p&gt;Mostly Claude Code on a subscription: use Remote Control, it is built in. Mostly Codex: use the ChatGPT app. Several kinds of agents at once in your editor: Paneherd's phone remote shows them together, and you can still turn on Remote Control in a Claude pane when you want the Claude app's full view of that one session. The options do not exclude each other.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://paneherd.com/guides/control-claude-code-codex-from-phone" rel="noopener noreferrer"&gt;paneherd.com/guides/control-claude-code-codex-from-phone&lt;/a&gt;. I make Paneherd, a VS Code extension for running coding agents side by side.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vscode</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
