Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ container rebuilds.
| [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) | TypeScript | Google Gemini in the terminal * |
| [OpenAI Codex CLI](https://github.com/openai/codex) | TypeScript | OpenAI Codex in the terminal * |
| [opencode](https://github.com/anomalyco/opencode) | Go | AI coding TUI |
| [Pi Coding Agent](https://github.com/earendil-works/pi) | TypeScript | Minimal terminal coding harness (Earendil) * |

\* Requires Node.js (auto-installed if needed).

Expand Down Expand Up @@ -325,6 +326,7 @@ First-run selections add to that:
| Google Gemini CLI | ~50 MB |
| OpenAI Codex CLI | ~50 MB |
| OpenCode | ~30 MB |
| Pi Coding Agent | ~50 MB |
| lazygit / gh-dash / yazi | ~10 / ~10 / ~10 MB |
| micro / edit | ~12 / ~7 MB |
| fresh / nvim | ~10 / ~45 MB |
Expand All @@ -350,7 +352,7 @@ get new features without waiting for a squarebox release, at the cost of
build-time pinning for that tier.

Third-party install scripts (Claude Code, uv, .NET) delegate to the vendor
installer. npm-based AI tools (Copilot CLI, Gemini CLI, Codex CLI) use npm's
installer. npm-based AI tools (Copilot CLI, Gemini CLI, Codex CLI, Pi) use npm's
built-in integrity verification.

For the full trust model (what `install.sh` does on your machine, how each
Expand Down
3 changes: 2 additions & 1 deletion scripts/e2e-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ suite_setup() {
suite_setup_editors() {
# Pre-seed selections in /workspace/.squarebox/
mkdir -p /workspace/.squarebox
echo "opencode" > /workspace/.squarebox/ai-tool
echo "opencode,pi" > /workspace/.squarebox/ai-tool
echo "micro,edit,fresh,nvim" > /workspace/.squarebox/editors
echo "lazygit,gh-dash,yazi" > /workspace/.squarebox/tuis
echo "tmux,zellij" > /workspace/.squarebox/multiplexer
Expand All @@ -194,6 +194,7 @@ suite_setup_editors() {

# 3.7 editors installed
run_test "3.7a opencode installed" command -v opencode
run_test "3.7a2 pi installed" command -v pi
run_test "3.7b micro installed" command -v micro
run_test "3.7c edit installed" command -v edit
run_test "3.7d fresh installed" command -v fresh
Expand Down
2 changes: 1 addition & 1 deletion scripts/squarebox-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ usage() {
${BOLD}Sections:${RESET}
git Git identity (name, email)
github GitHub CLI authentication
ai AI coding assistants (claude, copilot, gemini, codex, opencode)
ai AI coding assistants (claude, copilot, gemini, codex, opencode, pi)
editors Text editors (micro, edit, fresh, nvim)
tuis TUI tools (lazygit, gh-dash, yazi)
multiplexers Terminal multiplexers (tmux, zellij)
Expand Down
21 changes: 16 additions & 5 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -348,13 +348,14 @@ if $INTERACTIVE; then
gemini) gum_selected="${gum_selected:+$gum_selected,}Google Gemini CLI" ;;
codex) gum_selected="${gum_selected:+$gum_selected,}OpenAI Codex CLI" ;;
opencode) gum_selected="${gum_selected:+$gum_selected,}OpenCode" ;;
pi) gum_selected="${gum_selected:+$gum_selected,}Pi Coding Agent" ;;
esac
done
gum_args=(--no-limit --header "Select AI coding assistants (space=toggle, enter=confirm):")
[ -n "$gum_selected" ] && gum_args+=(--selected "$gum_selected")
selected=$(gum choose "${gum_args[@]}" \
"Claude Code" "GitHub Copilot CLI" "Google Gemini CLI" \
"OpenAI Codex CLI" "OpenCode") || true
"OpenAI Codex CLI" "OpenCode" "Pi Coding Agent") || true
ai_choice=""
while IFS= read -r line; do
case "$line" in
Expand All @@ -363,25 +364,26 @@ if $INTERACTIVE; then
"Google Gemini CLI") ai_choice="${ai_choice:+$ai_choice,}gemini" ;;
"OpenAI Codex CLI") ai_choice="${ai_choice:+$ai_choice,}codex" ;;
"OpenCode") ai_choice="${ai_choice:+$ai_choice,}opencode" ;;
"Pi Coding Agent") ai_choice="${ai_choice:+$ai_choice,}pi" ;;
esac
done <<< "$selected"
else
echo "Select AI coding assistants (comma-separated, 'all', or press Enter to skip):"
for ai_item in "1:claude:Claude Code" "2:copilot:GitHub Copilot CLI" "3:gemini:Google Gemini CLI" "4:codex:OpenAI Codex CLI" "5:opencode:OpenCode"; do
for ai_item in "1:claude:Claude Code" "2:copilot:GitHub Copilot CLI" "3:gemini:Google Gemini CLI" "4:codex:OpenAI Codex CLI" "5:opencode:OpenCode" "6:pi:Pi Coding Agent"; do
num="${ai_item%%:*}"; rest="${ai_item#*:}"; key="${rest%%:*}"; label="${rest#*:}"
if [[ ",$ai_prev," == *",${key},"* ]]; then
echo " ${num}) ${label} [installed]"
else
echo " ${num}) ${label}"
fi
done
read -rp "Selection [1,2,3,4,5/all/skip]: " ai_selection
read -rp "Selection [1,2,3,4,5,6/all/skip]: " ai_selection
if [ -z "$ai_selection" ] && [ -n "$ai_prev" ]; then
ai_choice="$ai_prev"
else
ai_choice=""
if [ "$ai_selection" = "all" ]; then
ai_choice="claude,copilot,gemini,codex,opencode"
ai_choice="claude,copilot,gemini,codex,opencode,pi"
elif [ -n "$ai_selection" ]; then
for item in $(echo "$ai_selection" | tr ',' ' '); do
case "$item" in
Expand All @@ -390,6 +392,7 @@ if $INTERACTIVE; then
3) ai_choice="${ai_choice:+$ai_choice,}gemini" ;;
4) ai_choice="${ai_choice:+$ai_choice,}codex" ;;
5) ai_choice="${ai_choice:+$ai_choice,}opencode" ;;
6) ai_choice="${ai_choice:+$ai_choice,}pi" ;;
esac
done
fi
Expand Down Expand Up @@ -423,6 +426,13 @@ install_codex() {
run_with_spinner "Installing OpenAI Codex CLI..." npm install -g --silent @openai/codex
}

