claude-computer
GitHub

A GitHub template · MIT

Mac + Claude.
Minus the cruft.

A GitHub template that sets up a Mac for a solo developer. It assumes you have a Claude Max subscription and like terminal-first development in Claude Code — you step in for the key decisions, judgement and taste. Mac + Claude is the best combination IMO. The point is to get things done FAST, by cutting the time you spend on cruft.

  • you authenticate
  • you set the mode
  • you decide
Terminal.app
# one command
$ /bin/bash -c "$(curl -fsSL https://claude-computer.com/install.sh)"

# or the four commands by hand — see Quick start

then paste docs/FIRST-PROMPT.md

01

The idea

The usual order

  1. Set up the machine
  2. Install your tools
  3. Maybe add an AI assistant to help you code

This order

  1. Xcode command line tools, Homebrew, gh, Claude Code
  2. Hand it the machine
  3. Everything else is a conversation

It's part stack (Claude + Tailscale + GitHub + Bitwarden + Cloudflare + Obsidian + Homebrew), part organization (an opinionated take on folders and repos), part process (slash commands, hooks, scheduled jobs) — all designed to take advantage of the Mac + Claude combination.

I built this after spending a year arriving at a stack, pattern and process that has let me up my output exponentially. All the things a solo dev ends up losing an afternoon to — install this, configure that, why is this port open, set up the new box in the cupboard, rotate this key — go to Claude instead. Install the operator first and the rest follows. A coding assistant sees one repo. An operator sees the system the repos live in: which machine this is, what's installed, where secrets come from, how things sync, what runs on a schedule. Give it that context once, written down in files it maintains, and every later session — including every coding session — starts from a true picture instead of a guess.

It is opinionated and reflects my learnings, taste and judgement. Change what doesn't fit.

The three jobs you keep

Authenticate
Every login, every password typed, every OAuth consent screen, every "allow" on a macOS permission prompt. Claude never handles a credential.
Set the mode
Claude Code runs in auto mode: a classifier model reviews each action instead of you, and your ask and deny rules still hold. Never bypass permissions.
Decide
Claude proposes; you choose. Anything destructive, anything touching credentials, anything that costs money — it asks first, every time.
02

How it works

Three parts. The stack is what gets installed. The organization is where things live — folders, one repo per project, a brain per folder, a vault for the notes, a file per machine. The process is what runs without you thinking about it — slash commands, hooks, scheduled jobs.

The stack

Claude Code is the operator. GitHub holds every repo, including the fleet brain that syncs between machines. Tailscale is how they reach each other (read about my fleet). Bitwarden is the only secret store. Cloudflare R2 is cold storage, no egress fees. Obsidian is the second brain — plain markdown in a git repo, so the notes stay as portable as the code. Homebrew installs the rest, from Brewfiles layered by role. Nothing exotic — each piece earns its place by being drivable from a terminal.

The map, and map-check

The home directory gets a handful of top-level folders — projects, products, personal, vault, archive, library. They are containers, not repos; repos live one level down, one per project, never nested. Then one file per machine records what is installed, what is listening, what is scheduled, where the keys live (never the keys). bin/map-check diffs those sections against reality — brew leaves, the LaunchAgents directories, lsof, the VS Code extension list — and then runs security-check. Drift is a bug: fix the machine or fix the map, in the same session.

Diagram of the home directory: claude-computer, projects, products, personal and vault sync with git to GitHub; archive, library/camera and library/books sync one-way to Cloudflare R2; resources syncs two-way, encrypted. Manager machines on a Tailscale tailnet reach headless boxes over SSH. Bitwarden feeds every script; a Telegram bot receives from every machine.
Where everything lives, and the one way each folder leaves the machine. Scroll sideways to read it all.

The session loop

~/claude-computer is your private repo, cloned on every machine that runs Claude Code. The SessionStart hook pulls with --rebase --autostash and reports whether Bitwarden is unlocked. The Stop hook commits any docs/ change as [host] update … and pushes, at the end of every turn — because sessions get killed far more often than they get exited. Each machine writes only its own file, so conflicts are rare by construction and DECISIONS.md is append-only, so it always merges.

