<?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: Dawon Lee</title>
    <description>The latest articles on DEV Community by Dawon Lee (@dawonlee).</description>
    <link>https://dev.to/dawonlee</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%2F4183197%2F6892c41a-ae4d-4cb0-b10e-08549b2ca5c6.jpg</url>
      <title>DEV Community: Dawon Lee</title>
      <link>https://dev.to/dawonlee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dawonlee"/>
    <language>en</language>
    <item>
      <title>Lid closed, Claude Code still running: how macOS DarkWakes burn your weekly limit overnight</title>
      <dc:creator>Dawon Lee</dc:creator>
      <pubDate>Sat, 24 Oct 2026 01:36:08 +0000</pubDate>
      <link>https://dev.to/dawonlee/lid-closed-claude-code-still-running-how-macos-darkwakes-burn-your-weekly-limit-overnight-217i</link>
      <guid>https://dev.to/dawonlee/lid-closed-claude-code-still-running-how-macos-darkwakes-burn-your-weekly-limit-overnight-217i</guid>
      <description>&lt;p&gt;You start a long Claude Code task, close the MacBook lid, and go to bed. In the morning the task isn't done, the log is full of &lt;code&gt;Connection lost while your computer was asleep&lt;/code&gt;, and your weekly limit is 20 or 30 points lower than when you left. Nothing useful was produced.&lt;/p&gt;

