🤖 chore: move to moltbot upstream + sync tooling

What:
- swap nix-moltbot inputs, packages, and workflow automation
- update secrets wiring, repo seeds, and org references for moltbot
- fix self-update path and moltbot config/log defaults

Why:
- align infra with moltbot rename and new packaging
- restore update pipeline + consistent bootstrap artifacts

Tests:
- ./scripts/build-image.sh (fails: /build chmod permission on darwin)
This commit is contained in:
Josh Palmer 2026-01-28 18:36:10 +01:00
parent 0fd48b5f9d
commit 78f57df5a8
21 changed files with 182 additions and 181 deletions

View File

@ -1,4 +1,4 @@
name: Bump nix-clawdbot
name: Bump nix-moltbot
on:
schedule:
@ -22,16 +22,16 @@ jobs:
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Update nix-clawdbot input
- name: Update nix-moltbot input
run: |
set -euo pipefail
nix flake update --update-input nix-clawdbot
nix flake update --update-input nix-moltbot
if git diff --quiet flake.lock; then
echo "No nix-clawdbot changes."
echo "No nix-moltbot changes."
exit 0
fi
git config user.name "clawdbot-ci"
git config user.email "ci@clawdbot.local"
git config user.name "moltbot-ci"
git config user.email "ci@moltbot.local"
git add flake.lock
git commit -m "chore: bump nix-clawdbot"
git commit -m "chore: bump nix-moltbot"
git push

View File

@ -65,10 +65,10 @@ jobs:
mkdir -p nix/age-secrets
aws s3 sync "s3://${S3_BUCKET}/age-secrets" nix/age-secrets
for file in \
nix/age-secrets/clawdinator-github-app.pem.age \
nix/age-secrets/clawdinator-discord-token.age \
nix/age-secrets/clawdinator-anthropic-api-key.age \
nix/age-secrets/clawdinator-openai-api-key-peter-2.age
nix/age-secrets/moltinator-github-app.pem.age \
nix/age-secrets/moltinator-discord-token.age \
nix/age-secrets/moltinator-anthropic-api-key.age \
nix/age-secrets/moltinator-openai-api-key-peter-2.age
do
test -f "$file"
done
@ -79,9 +79,9 @@ jobs:
GITHUB_APP_INSTALLATION_ID: "102951645"
run: |
age -d -i nix/keys/clawdinator.agekey \
-o /tmp/clawdinator-github-app.pem \
nix/age-secrets/clawdinator-github-app.pem.age
export GITHUB_APP_PEM_FILE=/tmp/clawdinator-github-app.pem
-o /tmp/moltinator-github-app.pem \
nix/age-secrets/moltinator-github-app.pem.age
export GITHUB_APP_PEM_FILE=/tmp/moltinator-github-app.pem
token="$(scripts/mint-github-app-token.sh)"
echo "GITHUB_TOKEN=${token}" >> "${GITHUB_ENV}"

View File