The session loop: the SessionStart hook pulls the repo and checks Bitwarden; Claude orients by reading CLAUDE.md, the machine file and FLEET.md; work happens; changes are recorded in the machine file, DECISIONS.md and TASKS.md; the Stop hook commits docs as [host] and pushes.
Hooks do the syncing, not discipline.

Trust

Auto mode is only sane with guard rails. git push, rm, rclone, sudo and the storage scripts sit on the ask list, which prompts even in auto mode; force-push, raw bw get and reading browser profiles sit on the deny list, which blocks in every mode. One SSH key per machine, generated on it and never copied. Bitwarden is the only secret store — no .env with keys, no rclone.conf with credentials on disk, no secret on a command line. Time Machine is the net: auto mode on a machine you care about needs a whole-machine rollback.

CLI first, MCP last

An MCP server loads its full tool schemas into every session's context, whether you use it or not. So each service gets a thin wrapper in bin/ instead — tavily, exa, firecrawl, jina, browse, gcal, gmail, gdrive — that reads its key from Bitwarden and prints markdown. Standing context cost: one paragraph in CLAUDE.md. MCP is reserved for things that are stateful or OAuth-bound in a way a wrapper can't handle.

A brain per folder

Any folder that needs automation gets its own CLAUDE.md — a brain — and a TASKS.md. You start Claude where the work is; that brain says what to do here and points at the fleet repo for what the system looks like. archive/ archives and retrieves. library/camera ingests cards and finds photos by metadata. Folders that just hold files have no brain.

The Second Brain, filed by Claude

Obsidian is the second brain — plain markdown in a git repo — but Claude does the filing. PARA was designed for a human doing the filing. With Claude doing it, the constraint flips: capture should cost nothing, and filing, linking and retrieval are Claude's job. So the vault is built for cheap capture and for Claude finding and connecting things, not for where a person would browse. Everything lands in inbox/. notes/ is flat — structure lives in properties, not folders. Tasks stay in the TASKS.md of the brain that owns them and the vault gets read-only copies, so ticking a box in Obsidian changes nothing. Voice and reading arrive on their own; /inbox files what's there.

How the vault works

If it can be a script, it is one

Slash commands are for steps that need judgment, and they orchestrate scripts rather than reimplement them. Hooks are for what must happen every time. Scheduled launchd jobs are for what must happen without a session. Everything deterministic lives in bin/, answers --help, and returns exit codes instead of prose.

03

What this isn't

Read this before you run it on a machine you care about.

  • It is my opinionated setup, not a neutral framework. Bitwarden, Tailscale, Cloudflare R2, Obsidian, Ghostty, Homebrew. Swap what doesn't fit — but you are swapping, not configuring.
  • Permission rules are pattern matches, not a sandbox. The ask and deny lists are string and glob rules on commands; auto mode adds a classifier on top. Both reduce prompts and mistakes. Neither is a security boundary, and nothing here contains a program that has already decided to do something else.
  • macOS first; Linux is thin. Headless Linux boxes are managed over SSH, but /setup, the Brewfiles and the macOS defaults assume a Mac.
  • It expects you to keep doing the three jobs. If you turn on bypass permissions, skip Time Machine, or let the map drift, none of the rest of this helps you.
  • It is young. I have run this approach on my own machines for about a year; the template is that approach written down. /setup has been dry-run and read end to end. If you try it, I would love to see your /setup report.

The Trust section of the README is the part to read closely: README · Trust

04

Quick start

