aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-11 11:35:45 -0500
committerCraig Jennings <c@cjennings.net>2026-06-11 11:35:45 -0500
commit3df14fc985ddad041c290c732b5b5b8eae41f68e (patch)
treebf549dd862d5dda2cd7b833d11eb8501368609dd
parentd576fc217ba304b48dfb1c54b92bc1849397fd9b (diff)
downloadrulesets-3df14fc985ddad041c290c732b5b5b8eae41f68e.tar.gz
rulesets-3df14fc985ddad041c290c732b5b5b8eae41f68e.zip
feat(install): adopt the statusline script into the managed set
An archsetup session added a statusLine entry to the tracked settings.json on 2026-06-11 (Craig's request), pointing at ~/.claude/statusline-command.sh, but the script itself lived outside the repo on one machine. This commits the settings entry and brings the script into .claude/, linked by make install like the rest of the config, so it reaches every machine on the next session. Two fixes over the original: uname -n instead of hostname (Arch doesn't ship hostname by default, so the host rendered empty with stderr noise), and the tilde replacement is escaped (unquoted, bash expands the replacement ~ straight back to $HOME, which defeated the abbreviation). scripts/tests/statusline-command.bats covers the format, branch handling, and the no-stderr contract.
-rw-r--r--.claude/settings.json4
-rwxr-xr-x.claude/statusline-command.sh27
-rw-r--r--Makefile2
-rw-r--r--scripts/tests/statusline-command.bats51
4 files changed, 83 insertions, 1 deletions
diff --git a/.claude/settings.json b/.claude/settings.json
index 2e37bc6..3b8b237 100644
--- a/.claude/settings.json
+++ b/.claude/settings.json
@@ -1,4 +1,8 @@
{
+ "statusLine": {
+ "type": "command",
+ "command": "~/.claude/statusline-command.sh"
+ },
"skillListingBudgetFraction": 0.05,
"attribution": {
"commit": "",
diff --git a/.claude/statusline-command.sh b/.claude/statusline-command.sh
new file mode 100755
index 0000000..3e5e6fb
--- /dev/null
+++ b/.claude/statusline-command.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Claude Code status line — mirrors the zsh prompt from ~/.zshrc
+# PROMPT: [%D %*] $WHO $HOST:${PWD/#$HOME/~} %(?..[%?] )$NEWLINE%#
+# RPROMPT: ${vcs_info_msg_0_} (format: "on %b")
+#
+# Wired via the statusLine entry in .claude/settings.json; make install
+# symlinks this file to ~/.claude/statusline-command.sh on every machine.
+
+input=$(cat)
+
+cwd=$(echo "$input" | jq -r '.cwd')
+# Replace $HOME prefix with ~. The replacement tilde must be escaped:
+# unquoted, bash tilde-expands it straight back to $HOME.
+home="$HOME"
+display_dir="${cwd/#$home/\~}"
+
+# Git branch from cwd (mirrors vcs_info RPROMPT "on %b")
+branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null)
+git_part=""
+[ -n "$branch" ] && git_part=" on $branch"
+
+date_part=$(date "+%y-%m-%d %H:%M:%S")
+user_part=$(whoami)
+# uname -n, not hostname: Arch doesn't ship hostname by default (inetutils).
+host_part=$(uname -n)
+
+printf "%s %s %s:%s%s" "[$date_part]" "$user_part" "$host_part" "$display_dir" "$git_part"
diff --git a/Makefile b/Makefile
index 5ff155d..450dc1a 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ HOOKS := $(wildcard hooks/*.sh hooks/*.py)
# them manually if they want the behavior. Add new opt-ins to this list.
OPTIN_HOOKS := hooks/destructive-bash-confirm.py
DEFAULT_HOOKS := $(filter-out $(OPTIN_HOOKS),$(HOOKS))
-CLAUDE_CONFIG := $(wildcard .claude/*.json) $(wildcard .claude/.*.json)
+CLAUDE_CONFIG := $(wildcard .claude/*.json) $(wildcard .claude/.*.json) $(wildcard .claude/*.sh)
LANGUAGES := $(notdir $(wildcard languages/*))
TEAMS := $(notdir $(wildcard teams/*))
PDFTOOLS_VENV ?= $(HOME)/.local/venvs/pdftools
diff --git a/scripts/tests/statusline-command.bats b/scripts/tests/statusline-command.bats
new file mode 100644
index 0000000..6a8725a
--- /dev/null
+++ b/scripts/tests/statusline-command.bats
@@ -0,0 +1,51 @@
+#!/usr/bin/env bats
+# .claude/statusline-command.sh — Claude Code status line mirroring the zsh
+# prompt: [yy-mm-dd HH:MM:SS] user host:~/path on <branch>
+
+setup() {
+ REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)"
+ SCRIPT="$REPO_ROOT/.claude/statusline-command.sh"
+ TMPDIR_T="$(mktemp -d)"
+}
+
+teardown() {
+ rm -rf "$TMPDIR_T"
+}
+
+run_statusline() {
+ printf '{"cwd":"%s"}' "$1" | sh "$SCRIPT"
+}
+
+@test "statusline renders date, user, host, and tilde-abbreviated cwd" {
+ dir="$HOME/.cache"
+ run run_statusline "$dir"
+ [ "$status" -eq 0 ]
+ host="$(uname -n)"
+ user="$(whoami)"
+ [[ "$output" =~ ^\[[0-9]{2}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}:[0-9]{2}\]\ $user\ $host:~/\.cache$ ]]
+}
+
+@test "statusline appends the git branch inside a repo" {
+ git -C "$TMPDIR_T" init -q -b trunk
+ run run_statusline "$TMPDIR_T"
+ [ "$status" -eq 0 ]
+ [[ "$output" == *" on trunk" ]]
+}
+
+@test "statusline omits the branch part outside a git repo" {
+ mkdir -p "$TMPDIR_T/plain"
+ run run_statusline "$TMPDIR_T/plain"
+ [ "$status" -eq 0 ]
+ [[ "$output" != *" on "* ]]
+}
+
+@test "statusline leaves a cwd outside HOME unabbreviated" {
+ run run_statusline "/tmp"
+ [ "$status" -eq 0 ]
+ [[ "$output" == *":/tmp" ]]
+}
+
+@test "statusline emits no stderr noise" {
+ err="$(printf '{"cwd":"%s"}' "$HOME" | sh "$SCRIPT" 2>&1 >/dev/null)"
+ [ -z "$err" ]
+}