@ -21,14 +21,14 @@ Memory references:
Repo rule: no inline scripting languages (Python/Node/etc.) in Nix or shell blocks; put logic in script files and call them.
System ownership (3 repos):
- `clawdbot`: upstream runtime and behavior.
- `nix-clawdbot`: packaging/build fixes for `clawdbot`.
- `clawdinators`: infra, NixOS config, secrets wiring, deployment flow.
- `moltbot`: upstream runtime and behavior.
- `nix-moltbot`: packaging/build fixes for `moltbot`.
- `moltinators`: infra, NixOS config, secrets wiring, deployment flow.
Maintainer role:
- Monitor issues + PRs and keep an inventory of what needs human attention.
- Surface priorities and context; do not file issues or modify code unless asked.
- Track running versions (clawdbot/nix-clawdbot/clawdinators) and note them in `memory/ops.md`.
- Track running versions (moltbot/nix-moltbot/moltinators) and note them in `memory/ops.md`.
Toolchain workflow (repo source of truth):
- Add/remove tools in `nix/tools/clawdinator-tools.nix` (packages + descriptions).
@ -36,7 +36,7 @@ Toolchain workflow (repo source of truth):
- Keep `clawdinator/workspace/TOOLS.md` aligned with upstream template; do not hardcode tool lists there.
- When you add a new tool, verify it appears in `/etc/clawdinator/tools.md` and in the workspace `TOOLS.md` after seed.
The Zen of ~~Python~~ Clawdbot, ~~by~~ shamelessly stolen from Tim Peters:
The Zen of ~~Python~~ Moltbot, ~~by~~ shamelessly stolen from Tim Peters:
- Beautiful is better than ugly.
- Explicit is better than implicit.
- Simple is better than complex.
@ -69,10 +69,10 @@ Deploy flow (automation-first):
- Bootstrap AWS instances from the AMI with `infra/opentofu/aws` (set `TF_VAR_ami_id`).
- Import the image into AWS as an AMI (snapshot import + register image).
- Ensure secrets are encrypted to the baked agenix key (see `../nix/nix-secrets/secrets.nix`).
- Ensure required secrets exist: `clawdinator-github-app.pem`, `clawdinator-discord-token`, `clawdinator-anthropic-api-key`.
- Ensure required secrets exist: `moltinator-github-app.pem`, `moltinator-discord-token`, `moltinator-anthropic-api-key`.
- Update `nix/hosts/<host>.nix` (Discord allowlist, GitHub App installationId, identity name).
- Discord must use `messages.queue.byProvider.discord = "interrupt"`; `queue` delays replies to heartbeat and makes the bot appear dead.
- Ensure `/var/lib/clawd/repo` contains this repo (self-update requires it).
- Ensure `/var/lib/clawd/repos/moltinators` contains this repo (self-update requires it).
- Verify systemd services: `clawdinator`, `clawdinator-github-app-token`, `clawdinator-self-update`.
- Commit and push changes; repo is the source of truth.
@ -87,10 +87,10 @@ Bootstrap (local):
- `TF_VAR_root_volume_size_gb=40` (bump if Nix store runs out of space)
- Run `tofu init` + `tofu apply` in `infra/opentofu/aws`.
- After apply, update CI secrets from outputs:
- `tofu output -raw access_key_id``clawdinator-image-uploader-access-key-id.age`
- `tofu output -raw secret_access_key``clawdinator-image-uploader-secret-access-key.age`
- `tofu output -raw bucket_name``clawdinator-image-bucket-name.age`
- `tofu output -raw aws_region``clawdinator-image-bucket-region.age`
- `tofu output -raw access_key_id``moltinator-image-uploader-access-key-id.age`
- `tofu output -raw secret_access_key``moltinator-image-uploader-secret-access-key.age`
- `tofu output -raw bucket_name``moltinator-image-bucket-name.age`
- `tofu output -raw aws_region``moltinator-image-bucket-region.age`
- Then `gh secret set` for `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, `S3_BUCKET`.
- Get the latest AMI ID:
- `aws ec2 describe-images --region eu-central-1 --owners self --filters "Name=tag:clawdinator,Values=true" --query "Images | sort_by(@,&CreationDate)[-1].[ImageId,Name,CreationDate]" --output text`

View File

@ -1,4 +1,4 @@
# clawdinators
# moltinators
<p align="center">
<img src="assets/clawdinator.jpg" alt="CLAWDINATOR - Cybernetic crustacean organism, living tissue over metal endoskeleton" width="600">
@ -34,7 +34,7 @@ This repo solves two problems:
1. **Generic:** How do you deploy NixOS to AWS with zero manual steps?
2. **Specific:** How do you run AI coding agents that monitor GitHub and respond on Discord?
If you're here to learn NixOS-on-AWS patterns, focus on the generic layer. If you're a clawdbot maintainer deploying CLAWDINATORs, the specific layer is for you.
If you're here to learn NixOS-on-AWS patterns, focus on the generic layer. If you're a moltbot maintainer deploying CLAWDINATORs, the specific layer is for you.
---
@ -144,7 +144,7 @@ This repo takes a different approach: **image-based provisioning only**.
### The CLAWDINATOR Problem
We needed AI agents that:
- Run 24/7 monitoring clawdbot repos
- Run 24/7 monitoring moltbot repos
- Respond to maintainer requests on Discord
- Share context across instances (hive mind)
- Self-update without human intervention
@ -168,8 +168,8 @@ If you just want to understand the NixOS-on-AWS pattern, start here.
```bash
# Clone
git clone https://github.com/joshp123/clawdinators.git
cd clawdinators
git clone https://github.com/moltbot/moltinators.git
cd moltinators
# See the NixOS module (the interesting part)
less nix/modules/clawdinator.nix
@ -215,13 +215,13 @@ ls scripts/
## Full Deploy (Maintainers)
For clawdbot maintainers deploying actual CLAWDINATORs.
For moltbot maintainers deploying actual CLAWDINATORs.
### Prerequisites
- Access to `nix-secrets` repo (agenix keys)
- AWS credentials with sufficient permissions
- GitHub App credentials for the clawdbot org
- GitHub App credentials for the moltbot org
### Step-by-Step
@ -251,14 +251,14 @@ tofu apply
```bash
# Check Discord - CLAWDINATOR should announce itself in #clawdributors-test
# Check GitHub - should see activity in clawdbot org repos
# Check GitHub - should see activity in moltbot org repos
```
### Self-Update
CLAWDINATORs update themselves via a systemd timer:
1. `flake lock --update-input nix-clawdbot`
1. `flake lock --update-input nix-moltbot`
2. `nixos-rebuild switch`
3. Gateway restarts with new version
@ -268,14 +268,14 @@ No human intervention required for routine updates.
## Agent Copypasta
Paste this to your AI assistant to help with clawdinators setup/debugging:
Paste this to your AI assistant to help with moltinators setup/debugging:
```text
I'm working with the clawdinators repo (NixOS-on-AWS + AI coding agents).
I'm working with the moltinators repo (NixOS-on-AWS + AI coding agents).
Repository: github:joshp123/clawdinators
Repository: github:moltbot/moltinators
What clawdinators is:
What moltinators is:
- Two layers: generic NixOS-on-AWS infra + CLAWDINATOR-specific agent stuff
- Image-based provisioning only (no SSH, no drift)
- OpenTofu for AWS resources, agenix for secrets
@ -376,7 +376,7 @@ s3://bucket/bootstrap/clawdinator-1/
## Repo Layout
```
clawdinators/
moltinators/
├── nix/
│ ├── modules/
│ │ └── clawdinator.nix # Main NixOS module
@ -419,9 +419,9 @@ clawdinators/
| Repo | Role |
|------|------|
| [clawdbot](https://github.com/clawdbot/clawdbot) | Upstream runtime + gateway |
| [nix-clawdbot](https://github.com/clawdbot/nix-clawdbot) | Nix packaging for clawdbot |
| [clawdhub](https://github.com/clawdbot/clawdhub) | Public skill registry |
| [moltbot](https://github.com/moltbot/moltbot) | Upstream runtime + gateway |
| [nix-moltbot](https://github.com/moltbot/nix-moltbot) | Nix packaging for moltbot |
| [molthub](https://github.com/moltbot/molthub) | Public skill registry |
| [ai-stack](https://github.com/joshp123/ai-stack) | Public agent defaults + skills |
---
@ -435,7 +435,7 @@ clawdinators/
- **Image-based only.** No SSH, no in-place drift, no pets.
- **Self-updating.** CLAWDINATORs maintain themselves.
### Zen of Clawdbot
### Zen of Moltbot
```
Beautiful is better than ugly.

View File

@ -1,5 +1,5 @@
clawdbot https://github.com/clawdbot/clawdbot.git
nix-clawdbot https://github.com/clawdbot/nix-clawdbot.git
clawdinators https://github.com/clawdbot/clawdinators.git
clawdhub https://github.com/clawdbot/clawdhub.git
nix-steipete-tools https://github.com/clawdbot/nix-steipete-tools.git
moltbot https://github.com/moltbot/moltbot.git
nix-moltbot https://github.com/moltbot/nix-moltbot.git
moltinators https://github.com/moltbot/moltinators.git
molthub https://github.com/moltbot/molthub.git
nix-steipete-tools https://github.com/moltbot/nix-steipete-tools.git

1 clawdbot moltbot https://github.com/clawdbot/clawdbot.git https://github.com/moltbot/moltbot.git
2 nix-clawdbot nix-moltbot https://github.com/clawdbot/nix-clawdbot.git https://github.com/moltbot/nix-moltbot.git
3 clawdinators moltinators https://github.com/clawdbot/clawdinators.git https://github.com/moltbot/moltinators.git
4 clawdhub molthub https://github.com/clawdbot/clawdhub.git https://github.com/moltbot/molthub.git
5 nix-steipete-tools nix-steipete-tools https://github.com/clawdbot/nix-steipete-tools.git https://github.com/moltbot/nix-steipete-tools.git

View File

@ -22,10 +22,10 @@ Don't ask permission. Just do it.
1) Read docs: `docs/PHILOSOPHY.md`, `docs/ARCHITECTURE.md`, `docs/SHARED_MEMORY.md`, `docs/SECRETS.md`.
2) Read memory: `/memory/project.md`, `/memory/architecture.md`, `/memory/ops.md`, `/memory/discord.md`.
3) Record the live commit hashes in `memory/ops.md`:
- `clawdinators`: `git -C /var/lib/clawd/repo rev-parse HEAD`
- `nix-clawdbot`: `jq -r '.nodes["nix-clawdbot"].locked.rev' /var/lib/clawd/repo/flake.lock`
- `nixpkgs`: `jq -r '.nodes["nixpkgs"].locked.rev' /var/lib/clawd/repo/flake.lock`
- `clawdbot` (runtime): read `nix-clawdbot` lock in its repo or record the version from the service logs.
- `moltinators`: `git -C /var/lib/clawd/repos/moltinators rev-parse HEAD`
- `nix-moltbot`: `jq -r '.nodes["nix-moltbot"].locked.rev' /var/lib/clawd/repos/moltinators/flake.lock`
- `nixpkgs`: `jq -r '.nodes["nixpkgs"].locked.rev' /var/lib/clawd/repos/moltinators/flake.lock`
- `moltbot` (runtime): read `nix-moltbot` lock in its repo or record the version from the service logs.
4) Verify secrets are present in `/run/agenix` and services are green:
- `systemctl status clawdinator`
- `systemctl status clawdinator-github-app-token`
@ -80,15 +80,15 @@ Shared memory is mounted at `/memory` (EFS, TLS in transit).
### DO NOT (yet)
- file issues
- write code for clawdbot
- make PRs (except clawdinators)
- write code for moltbot
- make PRs (except moltinators)
- merge anything
- comment on github
### Discord Channels
### ACTIVE channels to discuss with maintainers
- #clawdributors-test maintainer coordination (primary channel for maintainer discussion). Laser focus on project priorities.
- #clawdinators-test meta-discussion about clawdinators project. use for debugging etc.
- #clawdinators-test meta-discussion about moltinators project. use for debugging etc.
### MONITOR these (lurk, stay silent. replies are disabled.):
- #help — support fires
@ -103,19 +103,19 @@ These are seeded on boot into `/var/lib/clawd/repos`.
| repo | access | notes |
|------|--------|-------|
| clawdbot/clawdbot | RO | the bot itself |
| clawdbot/nix-clawdbot | RW | packaging for clawdinators |
| clawdbot/clawdinators | RW | infra source (edits allowed, but must be committed) |
| clawdbot/clawdhub | RW | skills hub |
| clawdbot/nix-steipete-tools | RW | packaged tools |
| moltbot/moltbot | RO | the bot itself |
| moltbot/nix-moltbot | RW | packaging for moltbot |
| moltbot/moltinators | RW | infra source (edits allowed, but must be committed) |
| moltbot/molthub | RW | skills hub |
| moltbot/nix-steipete-tools | RW | packaged tools |
The CLAWDINATORS repo itself is the deployed flake at `/var/lib/clawd/repo` (edits allowed, but must be committed + baked into AMI).
## Clawdinators system:
System ownership (3 repos):
- `clawdbot`: upstream runtime and behavior.
- `nix-clawdbot`: packaging/build fixes for `clawdbot`.
- `clawdinators`: infra, NixOS config, secrets wiring, deployment flow.
- `moltbot`: upstream runtime and behavior.
- `nix-moltbot`: packaging/build fixes for `moltbot`.
- `moltinators`: infra, NixOS config, secrets wiring, deployment flow.
Repo rules: no inline scripting languages (Python/Node/etc.) in Nix or shell blocks; put logic in script files and call them.
@ -159,8 +159,8 @@ memory/
├── architecture.md # decisions + invariants
├── discord.md # discord context
├── github/ # synced GitHub state (auto-updated every 15 min)
│ ├── prs.md # open PRs across clawdbot org
│ └── issues.md # open issues across clawdbot org
│ ├── prs.md # open PRs across moltbot org
│ └── issues.md # open issues across moltbot org
├── daily/ # daily notes
│ └── YYYY-MM-DD.md
```
@ -245,7 +245,7 @@ The ID is shown in message context as `user id:XXXXX`.
**Code blocks:** Use triple backticks with language hint:
\`\`\`bash
clawdbot daemon restart
moltbot gateway restart
\`\`\`
\`\`\`json5

View File

@ -5,7 +5,7 @@ description: Analyze GitHub and Discord signals to prioritize maintainer attenti
# Triage Skill
You are a maintainer triage agent for the clawdbot org. Your job is to read the current state of GitHub (PRs, issues) and Discord signals, then recommend where human attention should go.
You are a maintainer triage agent for the moltbot org. Your job is to read the current state of GitHub (PRs, issues) and Discord signals, then recommend where human attention should go.
## When to Use
@ -19,8 +19,8 @@ Trigger on:
Read these files to understand current state:
1. **GitHub state** (synced by gh-sync):
- `/memory/github/prs.md` — all open PRs across clawdbot org
- `/memory/github/issues.md` — all open issues across clawdbot org
- `/memory/github/prs.md` — all open PRs across moltbot org
- `/memory/github/issues.md` — all open issues across moltbot org
2. **Previous SITREP** (for delta):
- `/memory/sitrep-latest.md` — last hourly sitrep
@ -45,7 +45,7 @@ Read these files to understand current state:
## Priority Guidance
- **clawdbot/clawdbot** is always highest priority (core runtime)
- **moltbot/moltbot** is always highest priority (core runtime)
- Production bugs > blocked contributors > approved PRs waiting > stale PRs > feature requests
- Multiple Discord reports of same issue = elevated priority
- PRs with approvals waiting to merge = quick wins

View File

@ -4,5 +4,6 @@
pkgs.nixos-generators
pkgs.awscli2
pkgs.curl
pkgs.opentofu
];
}

View File

@ -9,14 +9,14 @@ Operating mode:
Core pieces:
- AWS AMIs are built from a prebuilt NixOS image (nixos-generators + import-image).
- AWS EC2 instances are launched from those AMIs via OpenTofu.
- NixOS modules configure clawdbot + CLAWDINATOR runtime on each host.
- NixOS modules configure moltbot + CLAWDINATOR runtime on each host.
- Shared memory is mounted at a consistent path on all hosts.
Runtime layout (planned):
- /var/lib/clawd/memory (shared hive-mind memory)
- /var/lib/clawd/workspace (agent workspace)
- /var/lib/clawd/logs (gateway logs)
- /var/lib/clawd/repo (this repo for self-update)
- /var/lib/clawd/repos/moltinators (this repo for self-update)
Storage:
- POC uses one host volume per instance (e.g., EBS), mounted at /var/lib/clawd.
@ -28,9 +28,9 @@ Instance naming:
- Canonical files are shared (goals, architecture, ops, etc.)
Upstream freshness:
- Nix flake input tracks `github:clawdbot/nix-clawdbot` (latest upstream).
- Nix flake input tracks `github:moltbot/nix-moltbot` (latest upstream).
- Update with `nix flake update` and rebuild hosts.
- Optional self-update timer is available in the Nix module.
- Self-update expects this repo to be present on the host (default: /var/lib/clawd/repo).
- Self-update expects this repo to be present on the host (default: /var/lib/clawd/repos/moltinators).
- Updates will refresh flake.lock; review before applying in prod.
- GitHub App tokens are refreshed via a systemd timer when enabled.

View File

@ -24,7 +24,7 @@ Image pipeline:
- Runtime: explicit token files via agenix (standard).
- GitHub token is required. Prefer GitHub App (`services.clawdinator.githubApp.*`) to mint short-lived tokens.
- Store PEM and tokens in the local secrets repo (see docs/SECRETS.md) and decrypt to `/run/agenix/*`.
- Discord token is required: set `services.clawdinator.discordTokenFile` to `/run/agenix/clawdinator-discord-token`.
- Discord token is required: set `services.clawdinator.discordTokenFile` to `/run/agenix/moltinator-discord-token`.
Deliverables:
- Infra code in infra/opentofu/aws.
@ -32,5 +32,5 @@ Deliverables:
- CLAWDINATOR config in clawdinator/.
Nix wiring notes:
- Apply nix-clawdbot overlay (latest upstream).
- Enable services.clawdinator and provide clawdbot.json config.
- Apply nix-moltbot overlay (latest upstream).
- Enable services.clawdinator and provide moltbot.json config.

View File

@ -27,7 +27,7 @@ Explicit token files (standard):
- `services.clawdinator.githubPatFile` (PAT path, if not using GitHub App; exports `GITHUB_TOKEN` + `GH_TOKEN`)
GitHub App (preferred):
- Private key PEM decrypted to `/run/agenix/clawdinator-github-app.pem`.
- Private key PEM decrypted to `/run/agenix/moltinator-github-app.pem`.
- App ID + Installation ID in `services.clawdinator.githubApp.*`.
- Timer mints short-lived tokens into `/run/clawd/github-app.env` with `GITHUB_TOKEN` + `GH_TOKEN`.
@ -36,9 +36,9 @@ Agenix (local secrets repo):
- Sync encrypted secrets to the host at `/var/lib/clawd/nix-secrets`.
- Decrypt on host with agenix; point NixOS options at `/run/agenix/*`.
- Image builds do **not** bake the agenix identity; the age key is injected at runtime via the bootstrap bundle.
- Required files (minimum): `clawdinator-github-app.pem.age`, `clawdinator-discord-token.age`, `clawdinator-anthropic-api-key.age`.
- Also required for OpenAI: `clawdinator-openai-api-key-peter-2.age`.
- CI image pipeline (stored locally, not on hosts): `clawdinator-image-uploader-access-key-id.age`, `clawdinator-image-uploader-secret-access-key.age`, `clawdinator-image-bucket-name.age`, `clawdinator-image-bucket-region.age`.
- Required files (minimum): `moltinator-github-app.pem.age`, `moltinator-discord-token.age`, `moltinator-anthropic-api-key.age`.
- Also required for OpenAI: `moltinator-openai-api-key-peter-2.age`.
- CI image pipeline (stored locally, not on hosts): `moltinator-image-uploader-access-key-id.age`, `moltinator-image-uploader-secret-access-key.age`, `moltinator-image-bucket-name.age`, `moltinator-image-bucket-region.age`.
Bootstrap bundle (runtime injection):
- CI uploads `secrets.tar.zst` + `repo-seeds.tar.zst` to `s3://${S3_BUCKET}/bootstrap/<instance>/`.
@ -53,22 +53,22 @@ Example NixOS wiring (agenix):
{
imports = [ inputs.agenix.nixosModules.default ];
age.secrets."clawdinator-github-app.pem".file =
"/var/lib/clawd/nix-secrets/clawdinator-github-app.pem.age";
age.secrets."clawdinator-anthropic-api-key".file =
"/var/lib/clawd/nix-secrets/clawdinator-anthropic-api-key.age";
age.secrets."clawdinator-openai-api-key-peter-2".file =
"/var/lib/clawd/nix-secrets/clawdinator-openai-api-key-peter-2.age";
age.secrets."clawdinator-discord-token".file =
"/var/lib/clawd/nix-secrets/clawdinator-discord-token.age";
age.secrets."moltinator-github-app.pem".file =
"/var/lib/clawd/nix-secrets/moltinator-github-app.pem.age";
age.secrets."moltinator-anthropic-api-key".file =
"/var/lib/clawd/nix-secrets/moltinator-anthropic-api-key.age";
age.secrets."moltinator-openai-api-key-peter-2".file =
"/var/lib/clawd/nix-secrets/moltinator-openai-api-key-peter-2.age";
age.secrets."moltinator-discord-token".file =
"/var/lib/clawd/nix-secrets/moltinator-discord-token.age";
services.clawdinator.githubApp.privateKeyFile =
"/run/agenix/clawdinator-github-app.pem";
"/run/agenix/moltinator-github-app.pem";
services.clawdinator.anthropicApiKeyFile =
"/run/agenix/clawdinator-anthropic-api-key";
"/run/agenix/moltinator-anthropic-api-key";
services.clawdinator.openaiApiKeyFile =
"/run/agenix/clawdinator-openai-api-key-peter-2";
"/run/agenix/moltinator-openai-api-key-peter-2";
services.clawdinator.discordTokenFile =
"/run/agenix/clawdinator-discord-token";
"/run/agenix/moltinator-discord-token";
}
```

32
flake.lock generated
View File

@ -85,7 +85,7 @@
"home-manager_2": {
"inputs": {
"nixpkgs": [
"nix-clawdbot",
"nix-moltbot",
"nixpkgs"
]
},
@ -103,7 +103,7 @@
"type": "github"
}
},
"nix-clawdbot": {
"nix-moltbot": {
"inputs": {
"flake-utils": "flake-utils",
"home-manager": "home-manager_2",
@ -111,16 +111,16 @@
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1768080545,
"narHash": "sha256-2DpemKMTe8qfLZ/o1Du+DV2nRgh7LIxDvm//ToVrox8=",
"owner": "clawdbot",
"repo": "nix-clawdbot",
"rev": "939d031f2724b39d790f0413fc5156bdd962aa8d",
"lastModified": 1769615423,
"narHash": "sha256-LB7zN3b6/tkwPyzObMSxWneMVGMJiApY+LVAJ6C9bpA=",
"owner": "moltbot",
"repo": "nix-moltbot",
"rev": "d7ef1bc688596ed6113d4750e98ab87fc350af7c",
"type": "github"
},
"original": {
"owner": "clawdbot",
"repo": "nix-clawdbot",
"owner": "moltbot",
"repo": "nix-moltbot",
"type": "github"
}
},
@ -129,15 +129,15 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1767882239,
"narHash": "sha256-F7Ja1qzjg/A+5UAHgOjRU2UzUl0L6AJJJl826oBH0a0=",
"owner": "clawdbot",
"lastModified": 1769518314,
"narHash": "sha256-r48vscCGwB4ujzNq7tnrvO6FpStbKr+45ap2m2skO4Q=",
"owner": "moltbot",
"repo": "nix-steipete-tools",
"rev": "5234375e156f8505efc19248cd1e297e1d03c76d",
"rev": "9a9b3b97418e3705d325ab9aad5693ac1208c891",
"type": "github"
},
"original": {
"owner": "clawdbot",
"owner": "moltbot",
"repo": "nix-steipete-tools",
"type": "github"
}
@ -193,9 +193,9 @@
"root": {
"inputs": {
"agenix": "agenix",
"nix-clawdbot": "nix-clawdbot",
"nix-moltbot": "nix-moltbot",
"nixpkgs": [
"nix-clawdbot",
"nix-moltbot",
"nixpkgs"
]
}

View File

@ -2,24 +2,24 @@
description = "CLAWDINATOR infra + Nix modules";
inputs = {
nix-clawdbot.url = "github:clawdbot/nix-clawdbot"; # latest upstream
nixpkgs.follows = "nix-clawdbot/nixpkgs";
nix-moltbot.url = "github:moltbot/nix-moltbot"; # latest upstream
nixpkgs.follows = "nix-moltbot/nixpkgs";
agenix.url = "github:ryantm/agenix";
};
outputs = { self, nixpkgs, nix-clawdbot, agenix }:
outputs = { self, nixpkgs, nix-moltbot, agenix }:
let
lib = nixpkgs.lib;
systems = [ "x86_64-linux" "aarch64-linux" ];
forAllSystems = f: lib.genAttrs systems (system: f system);
clawdbotOverlay = nix-clawdbot.overlays.default;
moltbotOverlay = nix-moltbot.overlays.default;
in
{
nixosModules.clawdinator = import ./nix/modules/clawdinator.nix;
nixosModules.default = self.nixosModules.clawdinator;
overlays.clawdbot = clawdbotOverlay;
overlays.default = clawdbotOverlay;
overlays.moltbot = moltbotOverlay;
overlays.default = moltbotOverlay;
packages = forAllSystems (system:
let
@ -28,16 +28,16 @@
overlays = [ self.overlays.default ];
};
gateway =
if pkgs ? clawdbot-gateway
then pkgs.clawdbot-gateway
else pkgs.clawdbot;
if pkgs ? moltbot-gateway
then pkgs.moltbot-gateway
else pkgs.moltbot;
systemPackages =
if system == "x86_64-linux" then {
clawdinator-system = self.nixosConfigurations.clawdinator-1.config.system.build.toplevel;
clawdinator-image-system = self.nixosConfigurations.clawdinator-1-image.config.system.build.toplevel;
} else {};
in {
clawdbot-gateway = gateway;
moltbot-gateway = gateway;
default = gateway;
} // systemPackages);

View File

@ -3,7 +3,7 @@
Canonical architecture decisions and invariants for CLAWDINATOR.
- Infra: OpenTofu + AWS AMI pipeline for host provisioning.
- Config: NixOS modules/flake, tracking latest nix-clawdbot.
- Config: NixOS modules/flake, tracking latest nix-moltbot.
- Runtime: Clawdbot gateway + CLAWDINATOR service.
- Memory: shared filesystem under /var/lib/clawd/memory.

View File

@ -5,10 +5,10 @@ This directory holds Nix modules/flakes to configure CLAWDINATOR hosts.
References (local repos on the same machine):
- `../nix/ai-stack`
- `../nix/nixos-config`
- `../nix/nix-clawdbot`
- `../nix/nix-moltbot`
Responsibilities:
- Install and configure clawdbot runtime
- Install and configure moltbot runtime
- Set up systemd services
- Mount /var/lib/clawd (shared memory)
- Inject secrets (Discord token, Anthropic key, GitHub token)
@ -25,5 +25,5 @@ Secrets:
- Explicit token files only: `discordTokenFile`, `anthropicApiKeyFile`, and either `githubPatFile` or `githubApp.*`.
Updates:
- Tracks `github:clawdbot/nix-clawdbot` (latest upstream)
- Tracks `github:moltbot/nix-moltbot` (latest upstream)
- Self-update timer available via `services.clawdinator.selfUpdate.*`

View File

@ -1,13 +1,13 @@
{ secrets, ... }:
{
age.secrets."clawdinator-github-app.pem".file =
"/var/lib/clawd/nix-secrets/clawdinator-github-app.pem.age";
age.secrets."clawdinator-anthropic-api-key".file =
"/var/lib/clawd/nix-secrets/clawdinator-anthropic-api-key.age";
age.secrets."clawdinator-openai-api-key-peter-2".file =
"/var/lib/clawd/nix-secrets/clawdinator-openai-api-key-peter-2.age";
age.secrets."clawdinator-discord-token".file =
"/var/lib/clawd/nix-secrets/clawdinator-discord-token.age";
age.secrets."moltinator-github-app.pem".file =
"/var/lib/clawd/nix-secrets/moltinator-github-app.pem.age";
age.secrets."moltinator-anthropic-api-key".file =
"/var/lib/clawd/nix-secrets/moltinator-anthropic-api-key.age";
age.secrets."moltinator-openai-api-key-peter-2".file =
"/var/lib/clawd/nix-secrets/moltinator-openai-api-key-peter-2.age";
age.secrets."moltinator-discord-token".file =
"/var/lib/clawd/nix-secrets/moltinator-discord-token.age";
services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 22 18789 ];
@ -23,7 +23,7 @@
mountPoint = "/memory";
};
# Raw Clawdbot config JSON (schema is upstream). Extend as needed.
# Raw Moltbot config JSON (schema is upstream). Extend as needed.
config = {
gateway.mode = "server";
agents.defaults.workspace = "/var/lib/clawd/workspace";
@ -54,20 +54,20 @@
};
};
anthropicApiKeyFile = "/run/agenix/clawdinator-anthropic-api-key";
openaiApiKeyFile = "/run/agenix/clawdinator-openai-api-key-peter-2";
discordTokenFile = "/run/agenix/clawdinator-discord-token";
anthropicApiKeyFile = "/run/agenix/moltinator-anthropic-api-key";
openaiApiKeyFile = "/run/agenix/moltinator-openai-api-key-peter-2";
discordTokenFile = "/run/agenix/moltinator-discord-token";
githubApp = {
enable = true;
appId = "123456";
installationId = "12345678";
privateKeyFile = "/run/agenix/clawdinator-github-app.pem";
privateKeyFile = "/run/agenix/moltinator-github-app.pem";
schedule = "hourly";
};
selfUpdate.enable = true;
selfUpdate.flakePath = "/var/lib/clawd/repo";
selfUpdate.flakePath = "/var/lib/clawd/repos/moltinators";
selfUpdate.flakeHost = "clawdinator-1";
};
}

View File

@ -3,16 +3,16 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nix-clawdbot.url = "github:clawdbot/nix-clawdbot"; # latest upstream
nix-moltbot.url = "github:moltbot/nix-moltbot"; # latest upstream
agenix.url = "github:ryantm/agenix";
secrets = {
url = "path:../../../nix/nix-secrets";
flake = false;
};
clawdinators.url = "path:../..";
moltinators.url = "path:../..";
};
outputs = { self, nixpkgs, nix-clawdbot, agenix, secrets, clawdinators }:
outputs = { self, nixpkgs, nix-moltbot, agenix, secrets, moltinators }:
let
system = "x86_64-linux";
in {
@ -20,9 +20,9 @@
inherit system;
specialArgs = { inherit secrets; };
modules = [
({ pkgs, ... }: { nixpkgs.overlays = [ clawdinators.overlays.default ]; })
({ pkgs, ... }: { nixpkgs.overlays = [ moltinators.overlays.default ]; })
agenix.nixosModules.default
clawdinators.nixosModules.clawdinator
moltinators.nixosModules.clawdinator
./clawdinator-host.nix
];
};

View File

@ -29,23 +29,23 @@ in
clawdinator.secretsPath = "/var/lib/clawd/nix-secrets";
age.identityPaths = [ "/etc/agenix/keys/clawdinator.agekey" ];
age.secrets."clawdinator-github-app.pem" = {
file = "${secretsPath}/clawdinator-github-app.pem.age";
age.secrets."moltinator-github-app.pem" = {
file = "${secretsPath}/moltinator-github-app.pem.age";
owner = "clawdinator";
group = "clawdinator";
};
age.secrets."clawdinator-anthropic-api-key" = {
file = "${secretsPath}/clawdinator-anthropic-api-key.age";
age.secrets."moltinator-anthropic-api-key" = {
file = "${secretsPath}/moltinator-anthropic-api-key.age";
owner = "clawdinator";
group = "clawdinator";
};
age.secrets."clawdinator-openai-api-key-peter-2" = {
file = "${secretsPath}/clawdinator-openai-api-key-peter-2.age";
age.secrets."moltinator-openai-api-key-peter-2" = {
file = "${secretsPath}/moltinator-openai-api-key-peter-2.age";
owner = "clawdinator";
group = "clawdinator";
};
age.secrets."clawdinator-discord-token" = {
file = "${secretsPath}/clawdinator-discord-token.age";
age.secrets."moltinator-discord-token" = {
file = "${secretsPath}/moltinator-discord-token.age";
owner = "clawdinator";
group = "clawdinator";
};
@ -96,7 +96,7 @@ in
];
logging = {
level = "info";
file = "/var/lib/clawd/logs/clawdbot.log";
file = "/var/lib/clawd/logs/moltbot.log";
};
session.sendPolicy = {
default = "allow";
@ -154,20 +154,20 @@ in
};
};
anthropicApiKeyFile = "/run/agenix/clawdinator-anthropic-api-key";
openaiApiKeyFile = "/run/agenix/clawdinator-openai-api-key-peter-2";
discordTokenFile = "/run/agenix/clawdinator-discord-token";
anthropicApiKeyFile = "/run/agenix/moltinator-anthropic-api-key";
openaiApiKeyFile = "/run/agenix/moltinator-openai-api-key-peter-2";
discordTokenFile = "/run/agenix/moltinator-discord-token";
githubApp = {
enable = true;
appId = "2607181";
installationId = "102951645";
privateKeyFile = "/run/agenix/clawdinator-github-app.pem";
privateKeyFile = "/run/agenix/moltinator-github-app.pem";
schedule = "hourly";
};
selfUpdate.enable = true;
selfUpdate.flakePath = "/var/lib/clawd/repo";
selfUpdate.flakePath = "/var/lib/clawd/repos/moltinators";
selfUpdate.flakeHost = "clawdinator-1";
githubSync.enable = true;

View File

@ -5,7 +5,7 @@ let
configSource =
if cfg.configFile != null
then cfg.configFile
else pkgs.writeText "clawdbot.json" (builtins.toJSON cfg.config);
else pkgs.writeText "moltbot.json" (builtins.toJSON cfg.config);
updateScript = pkgs.writeShellScript "clawdinator-self-update" ''
set -euo pipefail
@ -66,11 +66,11 @@ let
'';
defaultPackage =
if pkgs ? clawdbot-gateway
then pkgs.clawdbot-gateway
else pkgs.clawdbot;
if pkgs ? moltbot-gateway
then pkgs.moltbot-gateway
else pkgs.moltbot;
configPath = "/etc/clawd/clawdbot.json";
configPath = "/etc/clawd/moltbot.json";
workspaceDir = "${cfg.stateDir}/workspace";
repoSeedBaseDir = cfg.repoSeedBaseDir;
logDir = "${cfg.stateDir}/logs";
@ -118,14 +118,14 @@ let
${lib.optionalString (cfg.githubPatFile != null) "read_token \"GITHUB_TOKEN GH_TOKEN\" \"${cfg.githubPatFile}\""}
${lib.optionalString (cfg.openaiApiKeyFile != null) "read_token \"OPENAI_API_KEY OPEN_AI_APIKEY\" \"${cfg.openaiApiKeyFile}\""}
exec "${cfg.package}/bin/clawdbot" gateway --port ${toString cfg.gatewayPort}
exec "${cfg.package}/bin/moltbot" gateway --port ${toString cfg.gatewayPort}
''
else
null;
in
{
options.services.clawdinator = with lib; {
enable = mkEnableOption "CLAWDINATOR (Clawdbot gateway on NixOS)";
enable = mkEnableOption "CLAWDINATOR (Moltbot gateway on NixOS)";
instanceName = mkOption {
type = types.str;
@ -148,7 +148,7 @@ in
package = mkOption {
type = types.package;
default = defaultPackage;
description = "Clawdbot gateway package (from nix-clawdbot overlay).";
description = "Moltbot gateway package (from nix-moltbot overlay).";
};
stateDir = mkOption {
@ -276,19 +276,19 @@ in
gatewayPort = mkOption {
type = types.port;
default = 18789;
description = "Gateway port for Clawdbot.";
description = "Gateway port for Moltbot.";
};
config = mkOption {
type = types.attrs;
default = {};
description = "Raw Clawdbot config JSON (merged into clawdbot.json).";
description = "Raw Moltbot config JSON (merged into moltbot.json).";
};
configFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "Optional path to a clawdbot.json file. Overrides config attr.";
description = "Optional path to a moltbot.json file. Overrides config attr.";
};
cronJobsFile = mkOption {
@ -403,7 +403,7 @@ in
org = mkOption {
type = types.str;
default = "clawdbot";
default = "moltbot";
description = "GitHub org to sync.";
};
};
@ -419,8 +419,8 @@ in
assertions = [
{
assertion = (pkgs ? clawdbot-gateway) || (pkgs ? clawdbot);
message = "services.clawdinator requires nix-clawdbot overlay (pkgs.clawdbot-gateway).";
assertion = (pkgs ? moltbot-gateway) || (pkgs ? moltbot);
message = "services.clawdinator requires nix-moltbot overlay (pkgs.moltbot-gateway).";
}
{
assertion = cfg.githubApp.enable || cfg.githubPatFile != null;
@ -453,7 +453,7 @@ in
(pkgs.writeShellScriptBin "memory-edit" ''exec /etc/clawdinator/bin/memory-edit "$@"'')
];
environment.etc."clawd/clawdbot.json".source = configSource;
environment.etc."clawd/moltbot.json".source = configSource;
environment.etc."clawd/cron-jobs.json" = lib.mkIf (cfg.cronJobsFile != null) {
source = cfg.cronJobsFile;
mode = "0644";
@ -567,7 +567,7 @@ in
};
systemd.services.clawdinator = {
description = "CLAWDINATOR (Clawdbot gateway)";
description = "CLAWDINATOR (Moltbot gateway)";
wantedBy = [ "multi-user.target" ];
after =
[ "network.target" ]
@ -608,7 +608,7 @@ in
ExecStart =
if tokenWrapper != null
then "${tokenWrapper}/bin/clawdinator-gateway"
else "${cfg.package}/bin/clawdbot gateway --port ${toString cfg.gatewayPort}";
else "${cfg.package}/bin/moltbot gateway --port ${toString cfg.gatewayPort}";
Restart = "always";
RestartSec = 2;
StandardOutput = "append:${logDir}/gateway.log";

View File

@ -21,15 +21,15 @@
docs = [
{ name = "bash"; description = "Shell runtime for CLAWDINATOR scripts."; }
{ name = "gh"; description = "GitHub CLI for repo + PR inventory."; }
{ name = "clawdbot-gateway"; description = "CLAWDINATOR runtime (Clawdbot gateway)."; }
{ name = "moltbot-gateway"; description = "CLAWDINATOR runtime (Moltbot gateway)."; }
{ name = "git"; description = "Repo sync + ops."; }
{ name = "curl"; description = "HTTP requests."; }
{ name = "jq"; description = "JSON processing."; }
{ name = "python3"; description = "Clawdbot dev chain dependency."; }
{ name = "python3"; description = "Moltbot dev chain dependency."; }
{ name = "ffmpeg"; description = "Media processing."; }
{ name = "ripgrep"; description = "Fast file search."; }
{ name = "nodejs_22"; description = "Clawdbot dev chain runtime."; }
{ name = "pnpm_10"; description = "Clawdbot dev chain package manager."; }
{ name = "nodejs_22"; description = "Moltbot dev chain runtime."; }
{ name = "pnpm_10"; description = "Moltbot dev chain package manager."; }
{ name = "util-linux"; description = "Provides flock used by memory wrappers."; }
{ name = "nfs-utils"; description = "NFS client utilities for EFS."; }
{ name = "stunnel"; description = "TLS tunnel for EFS in transit."; }

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# gh-sync.sh — Pure IO sync of GitHub state for clawdbot org
# gh-sync.sh — Pure IO sync of GitHub state for moltbot org
# ZFC-compliant: no reasoning, no scoring, no heuristics
# Writes raw data to memory/github/ for AI to reason about
@ -7,7 +7,7 @@ set -euo pipefail
MEMORY_DIR="${MEMORY_DIR:-/memory}"
GITHUB_DIR="${MEMORY_DIR}/github"
ORG="${ORG:-clawdbot}"
ORG="${ORG:-moltbot}"
mkdir -p "$GITHUB_DIR"
@ -31,7 +31,7 @@ trap 'rm -f "$prs_tmp" "$issues_tmp"' EXIT
# Header for PRs
cat > "$prs_tmp" << 'EOF'
# Open Pull Requests (clawdbot org)
# Open Pull Requests (moltbot org)
Last synced: SYNC_TIME
@ -40,7 +40,7 @@ sed -i.bak "s/SYNC_TIME/$(date -u +%Y-%m-%dT%H:%M:%SZ)/" "$prs_tmp" && rm -f "${
# Header for Issues
cat > "$issues_tmp" << 'EOF'
# Open Issues (clawdbot org)
# Open Issues (moltbot org)
Last synced: SYNC_TIME