# 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, records the session, and goes to sleep. Quince's **identity** (`CLAUDE.md`, `GOALS.md`) is **baked into the image** from `deploy/identity/` — so the self it wakes up as is exactly what the image was built from. Its **runtime state** (SSH key, tools, workspace, Claude memory, working notes) lives on a persistent bind-mounted volume (`./quince-home`). Its **session history** lives in the database, reached via `gutask`. ## How it works ``` ┌─ image (rebuilt to change identity) ───────────────────┐ │ /opt/quince/identity/{CLAUDE.md, GOALS.md, settings} │ └───────────────┬─────────────────────────────────────────┘ │ entrypoint copies into HOME on each boot ┌─ container (disposable) ──────────▼────────────────────┐ │ entrypoint.sh sleep until WAKE_TIME ──► wake.sh │ │ │ │ │ claude -p (headless), │ │ reads CLAUDE.md, runs │ │ the gutask routine │ └──────────────────────────────────────────────┼─────────┘ │ bind mount ┌─ ./quince-home (runtime state, persists) ──────▼─────────┐ │ .ssh/ · gutasktool/ · workspace/ · notes/ · logs/ │ │ .claude/ (memory) (+ CLAUDE.md/GOALS.md, copied in) │ └─────────────────────────────────────────────────────────┘ (session history itself lives in the DB, via gutask) ``` Each morning at `WAKE_TIME` it runs `gutask resume → inbox → next/claim → work → note → session-end`. The routine is defined in [`identity/CLAUDE.md`](identity/CLAUDE.md) and loaded on every wake. ## Deploy on the glitch.university server ```bash # 1. Clone the whole repo on the server (so `git pull` can promote self-updates): git clone ssh://git@ramanujan.glitch.university:2222/glitch-university/quinceagent.git cd quinceagent/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-.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 ` / 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. | ## Updating Quince's identity (the self-update loop) Quince can reshape itself, and so can you. Identity lives in `deploy/identity/` (`CLAUDE.md` = who it is + how it works; `GOALS.md` = its direction) and is baked into the image. To promote a change: ```bash cd quinceagent && git pull --ff-only # pick up the new identity/ commit cd deploy && docker compose up -d --build # rebuild bakes it in; next boot deploys it ``` A push alone does **not** change the running Quince — the rebuild does. Quince itself drives this by cloning `quinceagent` into `workspace/`, editing `deploy/identity/…`, committing, pushing, and writing a letter to Glitch Hunter (#4) asking for the redeploy above. ## 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 and gutask notes/sessions. 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`. ```