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
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
# dotfiles-py9y
title: Finish personal->home role rename (gitconfig.sh + starship prompt)
status: completed
type: bug
priority: normal
created_at: 2026-06-22T02:19:07Z
updated_at: 2026-06-22T02:22:17Z
---

Commit e3e5027 renamed DOTPICKLES_ROLE personal->home but missed two files. Both fixed, plus docs captured.

## Checklist
- [x] gitconfig.sh: rename `personal)` case to `home)` (keep personal-identity include path)
- [x] Fix fish role detection so DOTPICKLES_ROLE is set before starship-init reads it (extracted to conf.d/dotpickles-role.fish, removed from config.fish, fixed starship fallback personal->home)
- [x] Verify gitconfig.sh runs and prompt reflects real role (bash -n + fish simulation: ctx=home)
- [x] Docs: architecture.md (fish path + conf.d ordering note), config/fish/CLAUDE.md (Load Order Gotcha section), ADR 0035 (added gitconfig.sh + starship fallback to consumers, conf.d placement note)
13 changes: 13 additions & 0 deletions config/fish/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,25 @@ Fish is the primary shell. Config is modular via `conf.d/` autoloading.

## Key conf.d Files

- `dotpickles-role.fish`: Sets `DOTPICKLES_ROLE` (canonical names `home`/`work`, see [ADR 0035](../../doc/adr/0035-canonical-dotpickles-role-names.md))
- `editor.fish`: Sets `EDITOR` based on `envsense` environment detection (Cursor vs Claude Code vs terminal)
- `ghostty.fish`: Ghostty-specific setup
- `cursor_agent.fish`, `obsidian.fish`: IDE-specific behaviors
- `atuin.fish`: Shell history with atuin
- Tool inits: starship, homebrew, bat, git-duet, mise, etc.

## Load Order Gotcha

Fish sources `conf.d/*.fish` (alphabetically) **before** `config.fish`. Anything a
conf.d file reads at init time must be set by an earlier-sorting conf.d file, not
`config.fish` -- by the time `config.fish` runs, the prompt is already built.

This is why `DOTPICKLES_ROLE` lives in `conf.d/dotpickles-role.fish` and not
`config.fish`: `starship-init.fish` reads the role to build `STARSHIP_CTX`, and
`dotpickles-role` sorts before `starship-init`. When it lived in `config.fish` the
role was always unset at prompt-build time, so the prompt silently fell back to its
default and showed the wrong role.

## Adding New Config

Drop a `.fish` file in `config/fish/conf.d/`. It autoloads on next shell start. No need to source manually.
Expand Down
17 changes: 17 additions & 0 deletions config/fish/conf.d/dotpickles-role.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Set DOTPICKLES_ROLE early.
#
# This lives in conf.d/ (not config.fish) on purpose: fish sources conf.d/*.fish
# BEFORE config.fish, and conf.d files load alphabetically. The starship prompt
# (conf.d/starship-init.fish) reads DOTPICKLES_ROLE to build STARSHIP_CTX, so the
# role must be set before it runs. "dotpickles-role" sorts before "starship-init",
# so this wins. Setting it in config.fish would be too late and the prompt would
# fall back to its default, showing the wrong role.
#
# Canonical role names are "home" / "work" (see doc/adr/0035-canonical-dotpickles-role-names.md).
if not set -q DOTPICKLES_ROLE
if string match --quiet --regex '^josh-nichols-' (hostname)
set -gx DOTPICKLES_ROLE work
else
set -gx DOTPICKLES_ROLE home
end
end
2 changes: 1 addition & 1 deletion config/fish/conf.d/starship-init.fish
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

if status --is-interactive
if type -q starship
set -l ctx (set -q DOTPICKLES_ROLE; and echo $DOTPICKLES_ROLE; or echo personal)
set -l ctx (set -q DOTPICKLES_ROLE; and echo $DOTPICKLES_ROLE; or echo home)
if test -f /.dockerenv; or test -n "$REMOTE_CONTAINERS"; or test -n "$CODESPACES"
set -gx STARSHIP_CTX "$ctx | devcontainer"
else
Expand Down
7 changes: 2 additions & 5 deletions config/fish/config.fish
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
if string match --quiet --regex '^josh-nichols-' (hostname)
set -gx DOTPICKLES_ROLE work
else
set -gx DOTPICKLES_ROLE home
end
# DOTPICKLES_ROLE is set in conf.d/dotpickles-role.fish (loaded before this file
# and before the starship prompt, which needs the role at init time).