&lt;p&gt;Four reports of this landed on the Claude Code tracker between October 15 and 18 (&lt;a href="https://github.com/anthropics/claude-code/issues/102597" rel="noopener noreferrer"&gt;#102597&lt;/a&gt;, &lt;a href="https://github.com/anthropics/claude-code/issues/102269" rel="noopener noreferrer"&gt;#102269&lt;/a&gt;, &lt;a href="https://github.com/anthropics/claude-code/issues/103064" rel="noopener noreferrer"&gt;#103064&lt;/a&gt;, &lt;a href="https://github.com/anthropics/claude-code/issues/103233" rel="noopener noreferrer"&gt;#103233&lt;/a&gt;). The logs in two of them are detailed enough to see exactly what happens, so here is the mechanism and what you can do about it today.&lt;/p&gt;

&lt;h2&gt;
  
  
  A sleeping Mac isn't asleep
&lt;/h2&gt;

&lt;p&gt;Closing the lid puts the Mac into &lt;code&gt;Clamshell Sleep&lt;/code&gt;. But macOS keeps waking it for a few seconds at a time, screen off, to run maintenance, Power Nap, network and "Sleep Service" chores. These are &lt;strong&gt;DarkWakes&lt;/strong&gt;, and &lt;code&gt;pmset -g log&lt;/code&gt; shows them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pmset &lt;span class="nt"&gt;-g&lt;/span&gt; log | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"DarkWake|Clamshell"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;a href="https://github.com/anthropics/claude-code/issues/103064" rel="noopener noreferrer"&gt;#103064&lt;/a&gt; log they came every 15 to 20 minutes and lasted 2 to 7 seconds, plus one 27-minute maintenance wake once the Mac was on AC power. In &lt;a href="https://github.com/anthropics/claude-code/issues/102597" rel="noopener noreferrer"&gt;#102597&lt;/a&gt; there were 26 wake cycles in 6.5 hours, about one every 15 minutes.&lt;/p&gt;

&lt;p&gt;Programs run during those seconds. A Claude Code session that was mid-stream when the lid closed does this on every wake:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Its watchdog sees the clock jump, aborts the frozen stream (&lt;code&gt;StreamSuspended&lt;/code&gt;) and reports &lt;code&gt;Connection lost while your computer was asleep&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It re-sends the request, which means the whole conversation context again.&lt;/li&gt;
&lt;li&gt;The Mac goes back to sleep 2 to 7 seconds later, mid-stream. Back to step 1.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What that costs
&lt;/h2&gt;

&lt;p&gt;The numbers from the two detailed reports, as the reporters measured them from their own transcripts and debug logs:&lt;/p&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;
&lt;a href="https://github.com/anthropics/claude-code/issues/102597" rel="noopener noreferrer"&gt;#102597&lt;/a&gt; (2 background subagents, battery)&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://github.com/anthropics/claude-code/issues/103064" rel="noopener noreferrer"&gt;#103064&lt;/a&gt; (1 foreground session, desktop app)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lid closed for&lt;/td&gt;
&lt;td&gt;6.5 h&lt;/td&gt;
&lt;td&gt;2.2 h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests sent&lt;/td&gt;
&lt;td&gt;81&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context per request&lt;/td&gt;
&lt;td&gt;400K to 580K tokens&lt;/td&gt;
&lt;td&gt;648K to 728K tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt cache&lt;/td&gt;
&lt;td&gt;cold on 15 of the completed calls (about 7.1M tokens of &lt;code&gt;cache_creation&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;warm throughout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output produced&lt;/td&gt;
&lt;td&gt;about 7K tokens&lt;/td&gt;
&lt;td&gt;task finished during the 27-minute wake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weekly usage&lt;/td&gt;
&lt;td&gt;20% → 56%&lt;/td&gt;
&lt;td&gt;about 9% → 19%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two things stand out. First, a foreground session does this too, not just background agents, and the desktop app's Code tab is no different from the CLI. Second, in the background-agent case the prompt cache was cold on half the completed calls, so each of those re-sent 400K+ tokens as a fresh cache write. The log shows &lt;code&gt;404 No thread state was found&lt;/code&gt; followed by &lt;code&gt;forcing create for retry: replay_not_found&lt;/code&gt; eleven times, which looks like the reason, but I can only guess from outside. Neither reporter can see what the aborted requests were charged; that part only Anthropic can answer, and both issues ask for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing it yourself
&lt;/h2&gt;

&lt;p&gt;The expensive state is the one in between: a Mac that is neither awake nor fully stopped. Before you close the lid, pick one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep it awake to the end.&lt;/strong&gt; The only thing that stops lid-close sleep on a MacBook is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pmset &lt;span class="nt"&gt;-a&lt;/span&gt; disablesleep 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stream never gets cut, so nothing is re-sent. It survives restarts, so set it back with &lt;code&gt;sudo pmset -a disablesleep 0&lt;/code&gt; when the task is done, or the Mac stays awake in your bag. Keep it on a hard surface; it will run warm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or really stop it.&lt;/strong&gt; Press Esc to interrupt the turn, and make sure no background agents are still running, before the lid goes down. With nothing in flight, the DarkWakes cost nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fewer wakes helps a little.&lt;/strong&gt; &lt;code&gt;sudo pmset -a powernap 0&lt;/code&gt; removes the longer Power Nap wakes. The short maintenance and Sleep Service wakes remain, so this reduces the retries rather than ending them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If it already happened to you&lt;/strong&gt;, your transcript (&lt;code&gt;~/.claude/projects/...jsonl&lt;/code&gt;) and &lt;code&gt;pmset -g log&lt;/code&gt; have the same data the reporters used. Adding your numbers to those issues is the most useful thing you can do; the open question is how aborted requests count against the limit, and more cases make it easier to answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing it only while work runs
&lt;/h2&gt;

&lt;p&gt;I build &lt;a href="https://lidnight.app/en/" rel="noopener noreferrer"&gt;Lidnight&lt;/a&gt;, a menu bar app for exactly this gap. It uses Claude Code's and Codex's hooks to know when a turn is running and keeps the Mac fully awake only then, lid closed and on battery too, background sessions included. Once every session has been quiet for ten minutes it restores &lt;code&gt;disablesleep&lt;/code&gt; and lets the Mac sleep, and it undoes a leftover &lt;code&gt;disablesleep&lt;/code&gt; at boot so a crash can't leave the Mac stuck awake. Working means no DarkWake gaps to re-send across; sleeping means nothing left in flight. Staying awake with the lid closed is a Pro feature and is included in the 7-day trial.&lt;/p&gt;

&lt;p&gt;The hooks themselves are plain shell. If you'd rather wire this up yourself, the &lt;code&gt;caffeinate&lt;/code&gt; recipe in &lt;a href="https://github.com/whereisdw/claude-code-hooks-recipes" rel="noopener noreferrer"&gt;claude-code-hooks-recipes&lt;/a&gt; keeps the Mac awake per session (it can't block lid-close sleep, so pair it with &lt;code&gt;disablesleep&lt;/code&gt; for that), and the longer write-up with the Korean and Japanese versions is on &lt;a href="https://lidnight.app/en/guides/claude-code-darkwake-lid-closed/" rel="noopener noreferrer"&gt;lidnight.app&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>claude</category>
      <category>macos</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Claude Code Remote Control stops when you close the lid. Here's why, and the fix</title>
      <dc:creator>Dawon Lee</dc:creator>
      <pubDate>Thu, 22 Oct 2026 22:52:59 +0000</pubDate>
      <link>https://dev.to/dawonlee/claude-code-remote-control-stops-when-you-close-the-lid-heres-why-and-the-fix-45h2</link>
      <guid>https://dev.to/dawonlee/claude-code-remote-control-stops-when-you-close-the-lid-heres-why-and-the-fix-45h2</guid>
      <description>&lt;p&gt;Claude Code's &lt;a href="https://code.claude.com/docs/en/remote-control" rel="noopener noreferrer"&gt;Remote Control&lt;/a&gt; is great: run &lt;code&gt;claude remote-control&lt;/code&gt; (or &lt;code&gt;/remote-control&lt;/code&gt; in a session), scan the QR code with the Claude app, and you can keep steering the session from your phone on the couch. Turn on &lt;strong&gt;Push when actions required&lt;/strong&gt; in &lt;code&gt;/config&lt;/code&gt; and permission prompts and questions arrive as pushes.&lt;/p&gt;

&lt;p&gt;Then you close the MacBook lid, and the session goes quiet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;The session runs on your Mac. Remote Control is a window into it, not a copy of it. When the Mac sleeps, Claude stops. The docs say exactly this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if your laptop sleeps or your network drops, Claude Code reconnects automatically when your machine comes back online.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it reconnects &lt;em&gt;afterwards&lt;/em&gt;. Nothing runs while the Mac is asleep, and the message you sent from your phone waits until the lid opens again.&lt;/p&gt;

&lt;p&gt;Closing the lid without an external display puts a MacBook to sleep regardless of &lt;code&gt;caffeinate&lt;/code&gt;. Claude Code already runs &lt;code&gt;caffeinate -i&lt;/code&gt; while it works, which only blocks &lt;em&gt;idle&lt;/em&gt; sleep.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing it yourself
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Lid open, on power.&lt;/strong&gt; Nothing to do. &lt;code&gt;caffeinate -i&lt;/code&gt; keeps the Mac awake while a turn runs. If the light bothers you, &lt;code&gt;pmset displaysleepnow&lt;/code&gt; turns the screen off without sleeping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lid closed (bag, bedside).&lt;/strong&gt; The only thing that stops lid-close sleep is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pmset &lt;span class="nt"&gt;-a&lt;/span&gt; disablesleep 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to know before you do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It survives restarts, and if you forget to run &lt;code&gt;sudo pmset -a disablesleep 0&lt;/code&gt; afterwards, the Mac stays awake in your bag, draining and heating. Keep it on a hard, ventilated surface.&lt;/li&gt;
&lt;li&gt;On battery you get a few hours at most, and a Mac that's awake but idle will keep polling. If a turn is mid-stream when the Mac finally sleeps, you get the &lt;a href="https://lidnight.app/en/guides/claude-code-computer-went-to-sleep/" rel="noopener noreferrer"&gt;"went to sleep mid-response"&lt;/a&gt; retries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Knowing when it's done.&lt;/strong&gt; Besides Remote Control's own pushes, a &lt;code&gt;Stop&lt;/code&gt; hook can ping you. I keep copy-paste versions of that (and of answering &lt;code&gt;AskUserQuestion&lt;/code&gt; from a hook) in &lt;a href="https://github.com/whereisdw/claude-code-hooks-recipes" rel="noopener noreferrer"&gt;claude-code-hooks-recipes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing it only while work runs
&lt;/h2&gt;

&lt;p&gt;I build &lt;a href="https://lidnight.app/en/" rel="noopener noreferrer"&gt;Lidnight&lt;/a&gt;, a menu bar app that takes just the part Remote Control leaves out: it uses Claude Code's and Codex's hooks to keep the Mac awake only while a turn is running (lid closed, on battery too), and once every session has been quiet for ten minutes it restores &lt;code&gt;disablesleep&lt;/code&gt; and lets the Mac sleep. It also undoes a leftover &lt;code&gt;disablesleep&lt;/code&gt; at boot, so a crash can't leave your Mac stuck awake.&lt;/p&gt;

&lt;p&gt;Remote Control stays exactly as it is. Continue from your phone, leave the lid closed, and the Mac sleeps on its own when the work is done.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>claude</category>
      <category>macos</category>
      <category>productivity</category>
    </item>
    <item>
      <title>You can answer Claude Code's AskUserQuestion from a hook (and from your phone)</title>
      <dc:creator>Dawon Lee</dc:creator>
      <pubDate>Wed, 21 Oct 2026 11:26:55 +0000</pubDate>
      <link>https://dev.to/dawonlee/you-can-answer-claude-codes-askuserquestion-from-a-hook-and-from-your-phone-1ddn</link>
      <guid>https://dev.to/dawonlee/you-can-answer-claude-codes-askuserquestion-from-a-hook-and-from-your-phone-1ddn</guid>
      <description>&lt;p&gt;Claude Code sometimes stops and asks you a multiple-choice question with the &lt;code&gt;AskUserQuestion&lt;/code&gt; tool ("Which framework?", "Keep the old API or replace it?"). If you're away from the terminal, the run just sits there.&lt;/p&gt;

&lt;p&gt;The hooks docs describe answering it in &lt;code&gt;-p&lt;/code&gt; mode: a &lt;code&gt;PreToolUse&lt;/code&gt; hook returns &lt;code&gt;allow&lt;/code&gt; plus an &lt;code&gt;updatedInput&lt;/code&gt; that carries the answers. I wanted to know if the same works in a normal interactive session through a &lt;code&gt;PermissionRequest&lt;/code&gt; hook, so I tested it on Claude Code 2.1.283. It does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the hook receives
&lt;/h2&gt;

&lt;p&gt;When Claude calls &lt;code&gt;AskUserQuestion&lt;/code&gt; in an interactive session, a &lt;code&gt;PermissionRequest&lt;/code&gt; hook gets this on stdin (trimmed):&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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hook_event_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PermissionRequest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AskUserQuestion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool_input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"questions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"question"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Which color do you want?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blue"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"multiSelect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What the hook returns
&lt;/h2&gt;

&lt;p&gt;Copy &lt;code&gt;tool_input&lt;/code&gt;, add an &lt;code&gt;answers&lt;/code&gt; object that maps each question's text to the chosen label (comma-separated for multi-select), and return it as &lt;code&gt;updatedInput&lt;/code&gt; with &lt;code&gt;behavior: "allow"&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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hookSpecificOutput"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hookEventName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PermissionRequest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"decision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"behavior"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"updatedInput"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"questions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...same&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;input...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"answers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Which color do you want?"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blue"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code then shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⏺ User answered Claude's questions:
  ⎿  · Which color do you want? → Blue
  ⎿  Allowed by PermissionRequest hook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and Claude continues with "Blue". No terminal prompt appears.&lt;/p&gt;

&lt;h2&gt;
  
  
  A minimal test hook
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;# Answers every AskUserQuestion with the last option. For testing only.&lt;/span&gt;
python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'
import json, sys
d = json.load(sys.stdin)
if d.get("tool_name") != "AskUserQuestion":
    sys.exit(0)  # no decision: the normal permission prompt shows
ti = d["tool_input"]
ti["answers"] = {q["question"]: q["options"][-1]["label"] for q in ti.get("questions", [])}
print(json.dumps({"hookSpecificOutput": {"hookEventName": "PermissionRequest",
      "decision": {"behavior": "allow", "updatedInput": ti}}}))
'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register it under &lt;code&gt;hooks.PermissionRequest&lt;/code&gt; in a settings file and try &lt;code&gt;claude --settings test-settings.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two things to watch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;allow&lt;/code&gt; alone doesn't answer the question.&lt;/strong&gt; If your approval hook (or an approval app) just returns &lt;code&gt;allow&lt;/code&gt; for &lt;code&gt;AskUserQuestion&lt;/code&gt;, the question stays open and the session still waits. I hit exactly this: my phone approval said "allowed", but Claude was still waiting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hook blocks until it returns.&lt;/strong&gt; To answer from somewhere else, the hook has to wait for that answer (and give up before the hook timeout so the terminal prompt still works).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using it from a phone
&lt;/h2&gt;

&lt;p&gt;I build &lt;a href="https://lidnight.app/en/" rel="noopener noreferrer"&gt;Lidnight&lt;/a&gt;, a menu bar app that keeps a Mac awake while Claude Code and Codex work. Version 1.7.79 uses this: when Claude asks a question, the options show up on the phone status page (end-to-end encrypted) and in the Mac menu bar, and the one you tap goes back to Claude through the hook. You can still answer in the terminal; whichever comes first wins.&lt;/p&gt;

&lt;p&gt;Update: the hook above plus four more (Stop notification, ntfy phone push, caffeinate for the session, leftover processes) are collected as copy-paste scripts here: &lt;a href="https://github.com/whereisdw/claude-code-hooks-recipes" rel="noopener noreferrer"&gt;https://github.com/whereisdw/claude-code-hooks-recipes&lt;/a&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Codex will answer its own question if you're not looking. Here's how to catch it</title>
      <dc:creator>Dawon Lee</dc:creator>
      <pubDate>Sun, 18 Oct 2026 10:07:17 +0000</pubDate>
      <link>https://dev.to/dawonlee/codex-will-answer-its-own-question-if-youre-not-looking-heres-how-to-catch-it-3gb8</link>
      <guid>https://dev.to/dawonlee/codex-will-answer-its-own-question-if-youre-not-looking-heres-how-to-catch-it-3gb8</guid>
      <description>&lt;p&gt;If you use Codex, you've probably seen this: it stops to ask you something ("Which folder should I refactor?"), and if you don't answer quickly it goes ahead with its own recommended option. People have asked for a way to turn that off, and the &lt;a href="https://github.com/openai/codex/issues/28969" rel="noopener noreferrer"&gt;issue&lt;/a&gt; has 200+ 👍. Since 0.147, Plan mode waits for you, but per the thread, questions in default mode (the desktop app's "ask while working" questions) can still resolve themselves.&lt;/p&gt;

&lt;p&gt;Until there's a setting, the practical fix is to &lt;strong&gt;find out the moment Codex asks&lt;/strong&gt;, even when the terminal is behind three other windows or you're on the couch.&lt;/p&gt;

&lt;h2&gt;
  
  
  There's no hook for it
&lt;/h2&gt;

&lt;p&gt;Codex hooks cover &lt;code&gt;SessionStart&lt;/code&gt;, &lt;code&gt;UserPromptSubmit&lt;/code&gt;, &lt;code&gt;PreToolUse&lt;/code&gt;, &lt;code&gt;PermissionRequest&lt;/code&gt;, &lt;code&gt;PostToolUse&lt;/code&gt;, &lt;code&gt;Stop&lt;/code&gt; and a few others (&lt;a href="https://developers.openai.com/codex/hooks" rel="noopener noreferrer"&gt;docs&lt;/a&gt;). &lt;code&gt;PermissionRequest&lt;/code&gt; fires for approvals (shell escalation, network), &lt;strong&gt;not&lt;/strong&gt; for questions. So a &lt;code&gt;notify&lt;/code&gt;/hook setup that pings you on approvals stays silent when Codex asks a question.&lt;/p&gt;

&lt;h2&gt;
  
  
  But the session log has it
&lt;/h2&gt;

&lt;p&gt;Every Codex session writes a JSONL rollout under &lt;code&gt;~/.codex/sessions/YYYY/MM/DD/&lt;/code&gt;. A question is a tool call named &lt;code&gt;request_user_input&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;"response_item"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"payload"&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;"function_call"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"request_user_input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;questions&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:[{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;header&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Scope&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;question&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Which folder should I refactor?&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}],&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;isBlocking&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:true}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"call_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"call_…"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you answer, a &lt;code&gt;function_call_output&lt;/code&gt; with the same &lt;code&gt;call_id&lt;/code&gt; follows. So &lt;strong&gt;a &lt;code&gt;request_user_input&lt;/code&gt; call with no output yet = Codex is waiting on you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Two caveats from checking my own logs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The desktop app's default-mode questions show up as &lt;code&gt;request_user_input_async&lt;/code&gt;. Those get &lt;code&gt;{"accepted":true}&lt;/code&gt; back within a fraction of a second while Codex keeps working, so "no output yet" doesn't work for them. The script below treats any async question from the last 3 minutes as new instead. These are the ones that can still resolve without you.&lt;/li&gt;
&lt;li&gt;The field layout above is from Codex's source (&lt;code&gt;protocol/src/request_user_input.rs&lt;/code&gt;) and matches the envelope in my logs, but log formats aren't a stable API, so expect to adjust it someday.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A small watcher
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Notify (macOS) when Codex is blocked on a question you haven&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t answered yet.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;

&lt;span class="n"&gt;ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.codex/sessions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getsize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;256_000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# the tail is enough
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="s"&gt;response_item&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payload&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function_call_output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function_call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_user_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_user_input_async&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_async&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getmtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;   &lt;span class="c1"&gt;# async: only fresh ones (they're 'accepted' instantly)
&lt;/span&gt;                &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arguments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;questions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;header&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
                &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;IndexError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
                &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_async&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_async&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_async&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Codex is waiting for your answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;osascript&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-e&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;display notification &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; with title &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Codex has a question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; sound name &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Glass&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ROOT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/*/*/*/*.jsonl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getmtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# only live sessions
&lt;/span&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cid&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it in a spare terminal (&lt;code&gt;python3 codex-question-alert.py&lt;/code&gt;). It only reads files that changed in the last 30 minutes and only the last 256 KB of each, so it's cheap. I tested it against a synthetic log (one unanswered question, one answered, one fresh async) and against a week of my real logs (no false alarms).&lt;/p&gt;

&lt;p&gt;To get it on your phone, swap &lt;code&gt;notify()&lt;/code&gt; for a &lt;code&gt;curl&lt;/code&gt; to an &lt;a href="https://ntfy.sh" rel="noopener noreferrer"&gt;ntfy&lt;/a&gt; topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did in Lidnight
&lt;/h2&gt;

&lt;p&gt;I build &lt;a href="https://lidnight.app/en/" rel="noopener noreferrer"&gt;Lidnight&lt;/a&gt;, a menu bar app that keeps a MacBook awake (lid closed, even on battery) while Claude Code and Codex work and lets it sleep when they're done. Version 1.7.69 does the check above on its own: when Codex asks you a question (blocking or the desktop app's async kind), you get a Mac notification and a phone push (if you've linked one) right away, with the question text. It can't answer for you. It just makes sure you see the question in time.&lt;/p&gt;

&lt;p&gt;Lidnight is free with the lid open (AI Auto mode); a one-time Pro keeps it going with the lid closed, even on battery. Launch price is 50% off through Oct 31. &lt;code&gt;brew install whereisdw/tap/lidnight&lt;/code&gt;&lt;/p&gt;

</description>
      <category>codex</category>
      <category>openai</category>
      <category>macos</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Claude Code now resumes after a usage limit — unless your Mac fell asleep</title>
      <dc:creator>Dawon Lee</dc:creator>
      <pubDate>Wed, 14 Oct 2026 09:14:49 +0000</pubDate>
      <link>https://dev.to/dawonlee/claude-code-now-resumes-after-a-usage-limit-unless-your-mac-fell-asleep-49dj</link>
      <guid>https://dev.to/dawonlee/claude-code-now-resumes-after-a-usage-limit-unless-your-mac-fell-asleep-49dj</guid>
      <description>&lt;p&gt;If you're on a Claude subscription, recent versions of Claude Code (v2.1.234+) do something quietly great: when a usage limit stops Claude mid-task, the session &lt;strong&gt;waits and continues the task on its own&lt;/strong&gt; after the limit resets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Usage limit reached · limit resets 3:45pm
Continuing automatically at 3:45pm · esc to cancel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's exactly what you want for a long refactor you start before bed. There's one catch, straight from the docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If it slept for more than about 30 minutes and the limit reset while it slept, the first line reads &lt;code&gt;Your usage limit has reset&lt;/code&gt; and the second reads &lt;code&gt;Press enter to continue&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So if your MacBook goes to sleep during the wait — lid closed, or just idle sleep — you wake up to a prompt asking you to press Enter, and the work hasn't moved. The 5-hour window means the wait can easily be a few hours.&lt;/p&gt;

&lt;p&gt;(One more catch, pointed out by John Reed in the comments: the wait is interactive-only. Background sessions and &lt;code&gt;claude -p&lt;/code&gt; runs don't get it — a rate-limit stop there is just a stop.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the Mac awake through the wait
&lt;/h2&gt;

&lt;p&gt;The wait itself uses almost no CPU, which is the problem: from the outside, a session waiting for a reset looks idle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DIY:&lt;/strong&gt; if you're at a desk on power, &lt;code&gt;caffeinate -i&lt;/code&gt; in another terminal (or &lt;code&gt;caffeinate -w &amp;lt;pid&amp;gt;&lt;/code&gt; for the Claude process) blocks idle sleep for as long as Claude runs. Closing the lid on battery is different — macOS sleeps on lid close unless you're in clamshell mode with an external display, and the only switch for that is &lt;code&gt;sudo pmset -a disablesleep 1&lt;/code&gt; (remember to set it back to &lt;code&gt;0&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Know when the wait starts and ends.&lt;/strong&gt; Claude Code's hooks tell you exactly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;StopFailure&lt;/code&gt; with &lt;code&gt;"error": "rate_limit"&lt;/code&gt; fires when a turn ends because of a rate limit.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Notification&lt;/code&gt; with &lt;code&gt;notification_type&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;quota_auto_resume_fired&lt;/code&gt; — Claude continued after the reset&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;quota_auto_resume_stale&lt;/code&gt; — the reset happened while the computer slept for 30+ minutes; it's waiting for Enter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;quota_auto_resume_disabled&lt;/code&gt; — the wait ended without continuing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A minimal logger to see it happen:&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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"StopFailure"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rate_limit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$(date) limit hit&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;gt;&amp;gt; ~/claude-limit.log"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quota_auto_resume_fired|quota_auto_resume_stale|quota_auto_resume_disabled"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cat &amp;gt;&amp;gt; ~/claude-limit.log"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With those two signals you can keep the Mac awake from the &lt;code&gt;rate_limit&lt;/code&gt; stop until &lt;code&gt;quota_auto_resume_fired&lt;/code&gt; (or a few minutes past the 5-hour window), and let it sleep otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did in Lidnight
&lt;/h2&gt;

&lt;p&gt;I build &lt;a href="https://lidnight.app/en/" rel="noopener noreferrer"&gt;Lidnight&lt;/a&gt;, a menu bar app that keeps a MacBook awake with the lid closed while AI agents work and lets it sleep when they're done. It installs the &lt;code&gt;StopFailure&lt;/code&gt; hook too: when Claude Code stops on a rate limit, the session shows &lt;strong&gt;"limit · resumes in 2h 14m"&lt;/strong&gt; and the Mac stays awake through a 5-hour wait, so the automatic continue actually happens. &lt;code&gt;quota_auto_resume_fired&lt;/code&gt; puts it back to "working".&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update (Oct 17):&lt;/em&gt; for the cases Claude Code won't continue on its own — a weekly limit, a &lt;code&gt;stale&lt;/code&gt;/&lt;code&gt;disabled&lt;/code&gt; wait, or Codex — Lidnight now sends a one-line "please continue" after the reset through official features (Claude Code's cross-session messaging, &lt;code&gt;codex queue&lt;/code&gt;). You choose per AI whether that should happen; set it to "paused" and the session stays stopped.&lt;/p&gt;

&lt;p&gt;The same docs pass also turned up two notification types I now count as "waiting for you": &lt;code&gt;elicitation_url_dialog&lt;/code&gt; (an MCP server asks you to open a URL) and &lt;code&gt;agent_needs_input&lt;/code&gt; (a background session needs input). And a reader on Qiita pointed out a subtle one: a sandboxed command's &lt;strong&gt;network-access prompt doesn't run &lt;code&gt;PermissionRequest&lt;/code&gt; hooks&lt;/strong&gt; — only the &lt;code&gt;permission_prompt&lt;/code&gt; notification catches it (after about six seconds). If you approve prompts from a hook, keep a &lt;code&gt;Notification&lt;/code&gt; hook around too.&lt;/p&gt;

&lt;p&gt;Lidnight is free with the lid open (AI Auto mode, you turn it on); Pro keeps going with the lid closed, even on battery, and adds auto-start, phone approvals and more — a one-time $9.99 (50% off through Oct 31) with a 7-day trial. &lt;code&gt;brew install whereisdw/tap/lidnight&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sources: &lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code hooks reference&lt;/a&gt; · &lt;a href="https://code.claude.com/docs/en/interactive-mode#wait-for-a-usage-limit-to-reset" rel="noopener noreferrer"&gt;Wait for a usage limit to reset&lt;/a&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>macos</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I keep long Claude Code runs alive with my MacBook lid closed</title>
      <dc:creator>Dawon Lee</dc:creator>
      <pubDate>Tue, 13 Oct 2026 23:54:59 +0000</pubDate>
      <link>https://dev.to/dawonlee/how-i-keep-long-claude-code-runs-alive-with-my-macbook-lid-closed-900</link>
      <guid>https://dev.to/dawonlee/how-i-keep-long-claude-code-runs-alive-with-my-macbook-lid-closed-900</guid>
      <description>&lt;p&gt;I hand Claude Code a lot of long tasks: a refactor across a package, a test suite to fix, a migration that takes a while. The point is to walk away while it works. So I'd start the run, close my MacBook, and leave.&lt;/p&gt;

&lt;p&gt;Then I'd come back to a session that had stalled a few minutes in.&lt;/p&gt;

&lt;p&gt;This post covers why that happens, what you can do about it with built-in macOS commands, where those commands fall short, and the small menu bar app I ended up building. If you only want the commands, the first half is for you. You don't need the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why closing the lid kills the run
&lt;/h2&gt;

&lt;p&gt;When a Mac sleeps, Claude Code in your terminal stops too. The network drops, API requests fail, and the agent sits there until you wake the machine. Two things cause it: idle sleep (you step away long enough), and lid-close sleep (you shut the laptop).&lt;/p&gt;

&lt;p&gt;macOS sleeps the Mac when you close the lid. The one built-in exception is clamshell mode, and that needs a power adapter, an external display, and an external keyboard or mouse all connected. Fine at a desk. Useless in a café, on a train, or when you just want to carry the laptop to another room.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;caffeinate&lt;/code&gt; isn't enough
&lt;/h2&gt;

&lt;p&gt;The first thing most of us try is &lt;code&gt;caffeinate&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# keep the Mac awake while one command runs&lt;/span&gt;
caffeinate &lt;span class="nt"&gt;-i&lt;/span&gt; your-command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a good tool and I still use it for short jobs. But &lt;code&gt;caffeinate&lt;/code&gt;, keep-awake apps, and the "Prevent automatic sleeping when the display is off" setting all target &lt;strong&gt;idle sleep&lt;/strong&gt;. Lid-close sleep works separately, so in most setups the Mac still sleeps when you close it, and on battery with no external display it definitely does.&lt;/p&gt;

&lt;p&gt;There's also a workflow problem. You have to remember to wrap every run, and an interactive Claude Code session isn't really "one command that exits."&lt;/p&gt;

&lt;h2&gt;
  
  
  The command that actually works: &lt;code&gt;pmset disablesleep&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The setting that also disables lid-close sleep is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# disable sleep entirely, including when the lid closes&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;pmset &lt;span class="nt"&gt;-a&lt;/span&gt; disablesleep 1

&lt;span class="c"&gt;# turn sleep back on&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;pmset &lt;span class="nt"&gt;-a&lt;/span&gt; disablesleep 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works. With it set, you can close the lid on battery and the Mac keeps running.&lt;/p&gt;

&lt;p&gt;It also has real risks, and they're why I didn't want to just leave it on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It's easy to forget to undo.&lt;/strong&gt; The agent finishes at 2 AM and your Mac keeps running. On battery, that means it drains.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The setting even survives a restart.&lt;/strong&gt; It's not tied to a session or a process. Whatever state you left it in stays until you change it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heat.&lt;/strong&gt; A MacBook that's awake and closed still makes heat. On a hard surface it vents from the bottom and back, which is fine. In a bag or under a blanket, it can't. A Mac you &lt;em&gt;think&lt;/em&gt; is asleep in your backpack is the worst case.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you go the DIY route, at least tie it to the job so it can't outlive it. A small wrapper with a &lt;code&gt;trap&lt;/code&gt; turns sleep back on even if you Ctrl-C:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/zsh&lt;/span&gt;
&lt;span class="c"&gt;# awake-run: keep the Mac awake (lid closed too) only while a command runs&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;pmset &lt;span class="nt"&gt;-a&lt;/span&gt; disablesleep 1
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;'sudo pmset -a disablesleep 0'&lt;/span&gt; EXIT INT TERM
&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;awake-run claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This still won't protect you from heat, a dying battery, or a crash that skips the trap, and you'll want to check the current state now and then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pmset &lt;span class="nt"&gt;-g&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;sleep&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it's much better than leaving &lt;code&gt;disablesleep 1&lt;/code&gt; on and hoping you remember.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowing when the agent is &lt;em&gt;actually&lt;/em&gt; done
&lt;/h2&gt;

&lt;p&gt;The wrapper keeps the Mac awake for as long as the process lives. That's not the same as "while Claude is working." An interactive session can sit idle for hours after the task ends, and keeping the Mac awake all that time is just the "forgot to undo it" problem in another form.&lt;/p&gt;

&lt;p&gt;Claude Code has hooks that fire on real events. A &lt;code&gt;Stop&lt;/code&gt; hook runs when a task ends, and a &lt;code&gt;Notification&lt;/code&gt; hook runs when Claude is waiting for your input or permission. Even without any app, you can get a macOS notification for both by putting this 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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Stop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"osascript -e 'display notification &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Claude Code finished&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; with title &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Claude Code&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"osascript -e 'display notification &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Claude Code needs you&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; with title &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Claude Code&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have a settings file, merge in just the &lt;code&gt;hooks&lt;/code&gt; key. It applies to sessions started afterwards.&lt;/p&gt;

&lt;p&gt;The limits: you only see those notifications at your Mac, you still have to go back to the terminal to see &lt;em&gt;what&lt;/em&gt; needs approval, and if the Mac has gone to sleep, the work has stopped anyway.&lt;/p&gt;

&lt;p&gt;Hooks are the right signal, though. They tell you exactly when work starts and ends instead of guessing. That's what I built on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built: Lidnight
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://lidnight.app/en/" rel="noopener noreferrer"&gt;Lidnight&lt;/a&gt; is a macOS menu bar app that puts those pieces together. It uses the same &lt;code&gt;disablesleep&lt;/code&gt; mechanism, but it turns it on and off for you based on whether AI work is actually running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detection.&lt;/strong&gt; When you turn on Claude Code in Settings › Agents, Lidnight adds Claude Code hooks for task start and end, so it knows exactly when Claude is working. Your settings file is backed up first, and turning it off removes only Lidnight's entries. Codex is integrated the same way. Other tools (Gemini CLI, Kiro CLI, Aider, Ollama, LM Studio, and others, 44 in total) are estimated from process activity, plus GPU use for local models. Multiple sessions are tracked separately, and the Mac sleeps only after the last one finishes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Going back to sleep.&lt;/strong&gt; In AI Auto mode, once everything has been quiet for 10 minutes, the Mac goes back to sleep normally. When it's unclear whether work is still going, it stays awake. I chose not cutting a run short over saving a few minutes of battery. There's also a Timer mode and an Until mode for tools it can't detect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The risks from above.&lt;/strong&gt; These are what I most wanted handled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the battery stays above 42°C for over a minute, you get an alert. At 45°C, the Mac goes to sleep. It also sleeps when the battery hits a floor you set.&lt;/li&gt;
&lt;li&gt;If the app is force-quit, a watchdog process restores sleep settings. After a sudden power loss, they're restored at the next boot.&lt;/li&gt;
&lt;li&gt;It only undoes what it changed: sleep prevention, Low Power and performance modes, fan control, and brightness all go back to their previous values.&lt;/li&gt;
&lt;li&gt;Changing the setting needs admin rights, so it installs a small helper that only runs a fixed list of sleep, battery power mode, and fan commands. You can remove it in Settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To be clear about heat: the temperature cutoff is a safety net, not permission to put a running Mac in a bag. Keep it on a hard, ventilated surface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lid behavior.&lt;/strong&gt; The default, "Agents use screen," keeps the display on at zero brightness without locking, so agents that control the screen keep working. That also means the session is &lt;strong&gt;unlocked&lt;/strong&gt; while the lid is closed. If you don't want that, pick "Screen off," which turns the display off and locks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approving permission prompts without going back to the terminal
&lt;/h2&gt;

&lt;p&gt;The other way a long run stalls is Claude stopping to ask "Can I run this?" while you're away.&lt;/p&gt;

&lt;p&gt;Lidnight's hook shows what Claude wants to do (the command, the file it will edit, or the URL) and lets you allow or deny it from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a card in the menu bar window, buttons on the macOS notification, or a small bunny that shows up just left of the notch only while an agent is waiting (free)&lt;/li&gt;
&lt;li&gt;your phone, through the free ntfy app, after linking once with a QR code and no account (Pro)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The normal terminal prompt still appears, and whichever answers first wins.&lt;/p&gt;

&lt;p&gt;Approving from a phone is the part I was most careful with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Push notifications never include the command.&lt;/li&gt;
&lt;li&gt;The status page is encrypted end to end on the Mac (AES-GCM), and the key reaches your phone only through the QR code, so the relay server can't read it.&lt;/li&gt;
&lt;li&gt;Allow and deny are one-time HMAC signatures. They expire and only work for that one request, so a copied one can't be replayed.&lt;/li&gt;
&lt;li&gt;Hard-to-undo commands like &lt;code&gt;rm -rf&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt;, or &lt;code&gt;sudo&lt;/code&gt; can't be allowed from the phone at all. Those stay Mac-only.&lt;/li&gt;
&lt;li&gt;Phone commands only reach a Mac that's awake, and anything more than 10 minutes late is ignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setup: turn on Claude Code in Settings › Agents, make sure "Approve from anywhere" is on (it's the default), and for your phone, turn on phone alerts in Settings › Alerts and scan the QR code. Claude sessions that were already open need one restart to pick it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smaller things that came along
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A bunny per agent in the menu bar that runs faster as tokens flow, and gets an amber dot when an agent is waiting for approval.&lt;/li&gt;
&lt;li&gt;Claude and Codex 5-hour and weekly limits with reset times, plus token counts and estimated API-price cost by model and project, all read from local logs. These are estimates, not your actual bill.&lt;/li&gt;
&lt;li&gt;A CLI (&lt;code&gt;lidnight start&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;doctor&lt;/code&gt;) so an agent can switch it on itself before a long job. &lt;code&gt;lidnight doctor&lt;/code&gt; checks the helper, sleep prevention, hooks, approvals, and phone link, one line each.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no account, and your code and conversations never leave the Mac. The app sends only five anonymous daily counts (no device or ID), and you can turn that off in Settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, or just use the commands
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;caffeinate -i&lt;/code&gt; for short jobs and the &lt;code&gt;pmset&lt;/code&gt; wrapper for long ones cover what you need, use those. They're free and they work.&lt;/p&gt;

&lt;p&gt;If you'd rather not think about it, Lidnight is at &lt;strong&gt;&lt;a href="https://lidnight.app/en/" rel="noopener noreferrer"&gt;https://lidnight.app/en/&lt;/a&gt;&lt;/strong&gt;, or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;whereisdw/tap/lidnight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It needs an Apple Silicon MacBook on macOS 13 or later. The free tier includes AI Auto mode with the lid open, battery and heat protection, and approvals on the Mac. Pro is a one-time $9.99 for one Mac ($14.99 for three; 50% off through Oct 31), no subscription, and adds keeping going with the lid closed (even on battery), phone alerts and approvals, auto-start when AI work begins, fan boost, and longer stats. Every download includes a 7-day Pro trial with no payment details needed, and there's a 14-day refund.&lt;/p&gt;

&lt;p&gt;Getting lid-closed sleep right was more subtle than I expected. If you've hit edge cases with &lt;code&gt;pmset&lt;/code&gt;, clamshell mode, or hooks, I'd like to hear about them in the comments.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>macos</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
