osascript-subprocess
NSTask via JXA ObjC bridge — full POSIX process control from within osascript. All scripts are Python with JXA embedded as strings.
NSTask vs doShellScript
doShellScript |
NSTask | |
|---|---|---|
| Execution | Synchronous, blocks | Sync or async |
| stderr | Merged or lost | Separate NSPipe |
| stdin | None | NSPipe — writable |
| Kill process | Cannot | task.terminate() |
| Exit code | Only via error | task.terminationStatus |
| Long-running | Blocks script | Background option |
Use doShellScript for quick one-liners. Use NSTask when you need stderr, stdin, kill, or async.
PATH Note
uv lives in /opt/homebrew/bin. Always set PATH explicitly in NSTask — it does not inherit shell PATH:
task.environment = $.NSDictionary.dictionaryWithObjectsAndKeys(
$("/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"), $("PATH"),
...
);
Use /usr/bin/env as launchPath with ["uv", "run", ...] as arguments — lets env resolve uv from PATH.
Scripts
Run any shell command via NSTask — returns {stdout, stderr, exitCode}:
uv run scripts/run-command.py "ls -la /tmp"
uv run scripts/run-command.py "ping -c 3 google.com"
Run a uv run Python script via NSTask with proper PATH resolution:
uv run scripts/run-uv-script.py /path/to/script.py arg1 arg2
Reference
- reference/21-nstask.md — Full NSTask API, stdin/stdout/stderr pipes, async, kill, env vars, uv pattern
- reference/01-languages-and-execution.md — Python wrapper patterns, doShellScript vs NSTask decision