From 601caef87ac780a0ec55c363356a0ab1e6048b44 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Thu, 26 Mar 2026 15:27:41 -0400 Subject: [PATCH 1/3] Install claude code via cask --- Brewfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Brewfile b/Brewfile index 7a973f8..b49eda6 100644 --- a/Brewfile +++ b/Brewfile @@ -56,6 +56,7 @@ cask 'battle-net' cask 'bitwarden' cask 'brave-browser' cask 'chromium', args: { "no-quarantine": true } +cask 'claude-code' cask 'cyberduck' cask 'discord' cask 'dungeon-crawl-stone-soup-tiles' From bcf591701299dd91122bd375c8a359a2ea46c3f1 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Fri, 5 Jun 2026 11:47:17 -0400 Subject: [PATCH 2/3] more path --- zsh/zshrc.symlink | 1 + 1 file changed, 1 insertion(+) diff --git a/zsh/zshrc.symlink b/zsh/zshrc.symlink index bc4e541..93dac65 100644 --- a/zsh/zshrc.symlink +++ b/zsh/zshrc.symlink @@ -41,3 +41,4 @@ done # bun export BUN_INSTALL="$HOME/.bun" export PATH="$BUN_INSTALL/bin:$PATH" +export PATH="$HOME/.local/bin:$PATH" From 3fea4495d832ba090dec0bd759e41cb5d06af2c8 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Wed, 17 Jun 2026 12:05:32 -0400 Subject: [PATCH 3/3] Add global Claude Code settings and instructions Make the claude topic the source of truth for personal, cross-project Claude Code configuration: - Reconcile config/settings.json with the live settings that had drifted (always-thinking, effort, auto permissions), so bootstrap no longer clobbers them on the next run. - Add themed spinner verbs in replace mode for custom "thinking" text. - Drop the Co-Authored-By trailer from commits via the attribution setting (the modern replacement for includeCoAuthoredBy). - Add config/CLAUDE.md with personal working, git, and editing preferences, including the seven rules of a great commit message. - Link every file in config/ into ~/.claude/ from install.sh, matching the postgresql/newsyslog nested-symlink pattern. - Un-ignore config/CLAUDE.md, which the global CLAUDE.md gitignore would otherwise exclude. --- .gitignore | 3 ++ claude/README.md | 91 +++++++++++++++++++++++++++++++++++++ claude/config/CLAUDE.md | 41 +++++++++++++++++ claude/config/settings.json | 47 +++++++++++++++++++ claude/install.sh | 28 ++++++++---- 5 files changed, 200 insertions(+), 10 deletions(-) create mode 100644 claude/README.md create mode 100644 claude/config/CLAUDE.md diff --git a/.gitignore b/.gitignore index 6631ad1..ad69e62 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,8 @@ local/config.json local/automount.sh .env +# Track the global Claude instructions despite a global CLAUDE.md ignore +!claude/config/CLAUDE.md + # Node.js node_modules/ diff --git a/claude/README.md b/claude/README.md new file mode 100644 index 0000000..282c82b --- /dev/null +++ b/claude/README.md @@ -0,0 +1,91 @@ +# Claude Code + +Global configuration for [Claude Code](https://claude.ai/code). + +## What this topic does + +- Installs Claude Code via the native installer (`install.sh`) +- Symlinks every file in `config/` → `~/.claude/` (currently `settings.json` + and `CLAUDE.md`) + +The symlinks are created at provision time by `install.sh`, which `bootstrap.sh` +runs automatically. It follows the same nested-config pattern as +`postgresql`/`newsyslog`: an existing symlink is left alone, and a real file at +the target is backed up to `.backup` before linking. Drop a new file in +`config/` and it gets linked on the next run — no script changes needed. + +Settings reload automatically on save, except `model` and `outputStyle`, which +take effect in a new session. + +## settings.json + +`config/settings.json` is the source of truth. The live `~/.claude/settings.json` +is a symlink to it, so edits here apply everywhere. + +Current keys: + +| Key | Purpose | +| -------------------------- | ----------------------------------------------------- | +| `alwaysThinkingEnabled` | Extended thinking on by default | +| `effortLevel` | Persisted reasoning effort (`high`) | +| `skipAutoPermissionPrompt` | Don't prompt for the auto-permission opt-in | +| `permissions` | `defaultMode: auto`, plus an explicit allow/deny list | +| `attribution` | Strips the `Co-Authored-By` trailer from commits | +| `spinnerVerbs` | Custom "thinking" phrases (see below) | + +## Commit attribution + +```json +"attribution": { + "commit": "" +} +``` + +An empty `commit` string hides the standard attribution (including the +`Co-Authored-By: Claude` trailer) from git commits. Add `"pr": ""` to also drop +the attribution footer from generated pull request descriptions. (This replaces +the deprecated `includeCoAuthoredBy` boolean.) + +## Custom thinking phrases (spinnerVerbs) + +The words shown while Claude works are themed for fun. Schema: + +```json +"spinnerVerbs": { + "mode": "replace", + "verbs": ["Seeking the Ocarina of Time", "..."] +} +``` + +- `mode: "replace"` — show **only** these phrases. +- `mode: "append"` — add these on top of Claude's built-in defaults. + +To add or change phrases, just edit the `verbs` array in +`config/settings.json`. The current set mixes Legend of Zelda, Lord of the +Rings, and Star Wars references. + +## Global instructions (CLAUDE.md) + +`config/CLAUDE.md` is symlinked to `~/.claude/CLAUDE.md` and holds personal +preferences that apply to **every** project (working style, git habits, editing +defaults). Project-level `CLAUDE.md` files take precedence where they conflict. +Edit it directly — keep it cross-project; project-specific rules belong in that +project's own `CLAUDE.md`. + +## Other global configs worth considering + +Not set up yet, but easy to add as their own symlinked files in this topic: + +- **Custom statusLine** — a `statusLine` command in `settings.json` pointed at a + script (e.g. `config/statusline.sh`) can show cwd, git branch, model, and + context usage. +- **Spinner tips** — `spinnerTipsEnabled` (bool) and `spinnerTipsOverride` + (string) control the hint line under the spinner. +- **Output style** — `outputStyle` (e.g. `"Explanatory"`) adjusts response style. +- **keybindings** — `~/.claude/keybindings.json` for custom shortcuts / vim mode + (`editorMode`). + +### Do not check in + +- `~/.claude.json` — OAuth tokens, MCP auth, and session state. +- `~/.claude/settings.local.json` — per-project personal overrides (gitignored). diff --git a/claude/config/CLAUDE.md b/claude/config/CLAUDE.md new file mode 100644 index 0000000..557dacd --- /dev/null +++ b/claude/config/CLAUDE.md @@ -0,0 +1,41 @@ +# Personal Global Instructions + +These preferences apply across every project. Project-level `CLAUDE.md` files +take precedence where they conflict. + +## Working style + +- Lead with the answer or result, then the supporting detail. Keep prose tight. +- Verify claims before stating them. Prefer reading the code/docs over recalling + from memory, and cite `file:line` when referring to specific code. +- Match the conventions already present in a repo (naming, formatting, structure) + rather than imposing new ones. +- Ask before doing anything destructive, hard to reverse, or outward-facing + (deleting files, force-pushing, publishing). Approval in one context does not + carry to the next. + +## Git + +- Do not commit or push unless explicitly asked. +- Never commit secrets or local-only config (`.env`, credentials, tokens). +- Follow the repo's own commit conventions where they exist (e.g. Conventional + Commits, changelog tags, issue references). Repo rules win on conflict. +- Otherwise, follow the seven rules of a great commit message + (https://cbea.ms/git-commit/): + 1. Separate subject from body with a blank line. + 2. Limit the subject line to 50 characters. + 3. Capitalize the subject line. + 4. Do not end the subject line with a period. + 5. Use the imperative mood in the subject line ("Add x", not "Added x"). + 6. Wrap the body at 72 characters. + 7. Use the body to explain _what_ and _why_ vs. _how_. +- Always end the commit message with a final line referencing the issue: + `Issue #XXX {actual issue title here}` — replace `XXX` with the issue number + and put the issue's real title inside the braces (e.g. + `Issue #142 {Fix login redirect loop}`). Look up the actual title rather than + guessing. + +## Editing + +- Make the smallest change that fully solves the problem; avoid unrelated churn. +- Run the project's formatter/linter before considering a change done. diff --git a/claude/config/settings.json b/claude/config/settings.json index 281781a..b737d3c 100644 --- a/claude/config/settings.json +++ b/claude/config/settings.json @@ -1,6 +1,10 @@ { "$schema": "https://claude.ai/schemas/claude-code/settings.json", + "alwaysThinkingEnabled": true, + "effortLevel": "high", + "skipAutoPermissionPrompt": true, "permissions": { + "defaultMode": "auto", "allow": [ "Bash(npm run test)", "Bash(npm run lint)", @@ -9,5 +13,48 @@ "Bash(gh pr view*)" ], "deny": ["Bash(sed *)"] + }, + "attribution": { + "commit": "" + }, + "spinnerVerbs": { + "mode": "replace", + "verbs": [ + "Seeking the Ocarina of Time", + "Collecting Korok seeds", + "Pulling the Master Sword", + "Solving the Water Temple", + "Charging a spin attack", + "Cooking a dubious meal", + "Bombing a suspicious wall", + "Playing Zelda's Lullaby", + "Paragliding off a cliff", + "Shattering pots for rupees", + "Climbing in the rain", + "Taming a wild horse", + "Walking into Mordor", + "Consulting the Palantír", + "Lighting the beacons of Gondor", + "Riding to Rohan", + "Second breakfasting", + "Following Gandalf's counsel", + "Whispering with the Ents", + "Sneaking past Shelob", + "Sailing to the Grey Havens", + "Holding the bridge of Khazad-dûm", + "Casting the Ring into the fire", + "Translating the Black Speech", + "Calibrating the hyperdrive", + "Consulting the Jedi Archives", + "Trusting the Force", + "Making the Kessel Run", + "Bullseyeing womp rats", + "Igniting a lightsaber", + "Negotiating with Hutts", + "Plotting a jump to lightspeed", + "Decrypting the Death Star plans", + "Rerouting power to shields", + "Listening to Master Yoda" + ] } } diff --git a/claude/install.sh b/claude/install.sh index 0ed7c29..b337969 100755 --- a/claude/install.sh +++ b/claude/install.sh @@ -28,16 +28,24 @@ if [ ! -d "$CLAUDE_CONFIG_DIR" ]; then mkdir -p "$CLAUDE_CONFIG_DIR" fi -# Symlink settings.json -if [ -f "$DOTFILES_CLAUDE_CONFIG/settings.json" ]; then - if [ -L "$CLAUDE_CONFIG_DIR/settings.json" ]; then - rm "$CLAUDE_CONFIG_DIR/settings.json" - elif [ -f "$CLAUDE_CONFIG_DIR/settings.json" ]; then - warn "Existing settings.json found, backing up to settings.json.backup" - mv "$CLAUDE_CONFIG_DIR/settings.json" "$CLAUDE_CONFIG_DIR/settings.json.backup" +# Symlink every file in config/ into ~/.claude/ (follows the nested-config +# pattern used by postgresql/newsyslog: leave an existing symlink alone, back +# up a real file before linking) +for src in "$DOTFILES_CLAUDE_CONFIG"/*; do + [ -f "$src" ] || continue + filename="$(basename "$src")" + target="$CLAUDE_CONFIG_DIR/$filename" + + if [ -L "$target" ]; then + info "${filename} already symlinked" + else + if [ -e "$target" ]; then + warn "${filename} exists and is not a symlink, backing up" + mv "$target" "${target}.backup" + fi + ln -s "$src" "$target" + success "Symlinked ${filename}" fi - ln -s "$DOTFILES_CLAUDE_CONFIG/settings.json" "$CLAUDE_CONFIG_DIR/settings.json" - success "Symlinked settings.json" -fi +done success "Claude Code configuration complete"