1
00:00:00,320 --> 00:00:02,540
Okay, quick one before you close that
terminal.

2
00:00:03,320 --> 00:00:07,040
Thanks to Jellypod to help make this daily
show a reality.

3
00:00:08,340 --> 00:00:13,980
Today is about a bug that bites anyone who
bounces between the Codex CLI and the

4
00:00:14,080 --> 00:00:15,740
Desktop app on one machine.

5
00:00:16,620 --> 00:00:23,340
It builds on 0.164.0, which we covered a
while back for inline model and permission

6
00:00:23,440 --> 00:00:26,720
switching and for saved thread settings on
resume.

7
00:00:27,300 --> 00:00:31,740
Here's the symptom, from issue 57004 on
the Codex GitHub.

8
00:00:32,320 --> 00:00:37,560
A user on macOS, CLI 0.164.0, desktop
build

9
00:00:37,960 --> 00:00:42,320
26.1021.31345, finishes a turn.

10
00:00:42,780 --> 00:00:45,700
The CLI prints "Worked" and there's no
task running.

11
00:00:46,200 --> 00:00:46,680
They exit.

12
00:00:47,100 --> 00:00:51,080
They open the same conversation in the
Desktop app and get a banner that says,

13
00:00:51,380 --> 00:00:53,920
in English, "Open in another application.

14
00:00:54,260 --> 00:00:56,240
Close the conversation there to continue
here."

15
00:00:56,860 --> 00:00:58,540
The reporter's was localized in Chinese.

16
00:00:58,980 --> 00:01:01,500
The only buttons are Retry and Fork chat.

17
00:01:02,175 --> 00:01:05,575
And the CLI's exit message points them the
wrong way.

18
00:01:06,175 --> 00:01:10,995
It says to run codex agents, select the
task, and press x.

19
00:01:11,795 --> 00:01:13,415
The reporter did that repeatedly.

20
00:01:14,195 --> 00:01:18,295
The task already showed as Ready, and the
saved last turn was completed,

21
00:01:18,635 --> 00:01:20,655
with runtime status reporting idle.

22
00:01:21,635 --> 00:01:24,295
Stop is built for cancelling a turn in
progress.

23
00:01:24,975 --> 00:01:29,195
There's no turn in progress, so pressing x
on a Ready task does nothing.

24
00:01:30,055 --> 00:01:33,615
That's the reporter's reading of the
behavior, and it matches what they saw.

25
00:01:34,278 --> 00:01:36,758
So who actually holds the conversation?

26
00:01:37,318 --> 00:01:43,038
The reporter ran lsof and found a specific
process id with a lock file open under

27
00:01:43,098 --> 00:01:47,118
the dot codex directory, in a folder
called thread writer locks,

28
00:01:47,698 --> 00:01:48,858
one file per thread id.

29
00:01:49,478 --> 00:01:55,638
That process was the managed app server
daemon, running out of the 0.164.0 package

30
00:01:56,058 --> 00:01:57,778
under app server daemon releases.

31
00:01:58,398 --> 00:02:01,318
The Desktop app had its own separate app
server process.

32
00:02:01,898 --> 00:02:05,578
So the CLI exited, but the shared daemon
kept the writer lock,

33
00:02:06,018 --> 00:02:08,318
and Desktop's single writer check says no.

34
00:02:09,027 --> 00:02:10,627
Why does the daemon hold on?

35
00:02:11,287 --> 00:02:16,907
The reporter cites the official
unsubscribe documentation, which describes a 30

36
00:02:16,967 --> 00:02:22,607
minute grace period with no subscribers
and no activity before the thread unloads.

37
00:02:23,567 --> 00:02:25,707
They're careful here, and we should be
too.

38
00:02:26,747 --> 00:02:31,607
They rejoined the idle thread over a local
socket, called thread unsubscribe,

39
00:02:31,987 --> 00:02:33,667
and got back "unsubscribed."

40
00:02:34,647 --> 00:02:38,687
About 40 seconds later the thread was
still in the loaded list.

41
00:02:39,547 --> 00:02:41,487
That's consistent with delayed unload.

42
00:02:42,007 --> 00:02:45,847
It doesn't prove the timer is broken, and
it doesn't prove nobody else was

43
00:02:45,887 --> 00:02:46,507
subscribed.

44
00:02:47,547 --> 00:02:51,167
The complaint is that there's no usable
handoff while you wait.

45
00:02:51,840 --> 00:02:52,920
So what do you do today?

46
00:02:53,540 --> 00:02:54,960
Option one, the blunt one.

47
00:02:55,460 --> 00:03:01,540
Issue 56797, a Windows report about a
remote disconnect, says the local Desktop only

48
00:03:01,600 --> 00:03:04,820
unblocked after codex app server daemon
stop.

49
00:03:05,360 --> 00:03:08,140
That works because it kills the process
holding the lock.

50
00:03:08,760 --> 00:03:10,240
But the daemon is shared.

51
00:03:10,760 --> 00:03:15,120
In the 57004 report, other conversations
were running under it,

