· 6 min read

My Claude Code Setup

aidiy

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.

My Claude Code setup - multiple panes in Zellij with parallel Claude sessions

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.0
3font-thicken = true
4theme = ayu
5macos-option-as-alt = true
6copy-on-select = true
7scrollback-limit = 50000
8cursor-style = bar
9cursor-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 true
2serialize_pane_viewport true
3scrollback_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 - ls with icons and git status
  • bat - cat with syntax highlighting
  • fd - faster find
  • zoxide - smarter cd that 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.

Touching grace...

My current list:

1SCIENCE!-ing
2Updating priors
3Applying Bayes
4Noticing confusion
5Making beliefs pay rent
6Steelmanning
7Noticing skulls
8Reversing stupidity
9Calibrating
10Approximating CEV
11Consulting dark side
12Level 3 plotting
13Going one higher
14Time-turning
15Quirrelling
16Outside viewing
17Trying finger, but hole
18Touching grace
19Git gud
20Vigor checking
21Hidden path ahead
22Liar ahead
23Fort, night
24Summoning mimic
25Reading item lore
26Try jumping
27Message appraising
28Rune farming
29Parrying it
30Quoting papa
31For those who come after
32Taking hobbits to Isengard
33Simply walking in
34Petting the precious
35Tossing dwarves
36Boiling 'em, mashing 'em
37Scarf wrapping
38Rumbling
39Reaching the basement
40Tatakae-ing
41Morse coding gravity
42Transcending spacetime
43Setting humor to 75%
44Come on, TARS
45Ding ding ding-ing
46Adjusting tie
47Bitch-ing
48Cooking, Jesse
49Knocking
50Eating apples
51Just as planned
52Taking a potato chip
53Questioning authority
54Advertising courier services
55Achieving perfect run
56Quicksaving
57Aranea networking
58Noting for next loop
59Refining macro data
60Praising Kier
61Meaning emerging
62Self-referencing
63Strange looping
64Amaze!-ing
65Running Crysis
66Maximum armor
67Bonfire lit
68Praising the sun
69Mikiri countering
70Henry's come to see us
71Reading in progress
72Jesus Christ be praised
73Feeling quite hungry
74Petting Cerberus
75Dragging
76Rushing
77Not quite my tempo
78Soul editing
79Leveling up
80Min-maxing
81Shard communicating
82"I can explain"
83Being reasonable
84Double jumping
85Putting ambitions to rest
86Grafting
87Defeating Malenia
88Solo'ing her
89Behold, dog!
90Remembrall glowing
91Drinking Comed-Tea
92Breaking into Azkaban
93Solving 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": true
6}

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.