( command: string, abortSignal: AbortSignal, shellType: ShellType, options?: ExecOptions, )
| 179 | * Creates a new shell process for each command execution |
| 180 | */ |
| 181 | export async function exec( |
| 182 | command: string, |
| 183 | abortSignal: AbortSignal, |
| 184 | shellType: ShellType, |
| 185 | options?: ExecOptions, |
| 186 | ): Promise<ShellCommand> { |
| 187 | const { |
| 188 | timeout, |
| 189 | onProgress, |
| 190 | preventCwdChanges, |
| 191 | shouldUseSandbox, |
| 192 | shouldAutoBackground, |
| 193 | onStdout, |
| 194 | } = options ?? {} |
| 195 | const commandTimeout = timeout || DEFAULT_TIMEOUT |
| 196 | |
| 197 | const provider = await resolveProvider[shellType]() |
| 198 | |
| 199 | const id = Math.floor(Math.random() * 0x10000) |
| 200 | .toString(16) |
| 201 | .padStart(4, '0') |
| 202 | |
| 203 | // Sandbox temp directory - use per-user directory name to prevent multi-user permission conflicts |
| 204 | const sandboxTmpDir = posixJoin( |
| 205 | process.env.CLAUDE_CODE_TMPDIR || '/tmp', |
| 206 | getClaudeTempDirName(), |
| 207 | ) |
| 208 | |
| 209 | const { commandString: builtCommand, cwdFilePath } = |
| 210 | await provider.buildExecCommand(command, { |
| 211 | id, |
| 212 | sandboxTmpDir: shouldUseSandbox ? sandboxTmpDir : undefined, |
| 213 | useSandbox: shouldUseSandbox ?? false, |
| 214 | }) |
| 215 | |
| 216 | let commandString = builtCommand |
| 217 | |
| 218 | let cwd = pwd() |
| 219 | |
| 220 | // Recover if the current working directory no longer exists on disk. |
| 221 | // This can happen when a command deletes its own CWD (e.g., temp dir cleanup). |
| 222 | try { |
| 223 | await realpath(cwd) |
| 224 | } catch { |
| 225 | const fallback = getOriginalCwd() |
| 226 | logForDebugging( |
| 227 | `Shell CWD "${cwd}" no longer exists, recovering to "${fallback}"`, |
| 228 | ) |
| 229 | try { |
| 230 | await realpath(fallback) |
| 231 | setCwdState(fallback) |
| 232 | cwd = fallback |
| 233 | } catch { |
| 234 | return createFailedCommand( |
| 235 | `Working directory "${cwd}" no longer exists. Please restart Claude from an existing directory.`, |
| 236 | ) |
| 237 | } |
| 238 | } |
no test coverage detected