52
00:03:15,540 --> 00:03:18,620
and the reporter deliberately didn't
restart it for that reason.

53
00:03:19,160 --> 00:03:23,280
Stopping it interrupts everything,
including subagents and background work.

54
00:03:23,840 --> 00:03:27,640
Check codex agents first, and only stop it
if nothing else matters.

55
00:03:28,298 --> 00:03:30,158
Option two is Fork chat.

56
00:03:31,178 --> 00:03:36,218
It gets you a working conversation in
Desktop right away, but it's a new

57
00:03:36,258 --> 00:03:36,858
conversation.

58
00:03:37,718 --> 00:03:43,178
You lose the identity of the original
thread, so anything that refers to the old one

59
00:03:43,418 --> 00:03:44,158
won't follow you.

60
00:03:45,158 --> 00:03:48,838
Fine for a quick follow up, awkward for
long running work.

61
00:03:49,590 --> 00:03:53,190
Option three is prevention, and I want to
flag the confidence level.

62
00:03:53,650 --> 00:03:58,390
The notes we're working from suggest
launching the CLI with the no daemon flag when

63
00:03:58,450 --> 00:04:00,170
you know you're handing off to Desktop.

64
00:04:00,670 --> 00:04:03,910
The idea is an embedded server that dies
with the terminal,

65
00:04:04,150 --> 00:04:05,190
so the lock goes with it.

66
00:04:05,750 --> 00:04:09,630
We haven't seen that confirmed in the
issue itself, so test it on a throwaway thread

67
00:04:09,710 --> 00:04:10,110
first.

68
00:04:11,210 --> 00:04:15,950
Whichever you try, the check is the same:
after you exit, run lsof on the thread's

69
00:04:15,990 --> 00:04:19,090
lock file and see whether a daemon process
still has it open.

70
00:04:19,793 --> 00:04:26,793
On a real fix, the reporter links pull
request 56378, described as a

71
00:04:26,853 --> 00:04:31,113
validated patch for an explicit
unsubscribe writer handoff.

72
00:04:31,893 --> 00:04:33,993
It's still a proposal as of the report.

73
00:04:34,733 --> 00:04:39,033
What they're asking for is a release
operation scoped to one conversation,

74
00:04:39,433 --> 00:04:44,993
separate from stopping a turn, so an idle
writer can be handed over without touching

75
00:04:45,033 --> 00:04:46,653
the daemon or anything else.

76
00:04:47,393 --> 00:04:50,453
Nothing is assigned and nothing is merged
in what we've seen,

77
00:04:50,833 --> 00:04:53,053
so don't plan around it landing next week.

78
00:04:53,695 --> 00:04:55,035
Now the smaller items.

79
00:04:55,535 --> 00:05:02,495
Issue 56850, reported on 0.165.0 alpha 1,
hits people with custom

80
00:05:02,555 --> 00:05:08,835
providers using the responses wire API,
like a llama.cpp style local server.

81
00:05:09,434 --> 00:05:13,295
If a long function call, say a big heredoc
in exec command,

82
00:05:13,875 --> 00:05:19,195
runs past the output budget, the stream
ends as incomplete with reason max output

83
00:05:19,255 --> 00:05:19,655
tokens.

84
00:05:20,275 --> 00:05:25,075
Codex leaves the truncated call in history
and replays it on every later request.

85
00:05:25,715 --> 00:05:29,975
Strict servers that validate the arguments
as JSON then return a 400,

86
00:05:30,435 --> 00:05:31,515
and the thread stays stuck.

87
00:05:31,935 --> 00:05:36,555
The reporter's workaround was having their
bridge send an explicit max output tokens

88
00:05:36,635 --> 00:05:37,695
at the server's maximum.

89
00:05:38,340 --> 00:05:43,480
Another one in the app server area, issue
56781.

90
00:05:44,380 --> 00:05:48,400
Archiving a thread also archives its
spawned subagent threads,

91
00:05:48,940 --> 00:05:51,400
but unarchive restores only the parent.

92
00:05:52,260 --> 00:05:57,880
If you rely on subagents, list the
children after unarchiving and don't assume they

93
00:05:57,940 --> 00:05:58,400
came back.

94
00:05:59,072 --> 00:06:02,312
And two things that did ship in 0.164.0.

95
00:06:02,952 --> 00:06:08,492
Config overrides passed with the c or
config flag are now preserved when they appear

96
00:06:08,552 --> 00:06:12,892
at more than one subcommand level, so they
stop getting silently dropped.

97
00:06:13,492 --> 00:06:18,072
And sandbox checks were hardened for case
variant metadata paths on macOS,

98
00:06:18,572 --> 00:06:21,672
plus replaceable symlinks used to locate
executables.

99
00:06:22,298 --> 00:06:28,818
The practical takeaway: if you end a CLI
session and plan to continue in Desktop,

100
00:06:29,458 --> 00:06:35,378
check codex agents for other live work
before you reach for the daemon stop command.

101
00:06:36,298 --> 00:06:40,798
If the shared daemon is busy, fork or wait
out the grace period.

