feat(profile,statusline): show active profile in statusline via .active-profile cache

`bash lib/profile.sh current` is 12s+ — far too slow to call from the
statusline hook (runs on every keystroke). Add a one-line cache file at
`<repo>/.active-profile`, written by `cmd_apply` and `cmd_reset`. The
statusline reads the file directly with a single `head -n1`, no
sub-shell into `profile.sh`.

Behavior:
- `bash lib/profile.sh set <name>` (which ends in `cmd_apply`) and
  `bash lib/profile.sh apply <name>` both write `<name>` to
  `<repo>/.active-profile`.
- `bash lib/profile.sh reset` writes the literal `none`.
- Statusline inserts the cached profile name between the plan segment
  and the context-bar segment, e.g.
  `Opus 4.7 | claude (master) | Max | full | ████░░░░░░ 42% | 3m`.
- Missing or empty cache → statusline shows `?`.

Cache file is gitignored — it tracks runtime state, not source.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Bastien Chanot
2026-05-21 05:14:12 +02:00
co-authored by Claude
parent a4558ee805
commit cb1e8cd814
3 changed files with 24 additions and 1 deletions
+11
View File
@@ -45,6 +45,7 @@ SKILLS_DIR="$REPO/skills"
DISABLED_DIR="$REPO/skills-disabled"
PROFILES_DIR="$REPO/lib/profiles"
TOGGLE_EXTERNAL="$REPO/lib/toggle-external.sh"
ACTIVE_CACHE="$REPO/.active-profile" # statusline reads this — keep fast (single-line file, profile name only)
# Plugins that are toggle-managed by `set`. Anything NOT in this list is
# never auto-disabled — protects always-on plugins (caveman, security-guidance,
@@ -71,6 +72,14 @@ warn() { echo -e "${YELLOW}⚠${NC} $1"; }
err() { echo -e "${RED}✗${NC} $1" >&2; }
info() { echo -e "${BLUE}ℹ${NC} $1"; }
# Persist active-profile name for fast statusline lookup (cmd_current is slow
# — iterates every profile + every entry). Write profile name only; statusline
# reads the file directly without re-invoking this script.
write_active() {
local name="$1"
printf '%s\n' "$name" > "$ACTIVE_CACHE" 2>/dev/null || true
}
# ── Profile parsing ────────────────────────────────────────
# Read a profile file. Output one line per entry: "<skill>\t<type>"
@@ -351,6 +360,7 @@ cmd_apply() {
while IFS=$'\t' read -r skill type; do
enable_skill "$skill" "$type"
done < <(read_profile "$prof")
write_active "$prof"
}
cmd_set() {
@@ -406,6 +416,7 @@ cmd_reset() {
fi
info "Plugin state NOT touched. To re-enable a managed plugin disabled by 'set',"
info "run: claude plugin enable <name>@<marketplace> (or: profile apply <profile>)"
write_active "none"
}
cmd_current() {