@bastani/atomic 0.6.0-0 → 0.6.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -87,6 +87,7 @@ bun install -g @bastani/atomic
87
87
  ```
88
88
 
89
89
  This skips the Bun install step but doesn't set up shell completions — run `atomic completions <shell>` separately if you want them (see [Commands Reference](#atomic-completions--shell-completions)).
90
+ If your shell cannot find `atomic` after the install, add the directory from `bun pm bin -g` to your PATH or use the bootstrap installer above to do it automatically.
90
91
 
91
92
  **Prerelease builds:** `bun install -g @bastani/atomic@next` (may contain breaking changes).
92
93
 
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Shared spawn utilities for postinstall and lifecycle scripts.
3
+ *
4
+ * Provides a thin async wrapper around Bun.spawn and a PATH-prepend helper,
5
+ * eliminating duplication across postinstall-playwright, postinstall-liteparse, etc.
6
+ */
7
+ export interface SpawnResult {
8
+ success: boolean;
9
+ details: string;
10
+ stdout?: string;
11
+ stderr?: string;
12
+ }
13
+ export interface RunCommandOptions {
14
+ /** When true, stdout/stderr are inherited so the user sees live output. */
15
+ inherit?: boolean;
16
+ }
17
+ /**
18
+ * Run a command asynchronously and collect its output.
19
+ * Returns a result object instead of throwing on failure.
20
+ *
21
+ * When `inherit` is true, output streams directly to the terminal so the
22
+ * user can follow installation progress in real time.
23
+ */
24
+ export declare function runCommand(cmd: string[], options?: RunCommandOptions): Promise<SpawnResult>;
25
+ /**
26
+ * Prepend a directory to the PATH environment variable (if not already present).
27
+ */
28
+ export declare function prependPath(directory: string): void;
29
+ export declare function resolveCommandFromCurrentPath(cmd: string): string | null;
30
+ export type MuxBinaryName = "tmux" | "psmux" | "pmux";
31
+ export declare function requiredMuxBinaryCandidatesForPlatform(platform?: NodeJS.Platform): MuxBinaryName[];
32
+ export declare function isMuxBinaryRequiredForPlatform(binary: MuxBinaryName, platform?: NodeJS.Platform): boolean;
33
+ export declare function hasRequiredMuxBinary(): boolean;
34
+ export declare function psmuxReleaseAssetSuffix(arch?: NodeJS.Architecture): string | null;
35
+ /**
36
+ * Get the user's home directory.
37
+ * Uses Node.js os.homedir() which handles cross-platform resolution
38
+ * (HOME on Unix, USERPROFILE on Windows, and fallback to passwd on Linux).
39
+ */
40
+ export declare function getHomeDir(): string;
41
+ /**
42
+ * Options for the user-facing ensure* installers.
43
+ *
44
+ * `quiet: true` captures subprocess output instead of streaming it to the
45
+ * terminal, so a higher-level spinner UI (see auto-sync's `runSteps`) can
46
+ * own the display. Failures collected in the captured buffer are thrown
47
+ * out of the ensure* function so the spinner can mark the step red and
48
+ * surface the captured tail in its summary.
49
+ *
50
+ * Default (`quiet: false`) preserves the historical inherit-stdout
51
+ * behavior used by the ad-hoc fallbacks in chat.ts / workflow.ts.
52
+ */
53
+ export interface EnsureOptions {
54
+ quiet?: boolean;
55
+ }
56
+ /**
57
+ * Install one or more global packages via a single `bun install -g` call.
58
+ * Uses `--trust` to allow postinstall lifecycle scripts (required by
59
+ * packages like @playwright/cli).
60
+ *
61
+ * Combining multiple packages into one invocation is important: Bun's
62
+ * global linker is not safe to run concurrently — two parallel
63
+ * `bun install -g` processes race to create the same symlinks in the
64
+ * shared global store, causing EEXIST errors for transitive deps that
65
+ * both packages (or the already-installed @bastani/atomic) share.
66
+ */
67
+ export declare function upgradeGlobalPackages(pkgs: string[]): Promise<void>;
68
+ /** Upgrade @playwright/cli and @llamaindex/liteparse globally in one pass. */
69
+ export declare function upgradeGlobalToolPackages(): Promise<void>;
70
+ /**
71
+ * Ensure a terminal multiplexer (tmux on Unix, psmux on Windows) is installed.
72
+ * No-op when already present on PATH.
73
+ *
74
+ * When `quiet: true`, subprocess output is captured instead of inherited
75
+ * so an outer spinner UI owns the display. On failure the captured tail
76
+ * is re-thrown as the error message.
77
+ */
78
+ export declare function ensureTmuxInstalled(options?: EnsureOptions): Promise<void>;
79
+ /**
80
+ * Ensure bun is installed and available on PATH.
81
+ * No-op when already present.
82
+ */
83
+ export declare function ensureBunInstalled(): Promise<void>;
84
+ /**
85
+ * Ensure tmux/psmux is installed. Used as a ToolingStep in the update pipeline.
86
+ * Does not attempt version upgrades — just ensures the tool exists.
87
+ */
88
+ export declare function upgradeTmux(): Promise<void>;
89
+ /**
90
+ * Upgrade bun to the latest version, or install if missing.
91
+ */
92
+ export declare function upgradeBun(): Promise<void>;
93
+ export declare class ToolingSetupError extends Error {
94
+ readonly failures: string[];
95
+ constructor(failures: string[]);
96
+ }
97
+ export interface ToolingStep {
98
+ label: string;
99
+ fn: () => Promise<unknown>;
100
+ }
101
+ export declare function collectFailures(steps: ToolingStep[], results: PromiseSettledResult<unknown>[]): string[];
102
+ //# sourceMappingURL=spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/lib/spawn.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAuCjG;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAUnD;AAMD,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAExE;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtD,wBAAgB,sCAAsC,CACpD,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,aAAa,EAAE,CAEjB;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,aAAa,EACrB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,OAAO,CAET;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAI9C;AAkHD,wBAAgB,uBAAuB,CACrC,IAAI,GAAE,MAAM,CAAC,YAA2B,GACvC,MAAM,GAAG,IAAI,CAWf;AA0HD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzE;AAED,8EAA8E;AAC9E,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/D;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6GpF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAoExD;AAED;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAUhD;AAMD,qBAAa,iBAAkB,SAAQ,KAAK;aACd,QAAQ,EAAE,MAAM,EAAE;gBAAlB,QAAQ,EAAE,MAAM,EAAE;CAQ/C;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAAE,EACpB,OAAO,EAAE,oBAAoB,CAAC,OAAO,CAAC,EAAE,GACvC,MAAM,EAAE,CAaV"}
@@ -1 +1 @@
1
- {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/sdk/providers/claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/sdk/providers/claude.ts"],"names":[],"mappings":"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"}
@@ -13,5 +13,19 @@
13
13
  * so it can't be used here.
14
14
  */
15
15
  import type { AgentType } from "../types.ts";
16
+ export declare function resolveAttachedFooterCliPath(runtimeDir?: string, platform?: NodeJS.Platform): string;
17
+ export declare function buildAttachedFooterCommand({ runtime, cliPath, windowName, agentType, platform, }: {
18
+ runtime: string;
19
+ cliPath: string;
20
+ windowName: string;
21
+ agentType?: AgentType;
22
+ platform?: NodeJS.Platform;
23
+ }): string;
24
+ export declare function buildAttachedFooterCloseHooks(agentPaneId: string, footerPaneId: string, options?: {
25
+ guardAgentPane?: boolean;
26
+ }): Array<{
27
+ event: string;
28
+ command: string;
29
+ }>;
16
30
  export declare function spawnAttachedFooter(windowName: string, paneId: string, agentType?: AgentType): void;
17
31
  //# sourceMappingURL=attached-footer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attached-footer.d.ts","sourceRoot":"","sources":["../../../src/sdk/runtime/attached-footer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAiB7C,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,SAAS,GACpB,IAAI,CA4BN"}
1
+ {"version":3,"file":"attached-footer.d.ts","sourceRoot":"","sources":["../../../src/sdk/runtime/attached-footer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA6B7C,wBAAgB,4BAA4B,CAC1C,UAAU,SAAkB,EAC5B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,CAIR;AAED,wBAAgB,0BAA0B,CAAC,EACzC,OAAO,EACP,OAAO,EACP,UAAU,EACV,SAAS,EACT,QAA2B,GAC5B,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,GAAG,MAAM,CAoBT;AAED,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GACzC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAU3C;AAOD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,SAAS,GACpB,IAAI,CAyCN"}
@@ -19,7 +19,9 @@ export type TmuxResult = {
19
19
  /**
20
20
  * Resolve the terminal multiplexer binary for the current platform.
21
21
  *
22
- * On Windows, tries psmux → pmux tmux (psmux ships all three as aliases).
22
+ * On Windows, tries psmux → pmux. Do not accept arbitrary `tmux.exe` because
23
+ * that can be a non-native shim and would prevent the psmux installer from
24
+ * running.
23
25
  * On Unix/macOS, uses tmux directly.
24
26
  *
25
27
  * Returns the binary name (not the full path) or null if none is found.
@@ -65,17 +67,24 @@ export declare function tmuxRun(args: string[]): TmuxResult;
65
67
  * @returns The pane ID of the initial pane (e.g., "%0")
66
68
  */
67
69
  export declare function createSession(sessionName: string, initialCommand: string, windowName?: string, cwd?: string, envVars?: Record<string, string>): string;
68
- /**
69
- * Install a hook that kills the entire session when the given pane's
70
- * process exits. Used by chat sessions so the session is torn down
71
- * when the agent CLI exits — whether via `/exit`, a deliberate double
72
- * Ctrl+C, or a crash — without leaving the footer pane keeping the
73
- * session alive.
70
+ export declare function buildKillSessionOnPaneExitHooks(sessionName: string, paneId: string, options?: {
71
+ guardPaneExited?: boolean;
72
+ }): Array<{
73
+ event: string;
74
+ command: string;
75
+ }>;
76
+ /**
77
+ * Install hooks that kill the entire session when the agent pane goes away.
78
+ * Used by chat sessions so the session is torn down when the agent CLI exits
79
+ * — whether via `/exit`, a deliberate double Ctrl+C, a crash, or a direct
80
+ * pane close — without leaving the footer pane keeping the session alive.
74
81
  *
75
- * The hook is session-scoped (pane-scoped hooks don't fire because the
76
- * pane is already gone when `pane-exited` would run) and guarded with
77
- * `#{hook_pane}` so the footer pane's eventual exit cascade doesn't
78
- * re-trigger it. `kill-session` is idempotent in any case.
82
+ * tmux fires `pane-exited` when a pane process exits; psmux also supports
83
+ * that event, but does not currently populate tmux's `#{hook_pane}` format,
84
+ * so the psmux hook is session-scoped. A direct pane close/kill fires
85
+ * `after-kill-pane` instead. These session-scoped hooks are safe for chat
86
+ * sessions: they only have the agent pane plus its footer, and closing either
87
+ * should close the entire chat window.
79
88
  */
