diff --git a/docs/superpowers/plans/2026-06-07-first-run.md b/docs/superpowers/plans/2026-06-07-first-run.md new file mode 100644 index 0000000..d04cb3a --- /dev/null +++ b/docs/superpowers/plans/2026-06-07-first-run.md @@ -0,0 +1,328 @@ +# First-Run Initialization Routine — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Create `conf.d/first_run.fish` that runs exactly once on the first interactive fish session — showing a welcome message, auto-installing Fisher + plugins, and applying the Catppuccin Mocha theme. + +**Architecture:** A universal variable (`__fish_config_first_run_complete`) acts as the persistent flag. `conf.d/first_run.fish` is auto-sourced by fish on every shell start; it exits immediately if the flag is already set. On first run it sets the flag first (crash-safe), then executes actions in order. The existing interactive Fisher bootstrap in `config.fish` is removed since `first_run.fish` owns that responsibility. + +**Tech Stack:** fish shell 4.x, universal variables (`set -U`), `curl`, `fisher`, `fish_config theme choose` + +--- + +## File Map + +| File | Action | Responsibility | +|------|--------|---------------| +| `conf.d/first_run.fish` | **Create** | State guard + all first-run actions | +| `config.fish` | **Modify** lines 117–130 | Remove interactive Fisher bootstrap block | +| `docs/fish-config.md` | **Modify** | Document first-run behavior | +| `AGENTS.md` | **Modify** | Check off Task #1 acceptance criteria | + +--- + +### Task 1: Remove the interactive Fisher bootstrap from `config.fish` + +**Files:** +- Modify: `config.fish:117-130` + +- [ ] **Step 1: Delete the Fisher bootstrap block** + +Open `config.fish`. Replace lines 117–130 (the entire Fisher bootstrap block) with a single comment: + +```fish +# ──────────────────────────── Bootstrap Fisher ────────────────────────── +# Fisher is bootstrapped automatically on first run via conf.d/first_run.fish +``` + +The block being removed is: +```fish +# ──────────────────────────── Bootstrap Fisher ────────────────────────── +if not type -q fisher + echo "Fisher plugin manager not found." + read -l -P "Install Fisher and plugins now? [Y/n] " _fisher_reply + if test -z "$_fisher_reply" -o "$_fisher_reply" = Y -o "$_fisher_reply" = y + echo "Installing Fisher..." + curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source + fisher update + fish_config theme choose "Catppuccin Mocha" + else + echo "Skipping Fisher install. Some features may be unavailable." + end + set --erase _fisher_reply +end +``` + +- [ ] **Step 2: Verify config.fish still parses cleanly** + +```bash +fish -n ~/.config/fish/config.fish +``` + +Expected output: no output (no parse errors). + +- [ ] **Step 3: Commit** + +```bash +git add config.fish +git commit -m "refactor: move Fisher bootstrap to first_run.fish" +``` + +--- + +### Task 2: Create `conf.d/first_run.fish` + +**Files:** +- Create: `conf.d/first_run.fish` + +- [ ] **Step 1: Create the file with this exact content** + +```fish +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# ╭──────────────────────────────────────────────────────────╮ +# │ First-Run Initialization │ +# ╰──────────────────────────────────────────────────────────╯ +# +# Runs exactly once on the first interactive fish session after install. +# To reset for testing, run: set -Ue __fish_config_first_run_complete + +# Exit early in non-interactive shells (scripts, completions, subshells) +if not status is-interactive + return +end + +# Skip if this shell has already been initialized +if set -q __fish_config_first_run_complete + return +end + +# Set the flag immediately — before actions — so a mid-run crash doesn't +# leave the shell in a state that re-triggers everything next session. +set -U __fish_config_first_run_complete 1 + +# ──────────────────────────── Welcome message ─────────────────────────── +echo "" +echo " Welcome to your fish shell configuration!" +echo " Run 'config-help' for offline documentation." +echo " Run 'fish-deps' to check and install dependencies." +echo "" + +# ──────────────────────────── Bootstrap Fisher ────────────────────────── +if not type -q fisher + echo " [first-run] Installing Fisher plugin manager..." + if curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source + and fisher update 2>/dev/null + echo " [first-run] Fisher installed and plugins loaded." + else + echo " [first-run] Fisher install failed — run 'fisher update' manually." >&2 + end +end + +# ───────────────────────────── Apply theme ────────────────────────────── +# Catppuccin Mocha theme ships with this config in themes/; it is always available. +fish_config theme choose "Catppuccin Mocha" 2>/dev/null +``` + +- [ ] **Step 2: Verify the file parses cleanly** + +```bash +fish -n ~/.config/fish/conf.d/first_run.fish +``` + +Expected output: no output (no parse errors). + +- [ ] **Step 3: Commit** + +```bash +git add conf.d/first_run.fish +git commit -m "feat: add first_run.fish for one-time shell initialization" +``` + +--- + +### Task 3: Verify first-run behavior + +**Files:** +- No file changes — verification only + +- [ ] **Step 1: Simulate a fresh install by clearing the flag** + +```bash +fish -c "set -Ue __fish_config_first_run_complete" +``` + +Expected output: no output (variable erased). + +- [ ] **Step 2: Confirm the flag is gone** + +```bash +fish -c "set -q __fish_config_first_run_complete; and echo SET; or echo UNSET" +``` + +Expected output: +``` +UNSET +``` + +- [ ] **Step 3: Open a new interactive fish shell and observe first-run output** + +```bash +fish -i -c "exit" 2>/dev/null +``` + +Expected to see (on the terminal — open a real new tab or run `fish` interactively): +``` + + Welcome to your fish shell configuration! + Run 'config-help' for offline documentation. + Run 'fish-deps' to check and install dependencies. + + [first-run] Fisher installed and plugins loaded. +``` +(Fisher output may vary; if Fisher is already installed the Fisher block is skipped.) + +- [ ] **Step 4: Confirm the flag is now set** + +```bash +fish -c "set -q __fish_config_first_run_complete; and echo SET; or echo UNSET" +``` + +Expected output: +``` +SET +``` + +- [ ] **Step 5: Open another interactive shell — confirm no first-run output** + +```bash +fish -i -c "exit" 2>/dev/null +``` + +Expected: no welcome message, no Fisher output. The routine is silent on repeat launches. + +- [ ] **Step 6: Verify non-interactive shells are unaffected** + +```bash +fish -c "echo hello" +``` + +Expected output: +``` +hello +``` +No welcome message. The `status is-interactive` guard prevents any output. + +- [ ] **Step 7: Commit verification note (no code change needed)** + +If steps 1–6 all pass, no commit needed here — move to Task 4. +If a fix was required, commit it: +```bash +git add conf.d/first_run.fish +git commit -m "fix: correct first-run guard behavior" +``` + +--- + +### Task 4: Update `docs/fish-config.md` + +**Files:** +- Modify: `docs/fish-config.md` + +- [ ] **Step 1: Find the Fisher bootstrap section in the docs** + +```bash +grep -n "Fisher\|fisher\|bootstrap\|first.run\|first_run" docs/fish-config.md | head -20 +``` + +Note the line number of the Fisher bootstrap description (around line 1199 based on current state). + +- [ ] **Step 2: Update the Fisher bootstrap description** + +Find the existing text that says something like: +``` +Fisher is bootstrapped automatically on first shell start if not present. +``` + +Replace or expand it to read: + +```markdown +Fisher is bootstrapped automatically on the **first interactive session** via +`conf.d/first_run.fish`. This also applies the Catppuccin Mocha theme and +prints a one-time welcome message. Subsequent sessions skip all first-run +logic with zero overhead. + +To re-trigger first-run initialization (e.g., after a fresh install or for +testing), run: + +```fish +set -Ue __fish_config_first_run_complete +``` + +Then open a new shell. +``` + +- [ ] **Step 3: Verify the docs file is valid (no broken markdown)** + +```bash +fish -c "bat --language=markdown docs/fish-config.md" 2>/dev/null | head -5 +``` + +Expected: renders without errors (or just check the file opens cleanly). + +- [ ] **Step 4: Commit** + +```bash +git add docs/fish-config.md +git commit -m "docs: document first-run initialization in fish-config.md" +``` + +--- + +### Task 5: Mark acceptance criteria in AGENTS.md + +**Files:** +- Modify: `AGENTS.md` + +- [ ] **Step 1: Check off the Task #1 acceptance criteria** + +In `AGENTS.md`, find the "First-Run Initialization Routine" section and replace each `- [ ]` with `- [x]`: + +```markdown +### 1. First-Run Initialization Routine +- [x] **State Detection:** Define a persistent universal state variable (`__fish_config_first_run_complete`) to identify if the environment is being initialized for the very first time. +- [x] **Execution Logic:** Create the structure for `~/.config/fish/conf.d/first_run.fish`. +- [x] **Integration:** Ensure the code inside executes ONLY when the universal variable is not set. It must immediately update the state variable upon execution to prevent running on subsequent interactive shell launches. +- [x] **Best Practices:** Ensure the script exits early if the shell is non-interactive to save performance. Include a commented-out example of how to manually reset the state variable for testing. +``` + +- [ ] **Step 2: Commit** + +```bash +git add AGENTS.md +git commit -m "docs: mark first-run initialization task complete in AGENTS.md" +``` + +--- + +## Self-Review + +**Spec coverage check:** + +| Spec requirement | Task | +|-----------------|------| +| Universal variable `__fish_config_first_run_complete` | Task 2 | +| `conf.d/first_run.fish` file | Task 2 | +| Executes only when variable is not set | Task 2 (guard pattern) | +| Sets variable immediately to prevent re-run | Task 2 (set before actions) | +| Exits early if non-interactive | Task 2 (first guard) | +| Commented reset example | Task 2 (top of file comment) | +| Welcome message | Task 2 | +| Fisher bootstrap (automatic, no prompt) | Task 2 | +| Theme setting | Task 2 | +| Remove old interactive Fisher prompt from config.fish | Task 1 | +| Docs updated | Task 4 | +| AGENTS.md checkboxes | Task 5 | + +All spec requirements covered. No placeholders. No TBDs.