My Claude Code Setup
I use Claude Code for 100% of my dev workflows now. Haven't manually written a line of code in ages. At this point, writing code by hand feels like fighting an eldritch horror from Elden Ring, except less satisfying. Claude just... works. And it's endlessly customizable.
Full disclosure: I wrote this post, but I'm also the subject of it. Every word here was generated by Claude Code—including this disclaimer. My human counterpart provided the direction; I handled the typing.

Terminal: Ghostty + Zellij
I run Claude Code inside Ghostty with Zellij as a multiplexer.
Ghostty is GPU-accelerated and noticeably snappier than iTerm2 or Terminal, especially when Claude is streaming long outputs. Zellij lets me run multiple Claude instances side by side (different tasks, different repos) and serializes sessions to disk. I can close my laptop and pick up exactly where I left off.
My Ghostty config (~/.config/ghostty/config):
1font-family = "R Plex Mono"2font-size = 19.03font-thicken = true4theme = ayu5macos-option-as-alt = true6copy-on-select = true7scrollback-limit = 500008cursor-style = bar9cursor-style-blink = false
The macos-option-as-alt bit is important because Zellij uses Alt-based shortcuts. Large scrollback helps when reviewing Claude's longer outputs.
Zellij config (~/.config/zellij/config.kdl) is mostly default. The important additions:
1session_serialization true2serialize_pane_viewport true3scrollback_lines_to_serialize 5000
Worktrees with ccwt
When I need to work on multiple branches simultaneously (feature branch and a hotfix, say), I use a small script called ccwt that launches Claude Code in a temporary git worktree:
1ccwt feature/new-auth
Why not just use git worktree directly? Mostly convenience. ccwt handles worktree creation, directory setup, and Claude launch in one step. Worktrees go in /tmp so my main repo stays clean. When Claude exits, the worktree gets cleaned up automatically. And any flags I pass get forwarded to Claude, so ccwt main --dangerously-skip-permissions just works.
Combined with Zellij panes, I can have separate Claude sessions working on completely different branches of the same repo without any git stashing or context switching.
Modern CLI Tools
I've replaced most of the default unix tools with faster, prettier alternatives. Mostly because I like pretty things, partly because Claude can use them too.
- eza -
lswith icons and git status - bat -
catwith syntax highlighting - fd - faster
find - zoxide - smarter
cdthat learns your habits - fzf - fuzzy finder for everything
- atuin - shell history that syncs across machines
- yazi - TUI file manager
- starship - minimal prompt with git info
- gum - pretty CLI prompts for scripts
When I tell Claude to explore a directory or search for files, it often reaches for fd or rg instead of the slower built-ins.
Sound Notifications
When Claude finishes a task or needs my attention, I want to know without staring at the terminal. Simple hooks:
1"hooks": {2 "Stop": [3 {4 "matcher": "",5 "hooks": [6 {7 "type": "command",8 "command": "afplay /System/Library/Sounds/Hero.aiff"9 }10 ]11 }12 ],13 "Notification": [14 {15 "matcher": "",16 "hooks": [17 {18 "type": "command",19 "command": "afplay /System/Library/Sounds/Submarine.aiff"20 }21 ]22 }23 ]24}
Stop fires when Claude completes work. Hero.aiff is a satisfying triumphant chime. Notification fires when Claude pauses for input. Submarine is a gentle nudge. macOS has a bunch of built-in sounds in /System/Library/Sounds/ to choose from.
Status Line
I wanted my status line to look more like my shell prompt. This shows user@host, current directory, git branch, and active Python virtualenv:
1"statusLine": {2 "type": "command",3 "command": "d=$(basename \"$(pwd)\"); g=\"\"; if git rev-parse --git-dir >/dev/null 2>&1; then b=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null); if [ -n \"$b\" ]; then g=$(printf \" \\033[36m(%s)\\033[0m\" \"$b\"); fi; fi; v=\"\"; if [ -n \"$VIRTUAL_ENV\" ]; then v=$(printf \" \\033[32m(%s)\\033[0m\" \"$(basename \"$VIRTUAL_ENV\")\"); elif [ -n \"$CONDA_DEFAULT_ENV\" ]; then v=$(printf \" \\033[32m(%s)\\033[0m\" \"$CONDA_DEFAULT_ENV\"); fi; printf \"\\033[2m%s@%s\\033[0m \\033[34m%s\\033[0m%s%s\" \"$(whoami)\" \"$(hostname -s)\" \"$d\" \"$g\" \"$v\""4}
Ugly one-liner, but it gives you rishitv@mac my-project (main) (venv) at a glance.
Spinner Verbs
Claude Code lets you replace the default loading messages with custom ones. It's called spinnerVerbs. Purely cosmetic, zero utility, I love it.
You're heads-down debugging something, grinding through it, and then "Quirrelling" flashes by. Or "Simply walking in". Or "Just as planned" appears right before Claude suggests exactly what you were hoping for. Snaps you out of the trance for a second, brings a smile, and you carry on.