if test -f ~/.gusto/init.fish
source ~/.gusto/init.fish
Expand Down
17 changes: 16 additions & 1 deletion doc/adr/0035-canonical-dotpickles-role-names.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,22 @@ Every role-keyed consumer must use exactly these names. Known consumers:
- `Brewfile.<role>`
- `claude/roles/<role>.jsonc`
- `config/1password/agent.toml.<role>` ([ADR 0033](0033-1password-ssh-agent-allowlist.md))
- the role default in `claudeconfig.sh`, `sshconfig.sh`, `install.sh`
- the role default / branch in `claudeconfig.sh`, `sshconfig.sh`, `install.sh`, `gitconfig.sh`
- the starship prompt context fallback in `config/fish/conf.d/starship-init.fish`

`gitconfig.sh` (a `case "$DOTPICKLES_ROLE"` branch) and the starship prompt
fallback were both missed by the original rename and only caught later:
`gitconfig.sh` would hit its `*)` "Unexpected role" exit on a `home` machine, and
the prompt showed a stale `personal` because its fallback string was never updated.

### Fish: set the role in conf.d, not config.fish

Fish sources `conf.d/*.fish` before `config.fish`. The starship prompt
(`conf.d/starship-init.fish`) reads `DOTPICKLES_ROLE` at init time, so the role
must be set by an earlier-sorting conf.d file. It lives in
`conf.d/dotpickles-role.fish` (sorts before `starship-init`). Setting it in
`config.fish` is too late: the prompt builds with the role unset and falls back to
its default, silently showing the wrong role.

### Role name vs agent identity name

Expand Down
2 changes: 1 addition & 1 deletion doc/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The central architectural pattern is **role-based adaptation**. The role is dete
- **Brewfile selection**: `Brewfile` + `Brewfile.$ROLE` are merged during brew bundle
- **Shell environment**: Various configs conditionally load based on role

The canonical role values are `home`, `work`, and `container` (see [ADR 0035](adr/0035-canonical-dotpickles-role-names.md)). Detection defaults to `work` for hostnames matching `josh-nichols-*`, `container` inside containers, otherwise `home`. The same hostname check is duplicated across [install.sh](../install.sh), [config/fish/config.fish](../config/fish/config.fish), and [home/.zshenv](../home/.zshenv) because bash, fish, and zsh can't share one snippet; the canonical-name list and a fail-loud guard ([ADR 0036](adr/0036-fail-loud-role-resolution.md)) keep the copies from drifting silently.
The canonical role values are `home`, `work`, and `container` (see [ADR 0035](adr/0035-canonical-dotpickles-role-names.md)). Detection defaults to `work` for hostnames matching `josh-nichols-*`, `container` inside containers, otherwise `home`. The same hostname check is duplicated across [install.sh](../install.sh), [config/fish/conf.d/dotpickles-role.fish](../config/fish/conf.d/dotpickles-role.fish), and [home/.zshenv](../home/.zshenv) because bash, fish, and zsh can't share one snippet; the canonical-name list and a fail-loud guard ([ADR 0036](adr/0036-fail-loud-role-resolution.md)) keep the copies from drifting silently. The fish copy lives in `conf.d/` (not `config.fish`) on purpose: fish sources `conf.d/*.fish` before `config.fish`, and the starship prompt reads `DOTPICKLES_ROLE` at init time, so the role must be set first.

## Symlink-Based File Management

Expand Down
2 changes: 1 addition & 1 deletion gitconfig.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fi

signing=false
case "$DOTPICKLES_ROLE" in
personal)
home)
echo " → using personal identify for git"
git config --file ~/.gitconfig.local --add include.path ~/.gitconfig.d/personal-identity

Expand Down
Loading