aboutsummaryrefslogtreecommitdiffstats
path: root/openspec/changes/add-bash-profile-bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'openspec/changes/add-bash-profile-bootstrap')
-rw-r--r--openspec/changes/add-bash-profile-bootstrap/.openspec.yaml2
-rw-r--r--openspec/changes/add-bash-profile-bootstrap/design.md30
-rw-r--r--openspec/changes/add-bash-profile-bootstrap/proposal.md22
-rw-r--r--openspec/changes/add-bash-profile-bootstrap/specs/shell-login-bootstrap/spec.md33
-rw-r--r--openspec/changes/add-bash-profile-bootstrap/tasks.md15
5 files changed, 0 insertions, 102 deletions
diff --git a/openspec/changes/add-bash-profile-bootstrap/.openspec.yaml b/openspec/changes/add-bash-profile-bootstrap/.openspec.yaml
deleted file mode 100644
index 563fab5..0000000
--- a/openspec/changes/add-bash-profile-bootstrap/.openspec.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
1schema: spec-driven
2created: 2026-09-21
diff --git a/openspec/changes/add-bash-profile-bootstrap/design.md b/openspec/changes/add-bash-profile-bootstrap/design.md
deleted file mode 100644
index e6ff923..0000000
--- a/openspec/changes/add-bash-profile-bootstrap/design.md
+++ /dev/null
@@ -1,30 +0,0 @@
1## Context
2
3See proposal.md - Why. This sits alongside `modules/home/dotfiles.nix` (`dotfiles-management`) without depending on it — this new behavior fires regardless of whether `home.dotfiles.repoUrl` is set. A real, repo-unmanaged `~/.bash_profile` (containing a plaintext Homebrew token) was found on the user's macOS machine during an earlier change's exploration and explicitly flagged out of scope there; the exists-check in this change is what makes it safe to run this feature on that same machine, and on any other machine that already has its own `.bash_profile`.
4
5## Goals / Non-Goals
6
7**Goals:**
8- Create `~/.bash_profile` (sourcing `~/.bashrc`) exactly once, only when it doesn't already exist.
9- Behave identically on every platform this flake targets, with no per-OS conditional.
10
11**Non-Goals:**
12- Managing the contents or ownership of `~/.bashrc` itself — that remains entirely owned by the external dotfiles repo, unchanged by this capability.
13- Reconciling or updating a `~/.bash_profile` that already exists, however it got there.
14
15## Decisions
16
17**New capability (`shell-login-bootstrap`) instead of a `dotfiles-management` delta.** `dotfiles-management`'s own Purpose and first requirement are specifically about the opt-in `home.dotfiles.repoUrl` clone-and-stow feature ("SHALL only run when a repository URL has been explicitly configured"). This new behavior is unconditional and fires identically whether or not that URL is ever set, so folding it in would contradict that capability's own framing rather than extend it.
18
19**A standalone `home.activation` script (`modules/home/bash-profile.nix`), not `programs.bash`.** `programs.bash` is deliberately not enabled anywhere in this repo (see the archived `add-developer-environment` design) because enabling it would make home-manager generate and own `~/.bashrc`, conflicting with the dotfiles-repo-owned `~/dotfiles/bash/.bashrc`. Reaching for `programs.bash.profileExtra` or similar would fight that existing setup, so this has to be a plain activation script writing a plain file directly, following the same `lib.hm.dag.entryAfter [ "writeBoundary" ]` idiom already used by `dotfiles.nix`.
20
21**`[ -e ]`, not `[ -f ]`, for the exists-check.** `-e` also matches an existing symlink (e.g. a future dotfiles-repo-provided `.bash_profile` package), so a symlink is never clobbered either — only true absence triggers the write.
22
23**`install -m 644` (GNU coreutils via `pkgs.coreutils`) instead of `cp` + `chmod`, and no temp-file-then-`mv` staging.** `install` sets content and permissions in one step, avoiding a GNU/BSD `install` behavior mismatch between Linux and macOS hosts. Temp-file staging was considered and rejected: this repo's only existing conditional-write precedent (`dotfiles.nix`'s `git clone`/`stow` calls) doesn't defend against partial writes either, activation scripts here run sequentially rather than concurrently, and the file is a few bytes — added complexity wasn't justified.
24
25**No ordering dependency between this activation script and `dotfiles.nix`'s.** `dotfiles.nix`'s activation entry only exists at all when `cfg.repoUrl != ""` (`lib.mkIf`-gated). A hard `entryAfter [ "dotfiles" ]` reference would leave the DAG edge dangling whenever the dotfiles feature is disabled — fragile for no benefit. Both possible race outcomes are already safe without any explicit ordering: if `dotfiles`'s stow step runs first and links a `.bash_profile` package, the `[ -e ]` check sees it and skips (the dotfiles-repo-owned file wins, consistent with the existing `.bashrc`/`.gitconfig` precedent); if this block runs first and creates the plain bootstrap file, and the dotfiles repo also ships a `.bash_profile` package, `stow` hits an occupied target and — per `dotfiles-management`'s existing "a conflicting package does not block the others" requirement — skips just that one package with a visible warning, without aborting. Accepted explicitly rather than engineered around.
26
27## Risks / Trade-offs
28
29- **A pre-existing, unmanaged `~/.bash_profile` (e.g. the one with a plaintext Homebrew token on the user's Mac) is left completely untouched, including if it's stale or wrong** → This is the explicit intent, not an oversight: the exists-check guard is a hard requirement precisely so this feature never touches a file it doesn't own.
30- **No local way to verify activation behavior since Nix isn't installed on this development machine** → Same constraint as every prior change in this repo; `nix flake check` and a real `home-manager switch` remain the acceptance gate.
diff --git a/openspec/changes/add-bash-profile-bootstrap/proposal.md b/openspec/changes/add-bash-profile-bootstrap/proposal.md
deleted file mode 100644
index 6991c2a..0000000
--- a/openspec/changes/add-bash-profile-bootstrap/proposal.md
+++ /dev/null
@@ -1,22 +0,0 @@
1## Why
2
3NixOS (and most other Linux distros) don't ship a `~/.bash_profile` that sources `~/.bashrc`, so login shells never pick up the user's bash config — only interactive non-login shells do. This repo made bash the primary managed shell in an earlier change (`add-developer-environment`), and the real `.bashrc` lives in the user's external dotfiles repo (`~/dotfiles/bash/.bashrc`, stowed to `~/.bashrc` by `modules/home/dotfiles.nix`), so this gap is real on any freshly provisioned machine.
4
5## What Changes
6
7- Add a new home-manager activation script that creates `~/.bash_profile` (sourcing `~/.bashrc` if present) only when `~/.bash_profile` does not already exist. An existing `~/.bash_profile`, in any form (regular file or symlink), is never modified.
8- Applies unconditionally on every platform this flake targets (Linux and macOS) — not gated by `home.dotfiles.repoUrl` — since the exists-check itself is what keeps it safe everywhere, including on a machine with an existing, repo-unmanaged `~/.bash_profile`.
9
10## Capabilities
11
12### New Capabilities
13- `shell-login-bootstrap`: ensures a login shell sources `~/.bashrc` via `~/.bash_profile`, creating that file only when it doesn't already exist, on every platform this flake targets.
14
15### Modified Capabilities
16(none — `dotfiles-management`'s existing "a conflicting package does not block the others" requirement already covers the rare case where a dotfiles-repo-provided `.bash_profile` package races against this file; no requirement of that capability changes)
17
18## Impact
19
20- Affected code: a new `modules/home/` module, registered in `modules/home/default.nix`'s imports; `README.md`'s documentation of the home-manager module layout and shell setup.
21- Applies to every `homeConfigurations`/`nixosConfigurations` output built from the shared home profile (both `tom@linux` and `tom@darwin`, plus any future NixOS host).
22- No change to `dotfiles.nix` or its behavior.
diff --git a/openspec/changes/add-bash-profile-bootstrap/specs/shell-login-bootstrap/spec.md b/openspec/changes/add-bash-profile-bootstrap/specs/shell-login-bootstrap/spec.md
deleted file mode 100644
index 37e236c..0000000
--- a/openspec/changes/add-bash-profile-bootstrap/specs/shell-login-bootstrap/spec.md
+++ /dev/null
@@ -1,33 +0,0 @@
1## Purpose
2
3Ensures a login shell actually loads the user's bash configuration, since NixOS and most other Linux distributions don't ship a `~/.bash_profile` that sources `~/.bashrc` by default — without ever touching a `~/.bash_profile` that already exists.
4
5## ADDED Requirements
6
7### Requirement: A missing `.bash_profile` is created to source `.bashrc`
8If no `~/.bash_profile` exists, home-manager activation SHALL create one whose contents source `~/.bashrc`.
9
10#### Scenario: No `.bash_profile` exists
11- **WHEN** activation runs and `~/.bash_profile` does not exist
12- **THEN** a `~/.bash_profile` is created that sources `~/.bashrc`
13
14### Requirement: An existing `.bash_profile` is never modified
15If `~/.bash_profile` already exists in any form (regular file or symlink), activation SHALL NOT create, overwrite, or otherwise modify it.
16
17#### Scenario: `.bash_profile` already exists
18- **WHEN** activation runs and `~/.bash_profile` already exists
19- **THEN** its contents are left completely unchanged, and no write is attempted
20
21### Requirement: The created file tolerates a missing `.bashrc`
22The generated `~/.bash_profile` SHALL only attempt to source `~/.bashrc` if that file exists, so it never errors on a login shell that runs before `~/.bashrc` is otherwise provisioned.
23
24#### Scenario: `.bashrc` does not exist yet
25- **WHEN** the generated `~/.bash_profile` runs and `~/.bashrc` does not exist
26- **THEN** it does nothing further and produces no error
27
28### Requirement: Behavior is identical on every platform this flake targets
29This capability SHALL apply unconditionally wherever the shared home-manager profile is activated — NixOS, standalone Linux, and macOS alike — gated only by whether `~/.bash_profile` already exists, not by operating system.
30
31#### Scenario: Activated on any supported platform
32- **WHEN** the shared home profile is activated on NixOS, standalone Linux, or macOS
33- **THEN** the same create-if-absent behavior for `~/.bash_profile` applies identically
diff --git a/openspec/changes/add-bash-profile-bootstrap/tasks.md b/openspec/changes/add-bash-profile-bootstrap/tasks.md
deleted file mode 100644
index 701d3f3..0000000
--- a/openspec/changes/add-bash-profile-bootstrap/tasks.md
+++ /dev/null
@@ -1,15 +0,0 @@
1## 1. Module
2
3- [x] 1.1 Create `modules/home/bash-profile.nix` with a `pkgs.writeText` block for the `.bash_profile` content and a `home.activation.bashProfile` script that creates it via `install -m 644` only when `${config.home.homeDirectory}/.bash_profile` does not exist (`[ ! -e ... ]`) — verify by reading the file against design.md's decisions (no ordering dependency on `dotfiles`, `install` via `pkgs.coreutils`, `[ -e ]` guard not `[ -f ]`, `$DRY_RUN_CMD` prefix on the write)
4- [x] 1.2 Add `./bash-profile.nix` to `modules/home/default.nix`'s imports — verify by grep confirming the import is present
5
6## 2. Documentation
7
8- [x] 2.1 Update `README.md`'s module layout summary and add a short section documenting the new always-on `~/.bash_profile` bootstrap behavior and its never-overwrite guarantee — verify by reading the updated section for consistency with the module
9
10## 3. Validation
11
12- [x] 3.1 Run `nix flake check` and confirm `modules/home/bash-profile.nix` evaluates cleanly (blocked — Nix is not installed on this machine; run this once Nix is available, e.g. via a real install or CI — this is the real acceptance gate, not the individual checkboxes above)
13- [x] 3.2 Manually trace each scenario in `specs/shell-login-bootstrap/spec.md` against the implemented module, confirming each is satisfied by inspection given #3.1 cannot run locally (all 4 scenarios traced and satisfied: the `[ ! -e "$BASH_PROFILE" ]` guard creates the file only when absent and sources `.bashrc`; the same guard means an existing file or symlink is never touched; the generated content's own `[ -f "$HOME/.bashrc" ]` check means a missing `.bashrc` produces no error; no platform conditional exists in the module, so behavior is identical wherever `modules/home/default.nix` is consumed — both `mkNixos` and `mkHome`)
14
15**Verification note:** as with every prior change in this repo, Nix is not installed on this machine, so task 3.1 (`nix flake check`) could not be executed and remains the outstanding acceptance gate. Implementation was reviewed manually against `design.md`'s decisions and the module follows the same `home.activation`/`lib.hm.dag.entryAfter` idiom already proven in `modules/home/dotfiles.nix`.