My current list:
1SCIENCE!-ing2Updating priors3Applying Bayes4Noticing confusion5Making beliefs pay rent6Steelmanning7Noticing skulls8Reversing stupidity9Calibrating10Approximating CEV11Consulting dark side12Level 3 plotting13Going one higher14Time-turning15Quirrelling16Outside viewing17Trying finger, but hole18Touching grace19Git gud20Vigor checking21Hidden path ahead22Liar ahead23Fort, night24Summoning mimic25Reading item lore26Try jumping27Message appraising28Rune farming29Parrying it30Quoting papa31For those who come after32Taking hobbits to Isengard33Simply walking in34Petting the precious35Tossing dwarves36Boiling 'em, mashing 'em37Scarf wrapping38Rumbling39Reaching the basement40Tatakae-ing41Morse coding gravity42Transcending spacetime43Setting humor to 75%44Come on, TARS45Ding ding ding-ing46Adjusting tie47Bitch-ing48Cooking, Jesse49Knocking50Eating apples51Just as planned52Taking a potato chip53Questioning authority54Advertising courier services55Achieving perfect run56Quicksaving57Aranea networking58Noting for next loop59Refining macro data60Praising Kier61Meaning emerging62Self-referencing63Strange looping64Amaze!-ing65Running Crysis66Maximum armor67Bonfire lit68Praising the sun69Mikiri countering70Henry's come to see us71Reading in progress72Jesus Christ be praised73Feeling quite hungry74Petting Cerberus75Dragging76Rushing77Not quite my tempo78Soul editing79Leveling up80Min-maxing81Shard communicating82"I can explain"83Being reasonable84Double jumping85Putting ambitions to rest86Grafting87Defeating Malenia88Solo'ing her89Behold, dog!90Remembrall glowing91Drinking Comed-Tea92Breaking into Azkaban93Solving death
These go in ~/.claude/settings.json under spinnerVerbs with mode: replace.
Plugins
A few community plugins I use:
- commit-commands - git workflow shortcuts
- pr-review-toolkit - code review helpers
- agent-sdk-dev - for building Claude Agent SDK apps
- ralph-loop - autonomous coding loops
1"enabledPlugins": {2 "pr-review-toolkit@claude-code-plugins": true,3 "agent-sdk-dev@claude-code-plugins": true,4 "commit-commands@claude-code-plugins": true,5 "ralph-loop@claude-plugins-official": true6}
Other Settings
1"model": "opus",2"alwaysThinkingEnabled": true
Opus is slower but noticeably better for complex reasoning. Extended thinking lets Claude work through problems step by step before responding. Makes a real difference for debugging and architecture decisions.
All of this lives in ~/.claude/settings.json. The Claude Code docs cover the full schema, but honestly the best way to figure out what works for you is to just experiment.