Better, Faster, and (Even) More

I’ve never built more interesting, random, and useless scripts, tools, and services than I have in the last six months. The cost to go from “Random Thought” to “Working Something” has never been lower thanks to Claude Code. However, this increase in speed has only made my desire to move faster and more efficiently higher.

The following is a set of tools and practices I’ve gathered over the last 90 days, which continue to accelerate my process and give me daily joy.

How I Organize

Everything lives under ~/Projects/. Each project is its own git repo with its own CLAUDE.md (project-specific instructions) and WORKLOG.md (session history). Three repos do special duty:

dotfiles — Machine configuration. Shell config, terminal config, Claude Code settings, skills, and status line script all live here and get symlinked to where the system expects them (~/.zshrc, ~/.claude/settings.json, ~/.config/ghostty/config, etc.). Checked into git so every machine stays in sync with a pull.

credentials — A private repo for API keys and secrets, kept separate from project code.

scripts — Standalone CLI tools added to PATH. Things like fresh (repo health checker), gpush (one-command commit and push), and ghostty-font (font switcher).

Every project gets two files: CLAUDE.md and WORKLOG.md. CLAUDE.md is instructions and reference — how to build, deploy, what patterns to follow, where things live. It rarely changes. WORKLOG.md is the session diary. Every time Claude and I work on a project, it logs what we investigated, what changed, what we decided, and why. When I come back days or weeks later, Claude reads the worklog and picks up where we left off instead of starting cold.

Copy to Clipboard

Claude generates a lot of stuff that I cut and paste, but the initial problem was that copying from Ghostty included unavoidable leading spaces on output. The fix? Have Claude paste text straight to the clipboard via macOS pbcopy1. Also, depending on where I am posting (mail, Slack, messages), I have Claude format appropriately before pasting2.

Screenshot to Clipboard

It is often much faster to just dump a screenshot into Claude Code rather than describe the issue. I used to grab a screenshot and then cut and paste it from my Documents directory. Too slow. F12 grabs a region of the screen and puts it on the clipboard so I can paste. Configured in macOS System Settings > Keyboard > Shortcuts3.

Check My Setup

I move between three machines a lot, and given that the state of the art is changing, well, daily, a day working on one machine means that my local config has improved THAT DAY, which means when I move to a new machine, I want to update the setup.

I have a single script that validates my entire Mac setup. Checks 30+ items across categories: core tools (Homebrew, Python, Node, Ghostty, Claude Code), shell config (zsh default, oh-my-zsh), symlinks (.zshrc, .gitconfig, Ghostty config), SSH (key, agent, keychain), credentials, and coding fonts. Reports green/yellow/red per item. When things are missing, prints fix commands in dependency order — SSH before git config, Homebrew before everything that needs brew install.

# This is an example
# Check Claude Code global settings.json

if [ -f "$HOME/.claude/settings.json" ]; then
settings_issues=""
if ! grep -q "alwaysThinkingEnabled.*true" "$HOME/.claude/settings.json"; then
settings_issues="thinking"
fi
if ! grep -q "statusLine" "$HOME/.claude/settings.json"; then
settings_issues="${settings_issues:+$settings_issues, }statusLine"
fi

if [ -z "$settings_issues" ]; then
print_row "Claude Code settings" "${GREEN}✓ Configured${NC}" "Thinking + status line enabled"
else
print_row "Claude Code settings" "${YELLOW}⚠ Incomplete${NC}" "Missing: $settings_issues"
missing_items+=("claude-settings")
fi
else
print_row "Claude Code settings" "${RED}✗ Missing${NC}" "~/.claude/settings.json"
missing_items+=("claude-settings")
fi

# This is an example
# Check Claude Code global settings.json

if [ -f "$HOME/.claude/settings.json" ]; then
settings_issues=""
if ! grep -q "alwaysThinkingEnabled.*true" "$HOME/.claude/settings.json"; then
settings_issues="thinking"
fi
if ! grep -q "statusLine" "$HOME/.claude/settings.json"; then
settings_issues="${settings_issues:+$settings_issues, }statusLine"
fi

