1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
{
bubblewrap,
coreutils,
lib,
pi-coding-agent,
python3,
runCommand,
symlinkJoin,
writeShellScriptBin,
}:
let
# Patch away the new distracting block-art logo. We're patching dist/
# rather than src to avoid downloading >600MB of npm-deps.
pi-coding-agent-patched = runCommand "${pi-coding-agent.name}-no-logo" { } ''
cp -a ${pi-coding-agent} "$out"
chmod -R u+w "$out"
substituteInPlace "$out/lib/node_modules/pi-monorepo/dist/modes/interactive/components/pi-logo.js" \
--replace-fail 'return !isAppleTerminalSession();' 'return false;' \
--replace-fail 'return `''${foregroundAnsi(CORAL, mode)}P''${RESET}''${foregroundAnsi(YELLOW, mode)}i''${RESET}`;' \
'return theme.bold(theme.fg("accent", "pi"));'
substituteInPlace "$out/lib/node_modules/pi-monorepo/dist/bundle/chunks/chunk-66G7ITPS.js" \
--replace-fail 'function supportsPiLogo(){return!isAppleTerminalSession()}' \
'function supportsPiLogo(){return false}' \
--replace-fail 'function piWordmark(){let mode=theme.getColorMode();return`''${foregroundAnsi(CORAL,mode)}P''${RESET}''${foregroundAnsi(YELLOW,mode)}i''${RESET}`}' \
'function piWordmark(){return theme.bold(theme.fg("accent","pi"))}'
substituteInPlace "$out/bin/pi" "$out/bin/.pi-wrapped" \
--replace-fail '${pi-coding-agent}' "$out"
'';
sbox = writeShellScriptBin "sbox" ''
set -euo pipefail
${coreutils}/bin/mkdir -p /tmp/pi "$HOME/.local/share/cargo-pi"
bwrap_args=(
--die-with-parent
--unshare-pid
--unshare-uts
--unshare-cgroup
--tmpfs /
--dev /dev
--proc /proc
--bind /tmp/pi /tmp
--ro-bind /etc /etc
--bind /nix/store /nix/store
--ro-bind /usr/bin/env /usr/bin/env
--setenv NIX_REMOTE daemon
--bind-try /nix/var/nix/daemon-socket /nix/var/nix/daemon-socket
--dir /run
--ro-bind-try /run/current-system /run/current-system
--ro-bind /doc /doc
--ro-bind "$HOME/.config/git" "$HOME/.config/git"
--ro-bind "$HOME/.config/jj" "$HOME/.config/jj"
--ro-bind "$HOME/repos/config" "$HOME/repos/config"
# jj must be able to write to ~/.config/jj/repos: https://github.com/jj-vcs/jj/issues/8841
--overlay-src "$HOME/.config/jj" --tmp-overlay "$HOME/.config/jj"
--setenv CARGO_HOME "$HOME/.local/share/cargo"
--bind "$HOME/.local/share/cargo-pi" "$HOME/.local/share/cargo"
)
exec ${bubblewrap}/bin/bwrap "''${bwrap_args[@]}" "$@"
'';
pi = writeShellScriptBin "pi" ''
set -euo pipefail
physical_pwd="$(${coreutils}/bin/pwd -P)"
exec ${sbox}/bin/sbox \
--setenv PATH "${lib.makeBinPath [ python3 ]}:$PATH" \
--setenv PI_CODING_AGENT_DIR "$HOME/.config/pi" \
--bind "$HOME/.config/pi" "$HOME/.config/pi" \
--bind "$physical_pwd" "$physical_pwd" \
--chdir "$physical_pwd" \
${pi-coding-agent-patched}/bin/pi \
--append-system-prompt "You're running in a sandbox with an ephemeral root filesystem and a separate PID namespace. The current working directory and a few configuration and cache paths are mounted from the host." \
--append-system-prompt "$HOME/.config/pi/APPEND_SYSTEM.md" \
"$@"
'';
pit = writeShellScriptBin "pit" ''
set -euo pipefail
tmp_cwd="$(${coreutils}/bin/mktemp -d /tmp/pit.XXXXXX)"
cleanup() {
${coreutils}/bin/rmdir "$tmp_cwd" 2>/dev/null || true
}
trap cleanup EXIT
cd "$tmp_cwd"
exec ${pi}/bin/pi "$@"
'';
in
symlinkJoin {
name = "pi-sandboxed";
paths = [
sbox
pi
pit
];
}
|