80
89
  export declare function killSessionOnPaneExit(sessionName: string, paneId: string): void;
81
90
  /**
@@ -165,6 +174,7 @@ export declare function sessionExists(sessionName: string): boolean;
165
174
  * the individual session, not the global server environment.
166
175
  */
167
176
  export declare function setSessionEnv(sessionName: string, key: string, value: string): void;
177
+ export declare function parseSessionEnvValue(stdout: string, key: string): string | null;
168
178
  /**
169
179
  * Read a session-level environment variable.
170
180
  * Returns `null` when the session doesn't exist or the variable isn't set.
@@ -201,6 +211,7 @@ export interface TmuxSession {
201
211
  /** Agent backend that owns this session (e.g. "claude", "copilot", "opencode") */
202
212
  agent?: string;
203
213
  }
214
+ export declare function parseListSessionsOutput(stdout: string, getEnv?: (sessionName: string, key: string) => string | null): TmuxSession[];
204
215
  /**
205
216
  * List all sessions on the atomic tmux socket.
206
217
  *
@@ -1 +1 @@
1
- {"version":3,"file":"tmux.d.ts","sourceRoot":"","sources":["../../../src/sdk/runtime/tmux.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tmux.d.ts","sourceRoot":"","sources":["../../../src/sdk/runtime/tmux.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/atomic",
3
- "version": "0.6.0-0",
3
+ "version": "0.6.1-0",
4
4
  "description": "Configuration management CLI and SDK for coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,60 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { buildLauncherScript } from "./index.ts";
3
+
4
+ function withMockPlatform<T>(platform: NodeJS.Platform, fn: () => T): T {
5
+ const originalPlatform = process.platform;
6
+ Object.defineProperty(process, "platform", {
7
+ configurable: true,
8
+ value: platform,
9
+ });
10
+ try {
11
+ return fn();
12
+ } finally {
13
+ Object.defineProperty(process, "platform", {
14
+ configurable: true,
15
+ value: originalPlatform,
16
+ });
17
+ }
18
+ }
19
+
20
+ describe("buildLauncherScript", () => {
21
+ test("builds a PowerShell launcher with cwd, env, args, and exit code", () => {
22
+ const { script, ext } = withMockPlatform("win32", () =>
23
+ buildLauncherScript(
24
+ "copilot",
25
+ ["--debug"],
26
+ "C:\\repo",
27
+ { ATOMIC_AGENT: "copilot" },
28
+ )
29
+ );
30
+
31
+ expect(ext).toBe("ps1");
32
+ expect(script).toContain('Set-Location "C:\\repo"');
33
+ expect(script).toContain('$env:ATOMIC_AGENT = "copilot"');
34
+ expect(script).toContain('& "copilot" @("--debug")');
35
+ expect(script).toContain('if ($LASTEXITCODE -is [int]) { $atomicExitCode = $LASTEXITCODE }');
36
+ expect(script).toContain("exit $atomicExitCode");
37
+ expect(script).not.toContain("Invoke-AtomicSessionCleanup");
38
+ });
39
+
40
+ test("builds a bash launcher without tmux input suppression", () => {
41
+ const { script, ext } = withMockPlatform("linux", () =>
42
+ buildLauncherScript(
43
+ "claude",
44
+ ["--dangerously-skip-permissions"],
45
+ "/repo",
46
+ { ATOMIC_AGENT: "claude" },
47
+ )
48
+ );
49
+
50
+ expect(ext).toBe("sh");
51
+ expect(script).toContain('cd "/repo"');
52
+ expect(script).toContain('export ATOMIC_AGENT="claude"');
53
+ expect(script).toContain('"claude" "--dangerously-skip-permissions"');
54
+ expect(script).toContain("atomic_exit_code=$?");
55
+ expect(script).not.toContain("exec ");
56
+ expect(script).not.toContain("stty -echo -icanon");
57
+ expect(script).not.toContain("atomic_original_tty_state");
58
+ expect(script).not.toContain("trap atomic_cleanup");
59
+ });
60
+ });
@@ -2,10 +2,7 @@
2
2
  /**
3
3
  * Chat CLI command for atomic
4
4
  *
5
- * Spawns the native agent CLI as an interactive subprocess.
6
- * When already inside a tmux/psmux session, the agent spawns inline
7
- * in the current pane. When outside tmux, it creates a new tmux
8
- * session and attaches to it.
5
+ * Spawns the native agent CLI in tmux/psmux with an OpenTUI footer pane.
9
6
  *
10
7
  * All extra arguments after `-a <agent>` are forwarded to the native CLI.
11
8
  *
@@ -36,9 +33,8 @@ import {
36
33
  import {
37
34
  createSession,
38
35
  detachAndAttachAtomic,
39
- killSession,
40
36
  killSessionOnPaneExit,
41
- setSessionEnv,
37
+ killSession,
42
38
  spawnMuxAttach,
43
39
  switchClient,
44
40
  } from "../../../sdk/workflows/index.ts";
@@ -113,7 +109,7 @@ function escPwsh(s: string): string {
113
109
  * Build a launcher script that preserves cwd and properly quotes args.
114
110
  * This avoids shell-injection risks from passthrough args.
115
111
  */
