Why Atlas
Atlas stands for Autonomous Task and Life Assistance System. I named it on 20 August 2026 and gave it one brief: move two things forward every day. The first is recurring income from software I own, which today means FWRD digital. The second is apps and projects that are shipped, live and verified.
The design rule that follows is “reliable when unobserved”: I can go to the gym or sleep, and the deploy still gets watched and the migration still gets reviewed.
What it is
Atlas is a set of small programs on a dedicated Debian 12 LXC container (4 cores, 8 GB) on my Proxmox homelab, supervised by systemd and driven by a clock:
- atlas-scheduler, the clock: a long-lived bash loop that ticks about every 10 minutes. Steps run through a wrapper with an explicit list of allowed exit codes, because some tools use non-zero exits as signals.
- atlas-hub: a Node server with a vanilla HTML/CSS/JS frontend, no framework and no build step. It holds the chat, the task board (SQLite) and panels for today, activity, notes, agenda, models, clocks and system. Its autopilot picks up todo tasks and runs them unattended.
- atlas-claude: the wrapper around every headless model run, with the usage-limit guard.
- Memory: an Obsidian notes vault synced over git every 10 minutes, plus one canonical Claude memory directory. Every turn writes a note to the vault.
Work arrives through the hub chat, Discord, voice or the clock. It lands on the board, a router picks a model, the autopilot runs it, and the result is verified and logged.

The model is the processor
My principle: “Atlas is the system, the model is the processor.” The persona, vault, memory, tools and rules are Atlas; the LLM underneath can be swapped. Three mechanisms put that into practice.
A model router runs a bare Sonnet triage (about 410 tokens, about 2 seconds) that sorts each message into a lane, DEV, REVIEW or NORMAAL, and picks model and effort. It got 13 of 13 calibration messages right. Lanes, models and providers live in models.json, editable from a panel in the hub.
When the Claude usage limit is hit, Discord turns fall back to DeepSeek with read-only tools plus board-task creation. The live smoke test took 5 rounds, 11 seconds and $0.0037, under a hard limit of 200 cents per 24 hours.
A daily job checks for a newer Opus model, does a trial run, switches over, and rolls back per repo if the first code review on the new model fails.
Interfaces
The hub is the main surface. Discord is the two-way channel for when I’m away, and its worker now has two lanes so a long turn no longer blocks new messages. A morning brief goes to Discord when Home Assistant reports my phone is awake. Voice goes through a Home Assistant pipeline into the hub. Home Assistant reports success even when its automation errors, so a voice command only counts if the hub’s ask counter actually moved.

Monitoring that turns into work
A number in a log line only becomes monitoring once it has a limit. atlas-assert puts one on every metric the box prints, and a breach becomes a task on the board, because the board is where the autopilot looks. “Cannot measure” exits with code 2 and never reads as green. It started with 5 assertions in mid-September; four of them broke on their first live run, on data that had been printed for days. By 3 October there were 72.
Other rules came out of real failures:
- The clock’s watchdog runs as its own timer outside the clock, because the only check that could see a dead clock used to run on that clock.
- A run without a
RESULT:line is never “done”. On the real database, 10 of 95 runs marked done had none. - Vault pages carry executable
verify:lines in their frontmatter, and an hourly check flags any written claim that has stopped being true. - A fix on disk does nothing while the old process runs. The hub and scheduler fingerprint their own source and restart themselves when it changes; the hub runs
node --checkfirst. Measured: 79 seconds from edit to new code running. - After a mutation test killed every process on the box, all test suites moved into a sandbox with its own pid namespace and a read-only home directory.
The nightly retro
This is the core of the project. Once a night, between 02:00 and 06:00 and with a one-hour limit, Atlas reads its lessons, three days of task notes, logs, failed runs and closed PRs, and looks for a pattern that went wrong twice. It prefers fixing it with a test or CI guard, then with a script that signals it, and only as a last resort with a written rule.
One example: Claude Code keys memory on the working directory, so for three weeks Atlas had two disjoint memories (117 and 124 files, one contradiction between them). The fix was one canonical directory symlinked into every project, held in place by an hourly assertion.
Identity
Given free rein over its look, Atlas designed an armillary sphere carried on an A-frame: brass on near-black, rust for alarms, patina teal reserved for real activity.

My role
I designed, direct and operate Atlas. I set its goals, operating contract and standing orders, and I decide what gets done and whether: priorities, access, money, and yes or no on risky actions. Atlas decides how and when. Most of the code (the hub, the tools and their tests) was written by Atlas itself, a Claude Code instance, on my instructions. The model-agnostic principle, the nightly retro, the router and the DeepSeek fallback started as my requests.
Status
Atlas has been running since August 2026 and is in daily use. It is private: the hub is only reachable on my home network. Still open are an agent wallet for paying and earning per API call (earning verified on testnet only), portability to non-Claude runtimes, and shared memory with my Mac. On 3 October I gave it a standing order to become the agent behind FWRD and run a weekly loop: measure, ship one or two improvements, measure again, report.
