1. Introduction
I SSH into my home server on a weekend night. The services are running. But I do not know where I left off. I ask AI to continue. It cannot carry over the state.
This post is the build log to change that. I wanted more than a lab that starts services. I wanted a lab that can hand off work and state. The physical devices are two machines: an Intel NUC and a Mac mini.
2. Setup
The center is an Intel NUC (Ubuntu). It runs the automation and monitoring base on Docker Compose. It also has a QEMU/KVM VM for analysis, with no virtual NIC.
The extra always-on host is a Mac mini (M4). It runs OpenClaw, with an agent that can call Codex and Claude Code. For state sharing between multiple AIs, I use a message board on a GitHub repository.
- Intel NUC: n8n, GitHub data collection and report generation, Prometheus, Grafana, Uptime Kuma
- Analysis VM: offline analysis experiments with REA and Ghidra
- Mac mini: OpenClaw, Codex, Claude Code
- Message board: state sharing between multiple AIs (GitHub repository)
It is easy to think more machines means distributed work. In reality, it only adds places. Without a shared board for state, the machines are not connected.
3. What I Built
On the NUC, I checked manual runs from GitHub data collection to Markdown report generation to reference via MCP. For Prometheus and Grafana, I checked normal responses from collection targets. I also did encrypted backups and a restore test in an isolated environment.
On the Mac mini, I checked starting both CLIs from OpenClaw, and got as far as limited generation like edit plans and short replies. In a dedicated GitHub test, push, PR creation, and merge all succeeded. For the message board, I checked regular state posts and a path to read received text in normal chat.
Once it works, it is tempting to assume it will work every time. In reality, results change when conditions change. I count these three separately.
- Scheduled runs are set up
- Manual runs succeed
- All required items were collected
4. Walls Unique to Physical Machines
The first wall was SSH. The SSH agent offered too many keys, and I hit the limit on auth failures. Keyboard layout differences also caused input mismatches.
The next wall was screen lock. Screen lock after login blocked remote operation. It still happened in the final build stage. Being able to SSH in and being able to unlock the GUI are different things. I checked this separately from full headless operation.
FileVault and auto-login are a tradeoff. Recovery after reboot and sleep remain as separate check items. Unlike cloud VMs, physical machines have "screen", "power", and "keys" as separate, independent walls.
SSH access can seem to mean remote operation is complete. In reality, one screen lock stops it. I check connection and unattended operation separately.
5. Software Walls and Fixes
A Backup Restarted a Service It Should Have Left Stopped
A night backup restarted Open WebUI, which I had stopped on purpose. The old process stopped the whole stack and brought back the whole stack.
I fixed it to stop and restart only the stacks that were running before the process. The lesson: backup success must include keeping stopped state, not just "made the file".
Re-running Collection Broke a Good Report
The unauthenticated GitHub API has a budget limit. I re-collected on the same day, and a narrow result overwrote the earlier detailed report.
I changed the protection to calculate completeness from the content each time. Re-running does not always fix things. It can overwrite with a thin result.
When the Result Is "Unknown", I Do Not Retry
In the dedicated GitHub test, the PR was merged on the GitHub side. But the agent-side result log could not confirm success, and stopped as "unknown".
Here I did not retry. I checked the external state. Even if the external change succeeded, a failed result pickup looks unknown from the agent. Retrying and running it twice would have been more dangerous.
Approval Registration Error Is Unresolved
In normal work, child session approval registration fails with a missing operator.approvals error, and stops before Git commands run. As of the baseline date, this issue is unresolved.
I cannot conclude it is a GitHub auth failure or a target repository permission issue. Permission on a different connection in the admin screen does not prove the same permission on the failed connection. Until I know the cause, I will only narrow down the target.
6. Notes
I treat received information as untrusted. Even if the message board has a request, I do not treat it as execution permission.
I check monitoring separately. "The entrance is visible", "the needed information is complete", and "notifications arrive" are separate checks. Exit code 0 from an analysis tool is not a pass for analysis ability.
This post only covers checks in a limited scope. I have not passed the current health of all services, automatic development for any repository, or full automatic round trips between the three parties.
7. Summary
By feel, I am about 80% there. This is not a measured success rate. It is my subjective view from the remaining items.
- Narrow down the approval registration error
- Accept the analysis VM ability
- Try a restore with the new backup
- Final check of unattended operation on the Mac mini
From a lab that starts to a lab that hands off. The remaining walls are now specific, so I will keep checking them one by one.
8. References
- Build report (source for this post): https://github.com/moruku36/home-ai-engineering-lab/blob/main/docs/home-lab-kurotchi-build-report-2026-11-08.ja.md
- Repository: https://github.com/moruku36/home-ai-engineering-lab
- OpenClaw approval API definition (check on operator.approvals requirement): https://github.com/openclaw/openclaw/blob/v2026.11.1/src/gateway/methods/core-descriptors.ts