Always-On AI Infrastructure
Your AI cofounder,
always on.
A Mac running Claude Code 24/7. DM it in Slack, it responds with full access to your codebase, tools, and context. $200/month. You own the whole stack.
This guide walks you through the hardware and software setup. It comes with a companion repo — starter CLAUDE.md, identity system, plugin marketplace with skills for inbox management, brainstorming, and image generation. You'll install it all in the final step.
The idea
Take a spare Mac, install Claude Code, wire it to Slack, and let it run 24/7. Your AI cofounder gets full access to your codebase, your tools, your business context. DM it a question at midnight, get a thoughtful answer with code changes attached. The kind of setup that benefits enormously from an always-on AI handling the routine stuff.
The experiment: can an always-on AI cofounder meaningfully accelerate a small team? Not by doing busywork — by doing everything. Product development, customer support, log investigation, marketing asset creation, conversion optimization, onboarding automation, content writing, A/B testing, bug fixes, feature builds. The infrastructure is a Mac, Claude Code on a $200/mo Max subscription, and Slack as the interface. The question isn't whether it can help — it's how far you can push it.
Why Claude Code and not the API? Anthropic's ToS prohibit using a Max subscription with third-party tools. Claude Code is Anthropic's own CLI — running it via a Slack bot is fully compliant. Flat $200/mo for Claude Opus instead of unpredictable API bills.
"But isn't CLI mode limited?"
No. This is the most common concern — that running Claude Code headlessly via claude -p is a stripped-down version. It's not. The CLI has near-complete feature parity with interactive Claude Code. Here's what your AI cofounder gets:
Launches multiple agents in parallel — Explore, Plan, general-purpose. Same Agent tool as interactive mode.
All configured MCP servers connect and work — Slack, Gmail, Google Drive, custom tools. No limitations.
Reads CLAUDE.md, auto-memory system, persists knowledge across sessions. Learns and remembers.
Bash, Edit, Read, Write, Glob, Grep, WebFetch, WebSearch, Chrome automation. Everything.
Resume conversations with full context via --resume. Thread-based memory in Slack.
Custom plugins, marketplace plugins, skill context — all injected and available in CLI mode.
What's interactive-only? Just the UI stuff: slash commands (/commit, /init), permission dialogs, vim mode, voice dictation, and the visual task list. None of which apply to a Slack bot. The core AI — tools, agents, memory, MCP, context — is identical.
Anthropic ships new features to both modes simultaneously. When they release something task-based (new tools, agent improvements, model upgrades), it works in -p mode. The only features that stay interactive-only are UI/interaction elements that don't make sense headlessly. ~95% parity — and the missing 5% is irrelevant for this use case.
How it works
Concepts explained
For when you want to understand what's actually going on. Click to expand.
Do you need it? Yes — for quick admin from your main machine without walking over, and essential when you're away from home. Combined with Tailscale, you can SSH into your Mac from anywhere.
Why do you need it? At home, you can SSH using the local network. But the moment you step out — a coffee shop, a co-working space, travelling — your home network is unreachable. Tailscale makes your Mac accessible from anywhere in the world, securely, without exposing anything to the public internet. Free for personal use.
Analogy: If SSH is a phone call, Tailscale is the phone network. SSH needs a way to reach your Mac — at home that's your WiFi, but outside the house, Tailscale provides that path.
Why do you need it? When you SSH into your Mac and start an interactive Claude Code session, you want it to keep running even if your connection drops. tmux makes that possible. Detach with Ctrl+B then D, reattach with
tmux attach -t claude.
Why do you need it? This is what makes the Slack bot truly always-on. Bot crashes at 3am? launchd restarts it in seconds. Mac reboots after a power blip? launchd starts the bot automatically. No human intervention.
bot.yourdomain.com) at the tunnel, and Cloudflare routes traffic through it to your local machine. HTTPS, DDoS protection, and auto-retries — all free.
Why not Socket Mode? Most Slack tutorials use "Socket Mode" — a WebSocket connection that avoids needing a public URL. But WebSocket connections are fragile: they drop on network blips, hit idle timeouts, and need reconnection logic. The production standard is HTTP Events API — Slack sends stateless HTTP requests to your URL. Each event is independent. If one fails, Slack retries. Much more robust. Cloudflare Tunnel gives you the public URL you need to use this approach.
claude command-line tool. When the Slack bot receives a message, it runs claude -p "your message" — giving Claude access to your codebase, CLAUDE.md context, and any tools you configure. Powered by the $200/month Max subscription — flat rate, no per-message costs.
Why not the API? The CLI inherits everything — your project context, installed tools, plugins. The API would require rebuilding all of that. Plus, Max is flat-rate vs unpredictable API billing.
Why use it? Optional but nice to have. If you frequently SSH into your Mac from unstable connections (coffee shops, mobile hotspots), Mosh eliminates the frustration of broken pipes. Install with
brew install mosh on both machines.
For your product: this would include your architecture, database schema highlights, deployment process, common maintenance tasks, how to check analytics, support response templates, and anything else your AI cofounder needs to know to be effective.
Hardware setup
Factory reset and configure your Mac for always-on use. ~30 minutes.
Before you start
You're setting up a dedicated Mac as an always-on server. Factory reset it, configure it to stay awake with the lid closed, and get the basic software installed. This phase gets the hardware ready — then you'll wire up the Slack bot.
1. Factory reset
- Back up anything worth keeping from the old install
- Go to System Settings → General → Transfer or Reset → Erase All Content and Settings
Heads up: This takes ~15-20 minutes. The Mac will restart and walk you through setup like it's brand new. Keep it plugged in and connected to WiFi.
- Go through the macOS setup wizard — create a user account (e.g., bot)
Tip: Pick a short username — you'll type it every time you SSH in (
ssh bot@...). - Sign in with your existing Apple ID (needed to download Tailscale from the App Store — no reason to create a new one)
- When asked about FileVault (disk encryption): skip it / turn it off
If the Mac restarts after a power loss, FileVault shows an unlock screen that needs a keyboard. Since it might restart unattended (lid closed), skip encryption so it boots straight to the desktop.
2. System Settings checklist
Open System Settings and configure each:
- Prevent automatic sleeping when the display is off — ON
- Wake for network access — ON
- Optimized Battery Charging — ON (protects battery while plugged in 24/7)
- Remote Login (SSH) — ON (so you can manage it from your main machine without opening the lid)
- Screen Sharing — ON (full desktop access from another Mac on the same network)
- Automatic login — set to the user account you created
- Require password after screen saver — Never (so Screen Sharing works without auth prompts)
3. Install Tailscale
Tailscale lets you access the dedicated Mac from anywhere — home, a coffee shop, travelling. Install it on both machines:
- Open the Mac App Store on the dedicated Mac, search for Tailscale, install it
- Open Tailscale, sign in with your account (Google, GitHub, or Apple ID)
Tip: Use an existing Google/GitHub account. If any of your machines run Windows or Linux, Tailscale works on those too — download from tailscale.com/download.
- Do the same on your main machine — same account
- Both devices now appear in your Tailscale dashboard with stable IPs like 100.x.x.x
- In Tailscale preferences on the dedicated Mac, enable "Start Tailscale when I log in"
bot@your-mac.local). Outside use the Tailscale IP (bot@100.x.x.x). Both always work.
4. Keep it awake with the lid closed
Open Terminal and run:
sudo pmset -a disablesleep 1
# Verify it worked
pmset -g
# To reverse later: sudo pmset -a disablesleep 0
sudo? It means "run as admin." It will ask for the password you set during setup. Type it — nothing will appear on screen as you type, that's normal — and press Enter.
5. Install core tools
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# IMPORTANT: Homebrew on Apple Silicon Macs needs this to work.
# After install, it prints these 2 commands — run them both:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
# Install essentials
brew install git python3 tmux node
# Install Claude Code
npm install -g @anthropic-ai/claude-code
# Sign in to Claude Code (your Max subscription)
claude
# Follow the login prompts — it opens a URL you paste in any browser
6. Enable passwordless sudo for Claude Code
Claude Code needs to run sudo commands (installing packages, managing services, etc.) but can't type a password into the interactive prompt. This lets it run admin commands freely:
echo "YOUR_USERNAME ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/YOUR_USERNAME
7. Grant Full Disk Access to Terminal
macOS blocks background processes (like the Slack bot) from accessing files unless explicitly allowed. Without this, you'll get constant "would like to access data from other apps" popups.
- Go to System Settings → Privacy & Security → Full Disk Access
- Click +, navigate to Applications → Utilities → Terminal.app, and add it
- Toggle it ON
8. Set it up physically
- Plug into power (always — use a reliable outlet)
- Connect to your home WiFi (or ethernet via USB-C adapter if you have one — more reliable)
- Close the lid, tuck it somewhere out of the way — a shelf, behind a monitor, wherever
- Note the local IP address or hostname (shown in System Settings → Sharing, something like
bot@your-mac.local)
Slack bot setup
Create the Slack app, install the bot, wire it to Claude Code. ~20 minutes.
1. Create the Slack app
You need admin access to your Slack workspace:
a. Go to api.slack.com/apps → Create New App → "From scratch"
b. Name it — whatever feels right for your AI cofounder
c. OAuth & Permissions → Add Bot Token Scopes: app_mentions:read, chat:write, im:history, im:read, im:write, files:read
d. Event Subscriptions → Enable Events → set Request URL to https://bot.yourdomain.com/slack/events (you'll set up Cloudflare Tunnel for this in step 5)
e. Subscribe to bot events: app_mention, message.im
f. Basic Information → copy the Signing Secret (used to verify requests are really from Slack)
g. Install to workspace → save the Bot Token (xoxb-...)
h. Find your Slack user ID: Profile → ⋮ menu → "Copy member ID"
When creating the app, choose "From an app manifest" instead of "From scratch". Paste this JSON — it configures everything in one shot. Replace the bot name and URL with your own:
"display_information": {
"name": "Your Bot Name",
"description": "AI cofounder for your product",
"background_color": "#0f172a"
},
"features": {
"bot_user": {
"display_name": "Your Bot Name",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": [
"app_mentions:read", "channels:history", "channels:join",
"channels:read", "chat:write", "chat:write.customize",
"commands", "files:read", "files:write",
"groups:history", "groups:read", "im:history",
"im:read", "im:write", "links:read",
"mpim:history", "mpim:read", "mpim:write",
"pins:read", "pins:write", "reactions:read",
"reactions:write", "team:read", "users:read",
"users:read.email", "users.profile:read",
"bookmarks:read", "metadata.message:read"
]
}
},
"settings": {
"event_subscriptions": {
"request_url": "https://bot.yourdomain.com/slack/events",
"bot_events": [
"app_mention", "message.im", "message.channels",
"message.groups", "message.mpim",
"member_joined_channel", "reaction_added",
"file_shared"
]
},
"org_deploy_enabled": false,
"socket_mode_enabled": false,
"token_rotation_enabled": false
}
}
After creating, you still need to manually grab the Bot Token (OAuth & Permissions → Install to workspace → xoxb-...) and the Signing Secret (Basic Information).
2. Install the bot on your Mac
SSH in from your main machine, or open the lid:
ssh bot@your-mac.local
# Create the bot directory
mkdir -p ~/Projects/slack-bot
cd ~/Projects/slack-bot
# Set up Python environment
python3 -m venv venv
source venv/bin/activate
pip install slack-bolt slack-sdk python-dotenv flask
3. Clone your codebase
git clone <your-repo-url> your-product
# Install your project's dependencies so the AI can use the full dev environment
cd your-product
# npm install / bundle install / pip install — whatever your stack needs
4. Set up the bot
Write your bot script (or use an existing Slack-to-Claude-Code bridge) and configure it:
mkdir -p ~/Projects/slack-bot
cd ~/Projects/slack-bot
# Set up Python environment
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Configure environment variables
cp .env.example .env
nano .env # Add your Slack tokens, Signing Secret, user IDs
~/Projects/ avoids permission errors.
The bot should handle:
- HTTP Events API via Flask (production-standard, each event is a stateless HTTP POST)
- Async processing — responds to Slack within 3 seconds, runs Claude in background
- Auth gating — only allowed Slack user IDs can interact
- Thread-based conversations with Claude session continuity
- Markdown to Slack formatting conversion
- File/image attachment handling
- Audit logging of every interaction
5. Set up Cloudflare Tunnel
This gives your Mac a public URL (bot.yourdomain.com) so Slack can send events to it. Free, production-grade, HTTPS included.
brew install cloudflared
# Authenticate (opens browser — do this before closing the lid!)
cloudflared tunnel login
# Create a named tunnel (note the UUID it prints — you'll need it below)
cloudflared tunnel create my-bot
# Route your subdomain to the tunnel
cloudflared tunnel route dns my-bot bot.yourdomain.com
# Create the config file (replace TUNNEL-UUID and YOUR_USERNAME)
cat > ~/.cloudflared/config.yml << 'EOF'
tunnel: TUNNEL-UUID
credentials-file: /Users/YOUR_USERNAME/.cloudflared/TUNNEL-UUID.json
ingress:
- hostname: bot.yourdomain.com
service: http://localhost:3000
- service: http_status:404
EOF
# Test it
cloudflared tunnel run my-bot
# Once working, install as a persistent system service
sudo cloudflared service install
https://bot.yourdomain.com routes to your Mac. Cloudflare handles HTTPS, DDoS protection, and auto-retries. The tunnel runs as a system service — survives reboots. Go back to your Slack app's Event Subscriptions and set the Request URL to https://bot.yourdomain.com/slack/events.
6. Test it
cd ~/Projects/slack-bot
source venv/bin/activate
python bot.py
# You should see:
Bot starting on port 3000
DM the bot in Slack. If it responds — you're in business.
Make it always on
Survive crashes, reboots, and power outages — permanently.
1. Create a launchd service
This tells macOS to keep the bot alive forever. Replace YOUR_USERNAME and paths as needed:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.claude.homebase</string>
<key>ProgramArguments</key>
<array>
<string>/Users/YOUR_USERNAME/Projects/slack-bot/venv/bin/python</string>
<string>/Users/YOUR_USERNAME/Projects/slack-bot/bot.py</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/YOUR_USERNAME/Projects/slack-bot</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/Users/YOUR_USERNAME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>StandardOutPath</key>
<string>/Users/YOUR_USERNAME/Projects/slack-bot/bot.log</string>
<key>StandardErrorPath</key>
<string>/Users/YOUR_USERNAME/Projects/slack-bot/bot-stderr.log</string>
</dict>
</plist>
EOF
claude or brew-installed tools. This tells launchd where to look.
2. Load, verify, and test
launchctl load ~/Library/LaunchAgents/com.claude.homebase.plist
# Verify it's running
launchctl list | grep homebase
curl -s http://localhost:3000/health
# Test crash recovery — kill it, watch launchd bring it back
kill $(pgrep -f bot.py)
sleep 3 && pgrep -f bot.py
# Test reboot survival
sudo reboot
# Wait 2-3 min, then DM the bot in Slack
Connect Google Workspace
Give your AI cofounder access to Drive, Sheets, Gmail, Calendar, Docs — so it can read and act on your business data.
1. Create a Google Cloud project
This is a one-time setup. Do it in the browser:
- Go to console.cloud.google.com and sign in with your account
- Create a new project (name it anything, e.g. "Workspace CLI")
- Go to APIs & Services → Library and enable the APIs you need:
Google Drive API Google Sheets API Gmail API Google Calendar API Google Docs API Google Slides API
- Go to Google Auth Platform → Audience → configure the consent screen if prompted → set user type to Internal
Tip: "Internal" means only people in your Google Workspace org can use it. This skips the test user and verification hassle entirely. If you're using a personal Gmail, choose "External" and add your email as a test user.
- Go to Clients → Create Client → Desktop app → Create
- Copy the Client ID and Client Secret
2. Install and authenticate on your Mac
SSH into your Mac (or open the lid) and tell Claude to do the rest:
claude
# Then paste this prompt (with your actual credentials):
Install the Google Workspace CLI from https://github.com/googleworkspace/cli using npm. Then authenticate using these credentials:
- Client ID:
<paste your client id> - Client Secret:
<paste your client secret>
Run gws auth login with those set as env vars. I'll handle the browser consent screen. After auth, verify it works by listing my Drive files.
gws, run gws auth login with the same Client ID and Client Secret, and approve the consent screen in the browser. The OAuth credentials are reusable — you just need to re-authenticate each device.
Using your AI cofounder
How you interact with it day-to-day.
How to talk to it
- DM the bot directly — just like messaging a teammate
- @mention it in channels — it responds in a thread
- Thread replies continue the conversation — it remembers context within a thread
- Attach screenshots or files — it can read images and documents
Things to try
"How many new signups did we get this week?"
"There's a bug — user X reports [issue]. Investigate and fix it."
"Draft a response to this support email" — paste the email
"What's our MRR looking like? Any churn this month?"
"Add a 'last active' badge to the user profile page"
"Review this PR and tell me what you think" — paste a GitHub link
"Write a migration to add an 'interests' column to the users table"
Your setup details
Fill these in once setup is complete. Bookmark this page.
| Machine | TBD |
| macOS username | TBD |
| Tailscale hostname | TBD |
| Tailscale IP | TBD |
| SSH (home) | ssh YOUR_USERNAME@your-mac.local |
| SSH (anywhere) | ssh YOUR_USERNAME@100.x.x.x |
| Screen Sharing | vnc://100.x.x.x |
| Claude Code | Max subscription ($200/mo) |
| Slack bot endpoint | https://bot.yourdomain.com/slack/events |
Admin commands
Quick reference for managing the server.
ssh YOUR_USERNAME@your-mac.local # at home
ssh YOUR_USERNAME@100.x.x.x # from anywhere via Tailscale
# Check bot status
launchctl list | grep homebase
curl -s http://localhost:3000/health
# View live logs
tail -f ~/Projects/slack-bot/bot.log
# Restart the bot
launchctl unload ~/Library/LaunchAgents/com.claude.homebase.plist
launchctl load ~/Library/LaunchAgents/com.claude.homebase.plist
# Pull latest code
cd ~/Projects/your-product && git pull
# Interactive Claude Code session
tmux new -s claude
cd ~/Projects/your-product && claude
# Detach: Ctrl+B then D | Reattach: tmux attach -t claude
# Full desktop access (home or via Tailscale)
# Finder → Go → Connect to Server → vnc://your-mac.local (home)
# Finder → Go → Connect to Server → vnc://100.x.x.x (anywhere)
# Or just walk over and open the lid :)
Good to know
Limitations and things to keep in mind.
| Limitation | Details |
|---|---|
| Rate limits | The $200/mo Max plan has usage caps. During heavy usage (long conversations, parallel tasks), you may hit limits. Space out intensive work or wait for the limit to reset. |
| Power outages | If your home loses power, the Mac shuts down. It'll restart automatically when power returns (if configured in System Settings → Energy → "Start up automatically after a power failure"). The bot restarts via launchd. |
| Internet outages | If your home internet drops, the Cloudflare Tunnel goes down and Slack can't reach the bot. Everything recovers automatically when internet returns. Consider a mobile hotspot as backup for critical uptime. |
| macOS updates | Automatic updates can restart your Mac unexpectedly. Disable automatic restarts in System Settings, and apply updates manually when convenient. |
| Context window | Each Slack conversation is a separate Claude session. Very long threads may hit context limits. Start a new thread for new topics to keep context fresh. |
Bring it to life
Everything is running. Now give your AI cofounder a brain, skills, and an identity.
Install the starter kit
Open Claude Code on your Mac and paste this:
Clone https://github.com/nityeshaga/claude-home-base to ~/claude-home-base. Copy CLAUDE.md.example to ~/CLAUDE.md. Install the plugin marketplace from the repo. Enable all plugins (tactical and more-ai).
Then set up identity.md and about-you-and-how-you-came-to-life.md in my home directory. Before you write them, ask me:
- What should I call you? (my name)
- Why did you bring me to life? (what I'm here to do)
- How do you want me to behave? (my personality and style)
Then customize CLAUDE.md with my details — fill in the team section, Slack user IDs, workspace paths, product description, and environment. After that, write my identity.md — who I am, in my own voice. And write my origin story.
That's it. It's alive.
Your AI cofounder now has a CLAUDE.md (its operations manual), an identity (its soul), an origin story (its history), and skills (inbox management, brainstorming, image generation). It knows who you are, what the product is, and how to reach you on Slack. From here, everything compounds — every conversation makes it smarter, every correction refines its preferences, every day it understands the business better.
Growing your AI cofounder
Once the basics are running, here's where to go next.
Write a comprehensive CLAUDE.md
Your AI cofounder is only as good as the context you give it. Write a detailed CLAUDE.md with your business model, architecture, deployment process, key metrics, customer personas, common tasks, and standing instructions. This is the single highest-leverage thing you can do.
Set up scheduled routines
Use launchd to schedule daily routines: morning briefings, email triage, error log checks, nightly summaries. Each routine is a wrapper script that runs claude -p with a specific prompt and posts results to Slack. Start with one routine and add more as you see what's useful.
Give it accounts and credentials
Create dedicated accounts for your AI cofounder — email, GitHub, task tracker. The more tools it can access, the more it can do autonomously. Store API keys in the bot's .env file.
Build custom skills (Claude Code plugins)
Write SKILL.md files that teach your AI cofounder specific workflows — inbox management, deployment procedures, customer support templates, analytics queries. Each skill is a markdown file that Claude reads automatically and uses when relevant.
Point it at growth
Once operations are stable, use your AI cofounder for growth work: A/B test landing pages, rewrite onboarding emails based on churn data, generate case studies, build features that drive upgrades, analyze what your best customers have in common.