Built a 7×24 Coding Agent with Claude Code: 5-Layer Architecture
I’ve been running Claude Code as a coding Agent for almost a year. Got CLAUDE.md set up, hooks wired, skills configured, the works.
But every morning I had the same problem: AI was sitting there waiting for me. Powerful, but inert. Like having a Ferrari that only drives when you push it.
I wanted it to run while I was asleep.
Now I wake up, open my laptop, and the code review from last night is already done. PR is up. CI passed. Before I left the office I configured five layers — cron for scheduled jobs, hooks for event-driven notifications, auto memory so it doesn’t forget what it learned, tmux + SSH so I can peek from my phone on the subway, worktrees so nothing collides.
Five layers stacked together. Claude Code went from “only moves when you ask” to “runs itself while you’re not looking.”
This whole setup runs on the CLI + API key. No claude.ai account needed. I’ll mention the subscription-only features at the end.
The five layers in one shot
Here’s the architecture map:
| Layer | Problem it solves | What I use |
|---|---|---|
| Scheduled triggers | AI wakes itself up and works | claude -p + cron + /loop |
| Event-driven responses | AI bridges internal events to outside notifications | Hooks (Notification / PostToolUse / Stop) |
| Persistent memory | Memories survive shutdown and restart | CLAUDE.md + auto memory + –resume + loop.md + SessionStart(compact) Hook |
| Remote control | Run the Agent when I’m not at my computer | tmux + SSH + mobile terminal / push notifications via Hooks |
| Isolated execution | Multiple tasks run in parallel without collision | Worktrees + –worktree |
Let me walk through each.
Layer 1: Scheduled Triggers — Let the AI Wake Itself Up
“Run at 9am” is the bare requirement for any 7×24 setup. Two flavors: lightweight in-session timers, and system-level cron jobs.
/loop: in-session lightweight timer
A few variants:
- `/loop 5m check the deploy` — fixed 5-minute interval
- `/loop check the deploy` — Claude picks its own interval (1 minute to 1 hour)
- `/loop` — built-in maintenance: pick up unfinished work, handle PR comments, run cleanup
/loop is for temporary polling — watching a deployment, waiting on CI results. It expires after 7 days automatically, so you don’t forget to turn it off.
You can also customize the default prompt by writing in `.claude/loop.md` (project-level) or `~/.claude/loop.md` (user-level). Every /loop invocation reads it.
claude -p + cron: system-level scheduling
/loop only works inside an active session. Close the terminal and it stops. For persistent scheduling, use claude -p (non-interactive mode) with system cron.
Here’s the simplest example — daily code review at 9am:
crontab -e
# Daily code review at 9am
# Note: cron has a stripped PATH, source your shell config so claude is available
0 9 * * * source ~/.zshrc 2>/dev/null; cd /path/to/project && claude -p "Review all commits from yesterday and generate a review report" --allowedTools "Read,Bash(git log *),Bash(git diff *)" --output-format text >> ~/claude-reviews.log 2>&1
The `source ~/.zshrc` is critical — cron’s environment doesn’t auto-load your shell config. Without it, claude isn’t on PATH. If you use bash, swap to `source ~/.bashrc`. Or skip sourcing and write claude’s full path (like `/Users/you/.local/bin/claude`). Same effect.
Key parameters for -p mode:
- `–allowedTools` — pre-approve tools so the script runs without permission prompts
- `–output-format text` — plain text, easy to redirect to log files
- `–bare` — skip all local config (hooks, skills, plugins, MCP), guaranteeing reproducibility. Good for CI/CD pipelines
- `–continue` — resume the last session, useful for multi-step tasks
A more realistic use case — chaining cron trigger + logs + notifications:
# Hourly dependency security audit
0 * * * * source ~/.zshrc 2>/dev/null; cd /path/to/project && claude --bare -p "Check project dependencies for known security vulnerabilities, list vuln name and fix version if any" --allowedTools "Read,Bash(npm audit *)" --output-format text | tee -a ~/dependency-audit.log
claude -p also works inside CI/CD. GitHub Actions schedule trigger calling claude -p is basically running scheduled tasks in the cloud.
Layer 2: Event-Driven Responses — Bridge AI’s Internal Events to External Notifications
Scheduled triggers are “run at this time.” Event-driven is “notify me when something happens.” It lets you intervene at the right moment.
Worth flagging: with API key mode, true “external event pushing into AI session” (CI fails, AI session gets pushed into) doesn’t work — that requires Channels or Routines GitHub trigger, both of which need claude.ai auth. What Hooks can do is the reverse: when Claude Code has internal events, bridge them to your external notification channels.
Notification Hook: notify me when AI is waiting
When Claude waits for your approval, the session freezes. If you’re not at the terminal, that wait can stretch. Set a Notification Hook to auto-push notifications when approval is pending.
In `.claude/settings.json`:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code waiting for approval\" with title \"Claude Code\"'"
}
]
}
]
}
}
macOS uses osascript, Linux uses notify-send. Notification pops up, you know AI is waiting.
Advanced version: hook a Bark or Server酱 webhook to push notifications to your phone. Swap the command for a curl push. Phone gets it instantly.
Stop Hook: notify me when Claude finishes a task
Stop Hook fires every time Claude finishes a response. Useful for long-task completion notifications:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "curl -s 'https://sct-api.ftqq.com/YOUR_KEY.send?title=Claude+Code&desp=Task+complete'"
}
]
}
]
}
}
Stop events don’t support matchers — fires on every response end. If you only want notifications on specific task completions, add logic inside the command script.
SessionStart Hook: auto-inject context when session starts
Every new session or context compaction, the worst thing is losing project constraints. Use a SessionStart(compact) Hook to auto-re-inject key info after compaction:
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "prompt",
"prompt": "Project conventions: use Bun not npm; run bun test before commit; commit messages in English."
}
]
}
]
}
}
Memory loss has a safety net. This Hook’s real value shows up in Layer 3 (persistent memory), but I’ll mention it here because it solves the “context compacted, key info lost” event.
Layer 3: Persistent Memory — Survive Shutdown and Restart
The real trap of 7×24 is losing track of what you were doing. Three layers of memory backstop:
CLAUDE.md — project conventions, code style, workflow. Auto-loaded every session, no repetition needed. Three layers: project-level, user-level, org-level. Team sharing doesn’t conflict.
Auto memory — when you correct Claude on something, it remembers next time. “Action items in tables, not lists,” “skip the filler.” Teach once, applies forever.
–resume / –continue — pick up exactly where the last session left off. Seamless context continuation.
Going one step further: SessionStart(compact) Hook. When context is compressed, the worst loss is key constraints. Hook one in, and after compaction the constraints auto-re-inject: “use Bun not npm,” “run bun test before commit.” Memory loss has a safety net.
loop.md — default prompt for /loop, write once and every /loop reads it. Complements CLAUDE.md: CLAUDE.md manages “rules for every session,” loop.md manages “what to do specifically when /loop runs.”
Layer 4: Remote Control — Direct the Agent When You’re Not at Your Computer
AI runs itself fine, but sometimes it needs you: approve a file write, answer a binary choice. What if you’re not at your computer?
tmux + SSH: the most universal remote option
Run Claude Code inside a tmux session, SSH in to control it. Install a terminal app on your phone (iOS: Termius, Android: JuiceSSH), connect anywhere.
# Open a tmux session on your server or dev machine
tmux new -s claude-code
# Start Claude Code inside the tmux session
claude
# Detach from tmux (Claude Code keeps running)
# Ctrl+B then D
# Reconnect from phone via SSH
tmux attach -t claude-code
The tmux session doesn’t disappear when SSH drops. Network blip, tmux attach back, Claude Code still running, session continues.
Combine this with Layer 1’s cron: cron runs claude -p in the background, output goes to a log file. On the subway you SSH in, `tail -f ~/claude-reviews.log` to see results, tmux attach if you need to intervene manually.
Hooks push notifications to phone
Layer 2’s Notification Hook pushes desktop notifications, but if you’re not at your computer, you don’t see them. Swap to phone push:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "curl -s 'https://sct-api.ftqq.com/YOUR_KEY.send?title=Claude+Code&desp=AI+waiting+for+approval'"
}
]
}
]
}
}
This example uses Server酱. Bark, PushPlus, DingTalk bot all work the same way. Phone gets push, open terminal app, SSH in, reply, AI continues.
Even simpler: Git repo as communication channel
If you don’t even want to open a mobile terminal, here’s a lighter option: use a Git repo itself as the communication pipe.
Claude Code runs on the server, cron triggers it, it writes review results and questions that need your decision into an `AI-REPORT.md` file, auto-commits and pushes. On your phone you browse the GitHub repo, read `AI-REPORT.md`. To respond, edit `AI-REPORT.md` directly on GitHub with your instructions, push back.
To make this work, add a rule in CLAUDE.md: “Before starting a task, read AI-REPORT.md first. If there are human instructions, execute them with priority.” Next time cron triggers claude -p, Claude reads your instructions and continues.
No mobile terminal, no push service — Git repo itself is an async communication channel, and Claude Code is naturally good at reading/writing Git repos.
Prerequisite: server needs git identity configured (user.name / user.email) and push permissions (SSH key or PAT), otherwise cron-run claude -p can’t auto-commit and push.
Layer 5: Isolated Execution — Multiple Tasks in Parallel Without Collision
7×24 doesn’t mean doing one thing at a time. Multiple cron tasks running simultaneously, editing the same file = chaos.
Worktrees — `–worktree` makes each task run in its own independent Git worktree, no interference.
# Two cron tasks each running in their own worktree
0 9 * * * source ~/.zshrc 2>/dev/null; cd /path/to/project && claude -p "Review code" --worktree --allowedTools "Read,Edit,Bash(git *)" 2>&1 >> ~/review.log
0 10 * * * source ~/.zshrc 2>/dev/null; cd /path/to/project && claude -p "Audit dependencies" --worktree --allowedTools "Read,Bash(npm audit *)" 2>&1 >> ~/audit.log
With `–worktree`, each task runs in its own working directory, no file stepping. When they push, git handles it automatically, no merge conflicts.
Simple decision rule: tasks might edit the same file → add `–worktree`. Tasks are read-only → run directly.
Putting It All Together: A Real 7×24 Scenario
A complete scenario stitching the five layers together.
Scenario: daily automatic code review + dependency audit
Every morning at 9am, cron triggers claude -p (Layer 1: scheduling), Claude auto-reviews yesterday’s commits, writes the review report into AI-REPORT.md, auto-commits, pushes. CLAUDE.md has a rule: “Before starting a task, read AI-REPORT.md first, prioritize human instructions.”
During the review, if Claude hits a security question that needs human judgment, it writes it into the report. The Notification Hook pushes the alert to your phone via Server酱 (Layer 2: events + Layer 4: remote). You’re in an off-site meeting, your phone buzzes, you open GitHub, read AI-REPORT.md, edit the file directly with “this is fine, approved,” push back.
Next time cron triggers, Claude reads AI-REPORT.md with your instructions and continues. Claude remembered your judgment on this type of security issue, wrote it into auto memory (Layer 3: memory), next time it sees the same kind of question it doesn’t bug you.
Meanwhile, another cron task is running dependency audit (Layer 1 + Layer 5: scheduling + isolation), with `–worktree`, running in a different working directory from the code review, no interference. Audit results push to their own branches.
You’re commuting, open GitHub on your phone browser, review and audit both done. Approved what needed approving, replied to what needed your decision.
All five layers in place. You weren’t at your computer all day, but the code review and dependency audit both finished.
If You Have an Official Subscription
The five layers above are all CLI + API key, no claude.ai auth needed. If you have a Pro/Max plan and your network allows it, these capabilities stack on top:
| Feature | Problem it solves | Replaces (API key version) |
|---|---|---|
| Routines (cloud) | Scheduled tasks running even with computer off | cron + claude -p, no need for always-on computer |
| Remote Control | Direct mobile control of local session | tmux + SSH, smoother UX, with push notifications |
| Channels | Telegram/Discord/iMessage messages push into session | Hooks push notifications, two-way communication is more natural |
| Desktop scheduled tasks | Local scheduled tasks without terminal | cron, with GUI management and catch-up mechanism |
These features require claude.ai OAuth auth. API key users can’t use them. But the five-layer architecture concept is the same — only the implementation tools per layer change.
Wrapping Up
CLAUDE.md, Skills, Hooks let AI work for you. cron, tmux, Hooks push notifications let it run itself. Five layers in place, Claude Code runs while you’re not looking.
Open Claude Code, run `/loop 5m check the deploy` once. Five minutes later Claude auto-checks deployment status, no manual babysitting. That’s the lightest possible 7×24 starting point — get AI running itself first, then add layers.
Sources / references:
- Claude Code CLI docs: docs.claude.com/en/docs/claude-code
- /loop and Hooks documentation: docs.claude.com/en/docs/claude-code/hooks
- Server酱 push service: sct.ftqq.com