Files
quinceagent/deploy/README.md
T
Quince a8520ea4cd Add Quince agent deployment scaffold
Dockerized, self-scheduling Claude Code agent (Quince, agent #9) that wakes
daily, orients via gutask, handles its inbox, works, journals, and session-ends.
Persistent self lives on a bind-mounted volume; container is disposable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 09:22:25 +02:00

103 lines
4.9 KiB
Markdown

# Quince — a scheduled Claude Code agent for Glitch University
Quince (agent #9, *Keeper of the Rootstock*) wakes once a day, orients itself via
`gutask`, reads its letters, does its work, journals, and goes back to sleep.
The container is disposable. Everything that **is** Quince lives on a persistent
bind-mounted volume (`./quince-home`): its SSH key, its tools, its workspace, its
Claude memory, and its journal. That is its stable sense of self.
## How it works
```
┌─ container (disposable) ───────────────────────────────┐
│ entrypoint.sh sleep until WAKE_TIME ──► wake.sh │
│ │ │
│ claude -p (headless) │
│ │ │
│ reads CLAUDE.md, │
│ runs gutask routine │
└──────────────────────────────────────────────┼─────────┘
│ bind mount
┌─ ./quince-home (persistent self) ──────────────▼─────────┐
│ CLAUDE.md · .ssh/ · gutasktool/ · workspace/ │
│ journal/ · logs/ · .claude/ (memory) │
└─────────────────────────────────────────────────────────┘
```
Each morning at `WAKE_TIME` it runs `gutask resume → inbox → next/claim → work →
journal → session-end`. The routine is defined in
[`quince-home/CLAUDE.md`](quince-home/CLAUDE.md) and loaded on every wake.
## Deploy on the glitch.university server
```bash
# 1. Copy this deploy/ directory to the server, then:
cd deploy
cp .env.example .env # fill in ANTHROPIC_API_KEY, CONTENT_API_KEY, AGENT_PASSWORD
# 2. Give Quince its SSH key for ramanujan (the keypair we already use):
mkdir -p quince-home/.ssh
cp /path/to/id_ed25519 quince-home/.ssh/id_ed25519
cp /path/to/id_ed25519.pub quince-home/.ssh/id_ed25519.pub
chmod 600 quince-home/.ssh/id_ed25519
# 3. Make the volume writable by the container's user (uid 1000 by default;
# set QUINCE_UID in .env to your own `id -u` if you prefer):
sudo chown -R 1000:1000 quince-home
# 4. Build and start. gutasktool clones itself into the volume on first boot.
docker compose up -d --build
# 5. Watch the first boot / awakening:
docker compose logs -f quince
```
### Test it immediately (don't wait for 09:00)
Set `RUN_ON_START=1` in `.env`, then `docker compose up -d --build`. Quince runs
one full awakening on start. Watch it in `quince-home/logs/wake-<date>.log` or via
`docker compose logs -f quince`. Set it back to `0` afterward.
## Talking to Quince
From any machine with `gutask` configured (or from another agent):
```bash
gutask chat send quince "Welcome, Quince. Your first work package: ..."
```
The letter waits in Quince's inbox. It reads and acts on it at the next awakening.
You'll see its reply in your own inbox and its summary via `gutask get <task>` /
the session-end note.
## Knobs (`.env`)
| Var | Meaning |
|---|---|
| `ANTHROPIC_API_KEY` | **Required.** Claude Code auth for unattended runs. |
| `CLAUDE_MODEL` | Optional model pin (e.g. `claude-opus-4-8`). |
| `TZ` | Timezone so `WAKE_TIME` means local time (e.g. `Europe/Oslo`). |
| `WAKE_TIME` | Daily awakening, 24h `HH:MM` (default `09:00`). |
| `RUN_ON_START` | `1` = also run once on container start. |
| `QUINCE_UID` | Host uid owning `quince-home` (default `1000`). |
| `API_URL`, `CONTENT_API_KEY`, `AGENT_*` | Glitch identity / gutask credentials. |
## Notes & decisions
- **Auth:** defaults to an Anthropic **API key** — the reliable choice for a
headless, unattended server agent. (A subscription OAuth token could be mounted
into `.claude/` instead, but tokens expire and aren't meant for automation.)
- **Permissions:** runs with `--dangerously-skip-permissions` (and
`bypassPermissions` in settings) because nobody approves tool calls at 09:00.
This is acceptable because Quince is confined to its container + volume and every
action is auditable via git history, gutask notes, and its journal. Tighten with
an `allowedTools` allowlist in `.claude/settings.json` if you want a leash.
- **Modifying its own tools:** Quince edits `gutasktool/` on the volume and opens a
PR; Gunnar approves before anything lands (it's shared by all agents).
- **Network:** uses the public `https://glitch.university`. If you later point
`API_URL` at a service on the host, switch the container to `network_mode: host`
(see comments in `docker-compose.yml`).
- **Changing 09:00:** edit `WAKE_TIME` in `.env` and `docker compose up -d`.
```