Before you start

  • A Mac on a recent macOS.
  • A GitHub account.
  • A Claude Max subscription. All-day sessions in auto mode are the whole point, and they outrun anything smaller.
  1. Install the operator

    One command in stock Terminal.app. It checks what you already have — Xcode command line tools, Homebrew, gh, Claude Code — installs whatever is missing, and hands over.

    /bin/bash -c "$(curl -fsSL https://claude-computer.com/install.sh)"

    read it first — curl -fsSL https://claude-computer.com/install.sh | less
    see what it would do — add -- --dry-run

    It asks one question: what your private repo should be called. Take the default and you get <you>/claude-computer cloned to ~/claude-computer — and that is one repo for every machine you own, so on a second machine you run the same command and it clones that repo instead of creating another. Want a different name? I called mine sys-admin: -- --name sys-admin --dir ~/claude-computer, the same on every machine (why, and what happens if you get it wrong).

  2. Hand over

    The installer has already put this prompt on your clipboard. Log in to Claude Code and check the status line reads ⏵⏵ auto mode on (Shift+Tab cycles modes). Then paste the first prompt and do what it asks: log in, grant, decide.

    You are the operator for this computer, my network and the devices on it. Your
    brain is this repo: read CLAUDE.md now and follow it.
    
    Start with this computer. This is a new machine, so run /setup:
    
    1. Identify this machine (hostname, hardware, macOS version). Tell me the
       hostname you will use as its name in the fleet and let me confirm it or
       rename the machine first. Then ask me its role (client, build, server) and a
       one-line purpose. Write docs/machines/<host>.md from
       docs/machines/_example.md, add it to docs/FLEET.md, and append the decision
       to docs/DECISIONS.md.
    2. Create an SSH key for this machine only, add it to GitHub with gh, and push
       this repo.
    3. Install Tailscale and walk me through logging in. Record the
       Tailscale name in the map.
    4. Install the Bitwarden CLI and walk me through `bw login`. Confirm
       bin/secrets-unlock works.
    5. Link claude-global/ into ~/.claude so the hooks and commands are live.
    6. Install the Brewfile layers for this role, link dotfiles, run
       macos-defaults.sh. Tell me before each step that needs a password or a
       macOS permission prompt.
    7. Run bin/map-check and bin/security-check, fix what fails, and update the map.
    
    Rules for the whole session: ask before anything destructive, anything that
    touches credentials, and anything that costs money. I will do every login and
    every step that handles a password myself. Record every decision we make in
    docs/DECISIONS.md. When something is deferred, put it in TASKS.md under Later.
    At the end, commit and push docs/ and tell me what is left.
Or do it by hand

The same thing, typed yourself: the installer runs exactly these, checking each first.

xcode-select --install
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install gh && gh auth login
brew install --cask claude-code

After the Homebrew installer finishes, run the shellenv lines it prints — nothing else works until brew is on your PATH.

Your instance is a private repo made from the template, cloned into your home directory.

cd ~ && gh repo create claude-computer --template narendranag/claude-computer --private --clone
cd ~/claude-computer && claude

A second machine is much shorter: the same one-line installer, with the same repo name — it finds the repo already there and clones it instead of creating a second one — and then /setup, which reads the repo, finds everything already decided, and asks only what is specific to this machine. By hand it is gh repo clone <you>/claude-computer ~/claude-computer in place of creating from the template.

05

Help wanted

This is the point where it stops being one machine's setup. The most useful thing you can send me is what happened when you ran /setup on yours.

  • Setup reports What broke, what asked for a password it shouldn't have, what map-check got wrong on your hardware and macOS version.
  • Other cameras The camera brain reads my RAW workflow. Other bodies, other card layouts, other sidecar conventions.
  • Linux Headless boxes are managed over SSH today. A real Linux /setup — packages, dotfiles, the security baseline — is the biggest open gap.
  • Equivalents 1Password instead of Bitwarden, Backblaze instead of R2, WireGuard instead of Tailscale, iTerm2 instead of Ghostty — as clean swaps, not forks.
  • Another agent Fork it for Codex, Gemini CLI or a local model. The brains are markdown and the work is in bin/, so most of it ports. Tell me and I'll link it here.
06

Who's behind this

I'm Narendra. Twenty-eight years at the intersection of journalism, digital and streaming, and I now run Marain, an operator's practice — most advisors leave a deck, I leave a system that runs. I write about media, attention and the industries that shape how we spend it at narendranag.com. For the last year I've spent 90% of my time in Claude Code and the terminal, with a laptop, a Mac Studio running Qwen, a Mac Mini, a Hetzner VPS (managed entirely by Claude) and a Pi — all set up and run by Claude. This template is that setup, written down.