install_pi() {
if command -v pi &>/dev/null; then echo "Pi Coding Agent already installed, skipping."; return 0; fi
ensure_node_for_npm
# --ignore-scripts is the upstream-recommended install flag (see pi.dev).
run_with_spinner "Installing Pi Coding Agent..." npm install -g --silent --ignore-scripts @earendil-works/pi-coding-agent
}
Comment on lines +429 to +434

for ai_tool in $(echo "$ai_choice" | tr ',' ' '); do
case "$ai_tool" in
claude)
Expand All @@ -443,13 +453,14 @@ for ai_tool in $(echo "$ai_choice" | tr ',' ' '); do
copilot) install_copilot || echo "Warning: GitHub Copilot CLI installation failed." ;;
gemini) install_gemini || echo "Warning: Google Gemini CLI installation failed." ;;
codex) install_codex || echo "Warning: OpenAI Codex CLI installation failed." ;;
pi) install_pi || echo "Warning: Pi Coding Agent installation failed." ;;
esac
done

# Set aliases based on selection — c maps to first selected tool in priority order
{
c_target=""
for ai_tool in claude copilot gemini codex opencode; do
for ai_tool in claude copilot gemini codex opencode pi; do
if [[ ",$ai_choice," == *",$ai_tool,"* ]]; then
[ -z "$c_target" ] && c_target="$ai_tool"
case "$ai_tool" in
Expand Down
Loading