ReviewOS

also looking at this

stacks/uplink

fix(app): a fresh install now either works or says why

#8
Merged glennmichael123 wants to merge fix/setup-blockers into main
16 files +512 -75
app/Uplink/agent-path.tsadded+39-0
Changes to app/Uplink/agent-path.ts
@@ -0,0 +1,39 @@
1import { homedir } from 'node:os'
2import { join } from 'node:path'
3import process from 'node:process'
4
5/**
6 * The PATH an Uplink process needs.
7 *
8 * launchd hands agents a bare PATH, and Uplink shells out to `claude`, `codex`,
9 * `git` and `osascript`. The from-source launcher has always built this list;
10 * the downloadable app did not, so a `claude` installed by bun, npm or nvm was
11 * invisible to it on a Mac where it works perfectly in a terminal. Both use
12 * this now, so the two cannot drift.
13 *
14 * The user's own locations come first: Uplink's bundled tools must not shadow
15 * the CLI a person deliberately installed. Whatever PATH already exists is kept
16 * last, so a real environment (a terminal, a debugging session) still wins over
17 * nothing.
18 */
19export function agentPath(options: { appDir?: string, env?: Record<string, string | undefined> } = {}): string {
20 const env = options.env ?? process.env
21 const home = env.HOME ?? homedir()
22
23 return [
24 // Where the installers put the agent CLIs.
25 join(home, '.local', 'bin'),
26 join(home, '.bun', 'bin'),
27 join(home, '.npm-global', 'bin'),
28 join(home, '.claude', 'local'),
29 '/opt/homebrew/bin',
30 '/usr/local/bin',
31 // The from-source install's own pinned toolchain, after the user's.
32 options.appDir ? join(options.appDir, 'pantry', '.bin') : '',
33 '/usr/bin',
34 '/bin',
35 '/usr/sbin',
36 '/sbin',
37 env.PATH ?? '',
38 ].filter(Boolean).join(':')
39}