People ask me how I get things done solo. The short answer is good tooling. The longer answer involves a CLI coding assistant with a lot of configuration files.

I’ve spent the last few months setting up Claude Code as my primary helper for development work. Not by writing a framework or building an abstraction layer. Just by adding files to a .claude/ directory that give it context about my projects, my preferences, and my workflows. It’s still an assistant. I still make every decision. But it saves me hours of typing.

Here is what the setup looks like.

The directory structure

Everything lives in a single Git repo. The .claude/ directory is where the interesting stuff happens:

1
2
3
4
5
6
.claude/
  commands/     # 48 slash commands, organized by category
  agents/       # 18 specialized agent definitions
  rules/        # 22 behavioral rules (always loaded)
  hooks/        # 11 shell scripts triggered by events
  skills/       # 4 reusable knowledge files

Commands are shortcuts I type. /deploy kicks off a Trigger.dev deployment. /morning pulls together a daily briefing. /humanize cleans up text. /gemini-image generates images. There are 48 of them across 11 categories: content, analysis, media, devops, code, search, docs, comms, productivity, and a couple more. I wrote about how they work and the specific devops and Toggl categories.

Rules are things Claude reads automatically. Every conversation starts with 22 rule files loaded into context. They cover everything from “never edit .env files directly” to “always copy commands to clipboard using the clip script” to “use Tavily for factual questions, don’t rely on training data alone.” One rule file is just a list of banned words and phrases that make text sound like AI wrote it.

Agents

This is where it gets good. I have 18 agent definitions that work as specialized helpers. Each one is a markdown file that describes what the agent focuses on and how it should behave. I tell them what to do, they do the legwork, I review the result.

Some examples:

  • enterprise-app-specialist helps me debug production issues. I point it at the error and the infrastructure context. It digs through logs and configs, then gives me a summary with suggestions. I decide what to actually fix.
  • email-writer drafts emails in my voice. It knows my style preferences and that I sign off as tomakl. It shows me the full text, I edit if needed, approve, and it copies to clipboard.
  • server-command-advisor helps me build commands for remote servers. It looks up docs, suggests the right flags, and copies the command to my clipboard. I paste and run it myself.
  • deploy-verifier checks if a deployment went well. Container health, web endpoints, worker status.
  • vault-secret-rotator helps me audit and rotate secrets in HashiCorp Vault.

The agents don’t share the main conversation’s context window. That’s the design. Raw logs and search results stay in the agent context. I get a clean summary back.

Hooks

Hooks are shell scripts that fire on specific events. I have 11 of them.

The permission hook is the most important. It auto-approves read operations, search commands, and safe tools. It auto-denies rm -rf /, git push --force, and git reset --hard. Everything else gets a manual prompt. This means I can work fast without accidentally nuking something.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# permission-auto-approve.sh (simplified)
case "$TOOL" in
  Read|Glob|Grep) echo '{"decision":"approve"}' ;;
  Bash)
    case "$COMMAND" in
      *"rm -rf /"*) echo '{"decision":"deny"}' ;;
      *"git push --force"*) echo '{"decision":"deny"}' ;;
      # ... more patterns
    esac ;;
esac

Other hooks scan Bash output for leaked secrets, lint edited files, save git status when a session ends, and detect when I rate something (for tracking quality over time). There’s a pre-commit hook that catches AWS keys, private keys, and debug statements before they reach the repo.

The hardware

An NVIDIA Jetson with 8 GB of RAM sits under my desk. ARM64, running Ubuntu 22.04. It hosts:

  • Trigger.dev (10 Docker containers, self-hosted)
  • A GitHub Actions runner (self-hosted, picks up CI/CD jobs)
  • HashiCorp Vault (all secrets, auto-unseal on boot)
  • AdGuard Home (DNS-level ad blocking for the whole LAN)
  • Privoxy (HTTP-level ad blocking, about 103k filter rules)
  • Samba (NAS shares for file exchange between my PC and the server)
  • n8n (workflow automation)
  • This blog (Hugo in a Docker container, nginx on port 8090, more on how it works)

All of it behind a Cloudflare tunnel. No ports forwarded on the router. The subdomains just work.

Trigger.dev tasks

I self-host Trigger.dev on the Jetson and use it for background tasks that need to run on a schedule or on demand. 16 task files across several categories:

  • Blog automation (cover image generation, weekly news digest, publish notifications)
  • Incident monitoring
  • School messaging (yes, it sends messages to my kid’s teachers)
  • Driving license appointment checking (scrapes a government site)
  • Solar panel output tracking
  • Weekly AI news research

The tasks are TypeScript, deployed via GitHub Actions to the same Jetson. I have an MCP server for Trigger.dev, so I can trigger tasks, check run status, and deploy from inside a Claude Code session.

Secrets

All secrets live in Vault. The .env file, .mcp.json, and .env.local are generated files. I never edit them directly. A shell script called inject.sh reads from Vault and writes the config files. If I need a new API key, I add it to Vault and re-run the script.

1
2
3
vault kv put secret/services/telegram bot_token=xxx chat_id=yyy
scripts/vault/inject.sh
# .env now has TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID

The clipboard trick

This one is small but it changed how I work. A script called clip sends text to my Windows Terminal clipboard using the OSC 52 escape sequence. When the assistant suggests a command, it copies it to my clipboard. I alt-tab to the server terminal and paste. I’m the one who runs it.

It works because I’m SSH’d from Windows Terminal into the dev server. The escape sequence travels back through the SSH connection and hits the terminal emulator, which writes to the Windows clipboard. No X11 forwarding, no xclip, no tmux buffer gymnastics.

Writing rules

I keep a file called humanizer.md in my rules directory. It lists every pattern that makes text sound machine-generated. Banned words like “delve”, “crucial”, “landscape.” Banned constructions like “Not only…but…” and “It’s not just about…” Banned formatting like em dash overuse and bold labels on every list item.

Every piece of text I produce with AI help, whether it’s an email, a ticket, or a blog post, passes through these rules. The goal isn’t to hide that AI assisted. It’s to produce writing that doesn’t make your eyes glaze over. I still write the ideas. The assistant helps with the typing.

What it costs

I’m on the Claude Max plan. No token counting, no routing to cheaper models. The Gemini image generation is free tier. Vault is free. The Jetson was a one-time hardware purchase. Trigger.dev is self-hosted so there’s no SaaS fee. The only recurring costs are the Claude subscription and the domain.

Is it worth the effort

The .claude/ directory has about 120 files in it. That’s a lot of configuration for a coding assistant. But each file exists because I hit a problem and solved it once. The permission hook exists because I accidentally ran a destructive command. The humanizer exists because I got tired of editing out “delve” from every email. The agent definitions exist because raw log output was eating my context window.

It’s not a product. It’s a workbench. And like any good workbench, the tools are where I left them.