if [ -z "$settings_issues" ]; then
print_row "Claude Code settings" "${GREEN}✓ Configured${NC}" "Thinking + status line enabled"
else
print_row "Claude Code settings" "${YELLOW}⚠ Incomplete${NC}" "Missing: $settings_issues"
missing_items+=("claude-settings")
fi
else
print_row "Claude Code settings" "${RED}✗ Missing${NC}" "~/.claude/settings.json"
missing_items+=("claude-settings")
fi
Bash

Uncommitted Changes / Or Fresh

I have an oh-my-zsh git plugin with the robbyrussell theme. The prompt shows a yellow ✗ when the working tree has uncommitted changes. No custom config — it’s the default behavior of that theme’s git_prompt_status function.

For times when I forget, I have a script called Fresh that walks through my entire Project directory and reports uncommitted changes, unpushed commits, and stale repos across all projects. One command to answer: “Did I forget to push something before switching machines?”

Memories vs. Skills vs. Hooks

Memories (~/.claude/projects/<project>/memory/): Persistent notes Claude saves between sessions per project. Things like “this user prefers terse responses” or “the auth rewrite is driven by compliance, not tech debt.” Claude reads them at the start of each conversation to pick up context that it would otherwise lose. They’re markdown files with frontmatter (type, description) indexed by a MEMORY.md file. Types: user preferences, feedback/corrections, project context, external references. Checked in alongside my project, and by far the largest timesaver for building context.

Skills (~/.claude/skills/<name>/SKILL.md): Reusable prompt templates invoked with /skillname. A skill defines a multi-step procedure Claude follows — like a macro. Example: /floyd loads a voice definition file, then rewrites whatever content I have in that voice. Skills don’t execute code themselves; they inject instructions into the conversation that Claude follows. I have skills for blog posts, podcasts, recurring expenses, and a lot more.

Hooks (settings.json → "hooks"): Shell commands that fire automatically on Claude Code events like tool use or end of response. I don’t use them yet, but they’re there for automation — things like running a linter after every file edit or logging tool usage.

Statusline

Claude Code has a configurable status line at the bottom of the terminal. Mine runs a bash script that renders three lines of live data:

The rate limit data comes from Anthropic’s usage API, authenticated via an OAuth token pulled from the macOS Keychain. It caches the response for 60 seconds, so it doesn’t slow down every render4.

Ghostty Tab Title

I’m usually working on several projects at once, so at-a-glance tabs are essential. I have a claude() wrapper in .zshrc:

claude() {
printf '\033]0;Claude: %s\007' "${PWD##*/}"
CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 command claude "$@"
printf '\033]0;%s\007' "${PWD##*/}"
}

claude() {
printf '\033]0;Claude: %s\007' "${PWD##*/}"
CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 command claude "$@"
printf '\033]0;%s\007' "${PWD##*/}"
}
Bash

Sets the Ghostty tab title to “Claude: projectname” when Claude starts, suppresses Claude’s own title management via the env var, and restores the tab to just the project name on exit.

I’ve written this up entirely because I am certain others have found equally satisfying improvements, and I want to know what they are.

UPDATE: Tips from Readers

Since publishing, readers have shared helpful tips that I’ve incorporated into my workflow:

Per-project terminal colors. Most modern terminals let you set background colors per profile or directory. I now have different colors for different projects — green for one, blue for another. It sounds minor, but it’s a surprisingly effective context signal when you’re bouncing between windows.

Tuning tool permissions. Claude Code asks permission before running shell commands, which is safe but slow. I had Claude review the commands I run regularly, filter out anything destructive, and approve the rest in the project’s .claude/settings.json. Game-changer — sessions move noticeably faster when you’re not clicking “Allow” every few seconds.

/copy for grabbing output. The /copy slash command copies Claude’s last response directly to your clipboard. Cleaner than selecting and copying manually, especially for long responses.

Worklog trimming. I wrote a persistent instruction that tells Claude how to compress my worklog files. The rule: delete anything recoverable from git history or the current code, condense old completed work, but keep open questions, key decisions, and active experiments. This keeps the context window focused on what actually matters rather than filling it with stale history.

Windows equivalent: clip, e.g., echo hello | clip

Also, I have since learned there is a /copy command in Claude

On Windows: Win+Shift+S opens the Snipping Tool for region capture to clipboard.

Currently rocking the IBM Plex Mono — more on this shortly