Repository navigation
SessionTree.readProcs uses macOS-only ps flags and throws on Linux #2470
Description
Version
LifeOS 8.761.0 · attestation: not run
What is broken
SessionTree.readProcs() reads the process table with macOS-only ps flags, so on Linux it throws before returning anything:
Error: Command failed: ps -ww -Axo pid=,ppid=,tty=,etime=,command=
error: must set personality to get -x option
procps-ng rejects BSD -x after a dash (-Axo), and it has no -E for the environment table either (ps -ww -E -Axo pid=,command= → unsupported SysV option). Every caller of readProcs() fails on Linux as a result. The visible one is the LifeOSHooks plugin's session-tree bridge, which logs the error on every pass once the plugin arms. RunningScan, OrphanReaper, HookBridge and Vigil's running adapter go through the same function.
Every other ps call in the tree runs fine on Linux (-o etime= -p, -o command= -p, -axo pid=,ppid=). psOne's -E call only runs on the darwin libc path, so it doesn't fail. The only failing site is the pair at SessionTree.ts:206-207.
Where (file:line)
LIFEOS/TOOLS/SessionTree.ts:206
Repro on a clean tree
# Linux, procps-ng 4.0.4, from the install root:
bun -e 'const m = await import("./LIFEOS/TOOLS/SessionTree.ts"); console.log(m.readProcs().length)'
# → Error: Command failed: ps -ww -Axo pid=,ppid=,tty=,etime=,command=
# the call on its own:
ps -ww -Axo pid=,ppid=,tty=,etime=,command=
# → error: must set personality to get -x option (exit 1)Negative control
Probe: ps -ww -Axo pid=,ppid=,tty=,etime=,command= · exit 1 · captured 2026-10-30T09:01:14.546Z
Red looks like: must set personality
error: must set personality to get -x option
Usage:
ps [options]
Try 'ps --help <simple|list|output|threads|misc|all>'
or 'ps --help <s|l|o|t|m|a>'
for additional help text.
For more details see ps(1).
Suggested fix
On Linux, use -eo for the plain table and the BSD-style e modifier for the environment table (ps axeww -o pid=,command=). procps appends the environment after the command, as macOS -E does, so parseTables reads both tables unchanged. macOS keeps the current flags. We've run this locally since v8.761.0: readProcs() returns 921 processes, and the env-derived fields come back populated (84 with session, 171 with term). The patch is attached.
diff --git a/LIFEOS/TOOLS/SessionTree.ts b/LIFEOS/TOOLS/SessionTree.ts
index 6667c6d7..6d7dee0e 100644
--- a/LIFEOS/TOOLS/SessionTree.ts
+++ b/LIFEOS/TOOLS/SessionTree.ts
@@ -203,8 +203,11 @@ export function readProcs(): Proc[] {
export function readProcsPs(): Proc[] {
const opts = { encoding: "utf8" as const, maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] as ["ignore", "pipe", "ignore"] };
- const plain = execFileSync("ps", ["-ww", "-Axo", "pid=,ppid=,tty=,etime=,command="], opts);
- const env = execFileSync("ps", ["-ww", "-E", "-Axo", "pid=,command="], opts);
+ // Linux procps rejects BSD `-x` after a dash and has no `-E`; its BSD-style `e` modifier appends the
+ // environment after the command the same way, so parseTables reads both tables unchanged.
+ const linux = process.platform === "linux";
+ const plain = execFileSync("ps", linux ? ["-ww", "-eo", "pid=,ppid=,tty=,etime=,command="] : ["-ww", "-Axo", "pid=,ppid=,tty=,etime=,command="], opts);
+ const env = execFileSync("ps", linux ? ["axeww", "-o", "pid=,command="] : ["-ww", "-E", "-Axo", "pid=,command="], opts);
return parseTables(plain, env);
}Environment
- OS: Pop!_OS 24.04 LTS (x64)
- Harness: claude-code
- bun: 1.3.14 · git: 2.56.0
- Doctor broken: none
Activity