116
- function buildLauncherScript(
112
+ export function buildLauncherScript(
117
113
  cmd: string,
118
114
  args: string[],
119
115
  projectRoot: string,
@@ -134,6 +130,9 @@ function buildLauncherScript(
134
130
  argList.length > 0
135
131
  ? `& "${escPwsh(cmd)}" @(${argList})`
136
132
  : `& "${escPwsh(cmd)}"`,
133
+ "$atomicExitCode = 0",
134
+ "if ($LASTEXITCODE -is [int]) { $atomicExitCode = $LASTEXITCODE }",
135
+ "exit $atomicExitCode",
137
136
  ].join("\n");
138
137
  return { script, ext: "ps1" };
139
138
  }
@@ -145,21 +144,13 @@ function buildLauncherScript(
145
144
  const envLines = envEntries.map(
146
145
  ([key, value]) => `export ${key}="${escBash(value)}"`,
147
146
  );
148
- // Pre-silence the tty before exec'ing the agent. copilot and opencode
149
- // write terminal-capability probes (CSI ?Pn $p, OSC 4;0;?, CSI c) to
150
- // stdout at startup; under tmux the DECRPM / OSC 4 / DA1 replies arrive
151
- // on stdin a few ms later. If the agent hasn't enabled raw mode yet,
152
- // the tty driver echoes those replies back to the screen as garbage
153
- // (e.g. `^[[?1016;2$y^[[?2004;1$y^[]4;0;rgb:...`). Disabling echo and
154
- // canonical mode here means the driver drops them silently; the agent's
155
- // own termios setup then takes over once it's ready. Redirected stdin
156
- // (no tty) harmlessly no-ops the stty call.
157
147
  const script = [
158
148
  "#!/bin/bash",
159
149
  `cd "${escBash(projectRoot)}"`,
160
150
  ...envLines,
161
- "stty -echo -icanon 2>/dev/null || true",
162
- `exec "${escBash(cmd)}" ${quotedArgs}`,
151
+ `"${escBash(cmd)}" ${quotedArgs}`,
152
+ "atomic_exit_code=$?",
153
+ 'exit "$atomic_exit_code"',
163
154
  ].join("\n");
164
155
  return { script, ext: "sh" };
165
156
  }
@@ -221,9 +212,7 @@ export async function chatCommand(options: ChatCommandOptions = {}): Promise<num
221
212
  const cmd = [config.cmd, ...args];
222
213
  const overrides = await getProviderOverrides(agentType, projectRoot);
223
214
  // ATOMIC_AGENT must be baked into the launcher env so the agent CLI
224
- // (and anything it spawns) can read it. `setSessionEnv` below only
225
- // affects processes spawned *after* the initial command, so it cannot
226
- // populate the env of the agent CLI that `new-session` kicks off.
215
+ // and anything it spawns can read it from process start.
227
216
  const envVars = {
228
217
  ...config.env_vars,
229
218
  ...overrides.envVars,
@@ -272,19 +261,8 @@ export async function chatCommand(options: ChatCommandOptions = {}): Promise<num
272
261
  // ── Create session on the atomic socket and attach ──
273
262
  try {
274
263
  const paneId = createSession(windowName, shellCmd, undefined, projectRoot);
275
- setSessionEnv(windowName, "ATOMIC_AGENT", agentType);
276
-
277
- // When the agent CLI exits (via `/exit`, double Ctrl+C, or crash),
278
- // tear down the whole session so the footer pane doesn't keep it
279
- // alive in the background. Pane-scoped so the footer's own exit
280
- // (which cascades from the kill-session) doesn't re-trigger.
281
- killSessionOnPaneExit(windowName, paneId);
282
-
283
- // Split the pane so the agent CLI runs on top and the React footer
284
- // (provider pill + window name) runs in a 5% bottom pane. Matches
285
- // the workflow-window layout, minus the keyboard hints (chat sessions
286
- // only host a single agent, so ctrl+g / ctrl+\ navigation is moot).
287
264
  spawnAttachedFooter(windowName, paneId, agentType);
265
+ killSessionOnPaneExit(windowName, paneId);
288
266
 
289
267
  if (isInsideAtomicSocket()) {
290
268
  // Already on the atomic server — just switch to the new session.