How to Turn Your Mac into an Autonomous Agent with Claude Code and Codex
The Concept
The idea is simple: an M1 MacBook Air running Claude Code permanently, acting as a personal agent you can control from your phone. You send tasks from Telegram or the Claude app, and while you’re out and about, the agent reads your backlog, executes code, creates PRs on GitHub, syncs with Notion, and notifies you when it’s done.
This is not science fiction. With the tools Anthropic released over the past few months — Remote Control, Channels, Skills, Subagents, and Hooks — you can set this up in an afternoon.
This tutorial documents the complete setup we built step by step, including integration with Obsidian for task management, Notion as a backup, GitHub for repos, and OpenAI’s Codex CLI as a second agent for code review.
What You’ll Need
Hardware:
- A Mac with Apple Silicon (M1 or later). We used an M1 MacBook Air, but it works with any modern Mac.
- The Mac must be powered on and plugged in 24/7.
Subscriptions:
- Claude Pro ($20/month minimum) or Max ($100–200/month for more headroom). Remote Control requires Pro at minimum.
- A GitHub account with a Fine-grained Personal Access Token.
- A Notion account (the free tier works).
- A ChatGPT account (Plus or above) if you want to use Codex CLI.
Software we’ll install:
- Claude Code CLI (npm)
- tmux (brew)
- Bun (for plugins/channels)
- Codex CLI (npm, optional)
- Obsidian (to view the backlog)
System Architecture
The system has three layers:
Control layer — how you give instructions to the agent:
- Claude app on your phone (Remote Control)
- Telegram (Channels)
- Direct terminal (tmux)
- OS cron jobs (automatic)
Agent layer — who does the work:
- Claude Code as the primary agent (tasks, PRDs, code, communication)
- Codex CLI as the secondary agent (code review, tests, second opinion)
Tool layer — where it connects:
- Obsidian vault (local markdown backlog)
- Notion (backup and visibility)
- GitHub (repos, PRs, issues)
- Gmail and Google Calendar (native claude.ai connectors)
Step 1: Install Prerequisites
# Homebrew (if you don't have it)/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Node.js, tmux, and Bunbrew install node tmuxcurl -fsSL https://bun.sh/install | bashexec /bin/zsh
# Verifyecho "Node: $(node --version) | tmux: $(tmux -V) | Bun: $(bun --version)"If zsh tries to autocorrect tmux to _tmux, fix it with:
echo 'alias tmux="nocorrect tmux"' >> ~/.zshrcsource ~/.zshrcStep 2: Install Claude Code and Authenticate
npm install -g @anthropic-ai/claude-codeclaude --version # You need v2.1.80+Open a session to log in:
cd ~claudeInside Claude Code:
/login # Opens the browser for OAuth with your Pro/Max account/config # Enable "Enable Remote Control for all sessions" → true/exitStep 3: Create the Folder Structure
The entire workspace lives inside a single folder. Claude Code only works here.
# Container workspacemkdir -p ~/claude-setup/{vault/backlog/{pending,in-progress,done},vault/prd,vault/daily-logs,projects}
# Claude Code configuration (skills, agents, scripts)mkdir -p ~/.claude/skills/{backlog-manager,notion-sync,daily-standup,pr-creator,run-codex}mkdir -p ~/.claude/{agents,scripts}Step 4: The Global CLAUDE.md
This is the most important file in the setup. Claude reads it at the start of every session and it contains all the rules, conventions, and context it needs to work the way you want.
cat > ~/.claude/CLAUDE.md << 'EOF'# Global Configuration
## WorkspaceEverything lives inside ~/claude-setup/- Vault (Obsidian backlog): ~/claude-setup/vault/- Projects: ~/claude-setup/projects/- Do NOT access files outside ~/claude-setup/ unless explicitly asked
## Task system- Backlog lives in ~/claude-setup/vault/backlog/- Tasks are markdown with YAML frontmatter (status, priority, project, type, assigned_to)- Statuses: pending → in-progress → done- Priorities: critical > high > medium > low- When completing a task, move file to done/ and update frontmatter- Write daily log in ~/claude-setup/vault/daily-logs/YYYY-MM-DD.md
## Code conventions- TypeScript strict mode- Functional components- Conventional commits (feat:, fix:, chore:)- Run tests before committingEOFAdapt this file with your own conventions, tech stack, and name.
Step 5: Create the Skills
Skills are SKILL.md files that teach Claude how to perform specific tasks. They are loaded on-demand and consume only 30–50 tokens each until activated.
The most important skill is the backlog manager:
cat > ~/.claude/skills/backlog-manager/SKILL.md << 'EOF'---name: backlog-managerdescription: Use when managing tasks, reading the backlog, creating or updating tasks in the Obsidian vaultallowed-tools: Read, Write, Edit, Bash, Grep, Glob---
# Backlog Manager
## Vault location~/claude-setup/vault/backlog/
## Task file formatFiles named YYYY-MM-DD-short-description.md with YAML frontmatter:status, priority, project, type, assigned_to, created, completed
## Rules1. Pick highest priority pending task with assigned_to: claude-code2. Change status to in-progress before starting3. After completing, move to done/ and add completed date4. Write log entry in daily-logs/EOFCreate additional skills for Notion sync, standup generation, PR creation, and Codex delegation. The format is always the same: YAML frontmatter with name and description, followed by instructions in markdown.
Step 6: Create the Subagents
Subagents are specialized Claude instances running in their own context. Unlike skills (instructions), subagents are independent workers.
cat > ~/.claude/agents/task-runner.md << 'EOF'---name: task-runnerdescription: Autonomous task executor for processing the backlogtools: Read, Write, Edit, Bash, Grep, Globmodel: sonnetmemory: projectpermissionMode: acceptEdits---
You are an autonomous task execution agent.Read ~/claude-setup/vault/backlog/pending/, pick the highestpriority task, execute it, update status, and write a log.EOFStep 7: Configure Hooks
Hooks execute code automatically at specific points in the Claude Code lifecycle. They are configured in ~/.claude/settings.json:
{ "hooks": { "SessionStart": [{ "hooks": [{ "type": "command", "command": "~/.claude/scripts/inject-date.sh" }] }], "Notification": [{ "hooks": [{ "type": "command", "command": "~/.claude/scripts/notify.sh \"$CLAUDE_NOTIFICATION\"" }] }] }}Support scripts:
# inject-date.sh — tells Claude what day it isecho "Today is $(date '+%A, %B %d, %Y'). Current time: $(date '+%H:%M %Z')."
# notify.sh — native macOS notificationosascript -e "display notification \"$1\" with title \"Claude Code\" sound name \"Glass\""Step 8: Connect MCP Servers
MCPs connect Claude to external services. You only need MCPs for things that aren’t on your local filesystem.
# Notion (official, hosted by Notion)claude mcp add --transport http notion https://mcp.notion.com/mcp --scope user
# GitHub (requires a Fine-grained Personal Access Token)claude mcp add --transport stdio github --env GITHUB_TOKEN=your_token -- npx -y @modelcontextprotocol/server-github --scope user
# Slack (official, if you use it)claude mcp add --transport http slack https://mcp.slack.com/mcp --scope userFor Obsidian you don’t need MCP. The vault is just markdown files on your disk — Claude reads them directly with its native tools (Read, Write, Edit, Bash).
For GitHub, use a Fine-grained Personal Access Token (not classic) that limits access to specific repos. Create it at GitHub → Settings → Developer Settings → Fine-grained tokens, selecting “Only select repositories” and granting only Contents, Pull Requests, and Issues permissions.
MCPs that require OAuth (Notion, Slack) authenticate the first time you use them inside Claude Code.
Step 9: The Always-On Session with tmux
tmux is a terminal multiplexer that keeps processes running even after you close the window. It’s the piece that makes “always-on” possible.
Startup script:
cat > ~/.claude/scripts/start-agent.sh << 'EOF'#!/bin/bashSESSION_NAME="claude-agent"
if tmux has-session -t $SESSION_NAME 2>/dev/null; then echo "Session '$SESSION_NAME' already running." exit 0fi
tmux new-session -d -s $SESSION_NAMEtmux send-keys -t $SESSION_NAME 'cd ~/claude-setup/projects && claude --remote-control --dangerously-skip-permissions' Enter
echo "Claude agent started in tmux session '$SESSION_NAME'"echo "Attach: tmux attach -t $SESSION_NAME"echo "Detach: Ctrl+B, then D"echo "Kill: tmux kill-session -t $SESSION_NAME"EOFchmod +x ~/.claude/scripts/start-agent.shTo use it:
~/.claude/scripts/start-agent.sh # Launchtmux attach -t claude-agent # View the session# Ctrl+B, D # Detachtmux kill-session -t claude-agent # KillOnce running, copy the Remote Control URL and open it on your phone. From that point on, everything is controlled from your phone.
Note on --dangerously-skip-permissions: this flag gives Claude full access without confirmation prompts. It’s necessary for fully autonomous operation (so it doesn’t wait for your approval on every action), but it means Claude can execute any command. That’s why we constrain its scope in CLAUDE.md to ~/claude-setup/.
Step 10: Crons for Automation
OS cron jobs run tasks periodically using Claude Code in headless mode (-p). Each run starts a clean session.
# crontab -e# Run backlog tasks every 2 hours0 */2 * * * ~/.claude/scripts/cron-wrapper.sh backlog
# Sync to Notion every 4 hours0 */4 * * * ~/.claude/scripts/cron-wrapper.sh sync
# Daily standup at 9pm0 21 * * * ~/.claude/scripts/cron-wrapper.sh standupOn macOS, you need to grant Full Disk Access to /usr/sbin/cron in System Settings → Privacy & Security for crons to work.
Codex as a Second Agent
Optionally, you can install OpenAI’s Codex CLI as a secondary agent for code review and testing:
npm install -g @openai/codexThe run-codex skill and codex-reviewer subagent we configured use it like this:
codex exec "Review these files for bugs and security issues" --sandbox read-onlyClaude Code orchestrates: it decides when to delegate to Codex, passes the context, receives the result, and integrates it with its own analysis. It’s an automatic second pair of eyes.
The Daily Workflow
- When you turn on the Mac:
~/.claude/scripts/start-agent.sh - Create tasks: from your phone via Remote Control, or by creating files in
~/claude-setup/vault/backlog/pending/ - Claude executes: automatically (crons) or on demand (when you ask from your phone)
- Review results: in Obsidian, in Notion, or by asking “what did you do today”
- Code review: Codex reviews automatically when Claude delegates to it
Context Management
The Remote Control session accumulates context. To keep it clean:
- Crons always run in isolated sessions (clean context every time)
- Subagents run in their own context (they don’t pollute the main session)
- Restart the session:
tmux kill-session -t claude-agent && ~/.claude/scripts/start-agent.sh - With Opus 4.6 you have 1M tokens of context, so it takes a long time to fill up
- Claude performs automatic compaction when approaching the limit
Limitations to Keep in Mind
- The Mac must be powered on and awake for everything to work
--dangerously-skip-permissionsgrants full access. Only use it on your personal machine- GitHub Fine-grained tokens expire (I recommend 90-day expiry) and need to be renewed
- Obsidian → Notion sync is one-directional. Notion is just a mirror
- Remote Control generates a new URL every time you restart the session
- Each cron execution consumes tokens from your Claude plan
Next Steps
- Telegram Channel: control the agent from Telegram instead of (or in addition to) Remote Control
- Agent Teams: for large tasks, launch teams of agents that work in parallel
- More MCPs: Slack, Linear, Figma, Playwright for visual testing
- Codex Cloud: when OpenAI launches it, Codex tasks could run in the cloud without depending on your Mac
- Claude Code on the web: Anthropic is developing cloud sessions that don’t depend on your local machine
Setup built in March 2026 using Claude Code v2.1.80+, Codex CLI, and macOS Sequoia on an M1 MacBook Air.