Document github.mirror-token and per-repo config.fnl schema
mirror-token uses kebab-case (not underscore) — the serde rename_all
means :mirror_token is silently ignored. Docs now call this out
explicitly and document both the global and per-repo mirror keys.

Also corrects README: mirroring is server-side on push, not a CI job.

https://claude.ai/code/session_018kJq4XvfvCe7XgnFGXXiKQ
change
commit 3cca3ec7cfc890192c915330642f61b7ce7a3ba3
author Claude <noreply@anthropic.com>
date
parent rovwxnmp
diff --git a/README.md b/README.md
index c308fae..a89f0af 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,8 @@ A Rust binary that runs in a Docker container, fronted by the host's sshd and a
 
 - **Git hosting over SSH**, via the host's sshd dispatching into the container. Explicit repo creation (`ssh git@host quire repo new <name>`).
 - **A read-only web view** for browsing README, tree, history, blame, diffs, and refs.
-- **Fennel-based CI** (Fennel is a Lisp that compiles to Lua), with pipelines defined in `.quire/ci.fnl`. Mirroring to GitHub is expressed as an ordinary CI job that shells out `git push` with a token from the global secrets map. Unsandboxed by default since every pipeline is code I've written; a bubblewrap-based opt-in is available for the day quire ever runs code I haven't.
+- **Fennel-based CI** (Fennel is a Lisp that compiles to Lua), with pipelines defined in `.quire/ci.fnl`. Unsandboxed by default since every pipeline is code I've written; a bubblewrap-based opt-in is available for the day quire ever runs code I haven't.
+- **Automatic GitHub mirroring** on every push. Set `:github :mirror` in `.quire/config.fnl` and `:github :mirror-token` in the global config; quire force-pushes each updated ref to the mirror URL independently of CI.
 - **Email notifications** for CI failures and recoveries. SMTP via `msmtp`; plain text; per-repo config for what to send and to whom.
 
 No issues, no PRs, no user management, no webhooks. Use the GitHub mirror for the social stuff; quire is your forge.
diff --git a/docs/config.md b/docs/config.md
index 55311bd..5dc440d 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -10,11 +10,14 @@ Lives at `/var/quire/config.fnl` on the bind-mounted volume.
 Operator-created. Read once at launch; a server restart is required to
 pick up changes.
 
-| Key                  | Type           | Required | Purpose                                                  |
-|----------------------|----------------|----------|----------------------------------------------------------|
-| `:port`              | integer        | no       | TCP port the HTTP server binds to (on `0.0.0.0`). Default: `3000`. |
-| `:sentry :dsn`       | `SecretString` | no       | Sentry DSN for error reporting from both `quire` and `quire-ci`. Omit to disable. |
-| `:secrets`           | table          | no       | Named secrets exposed to `ci.fnl` jobs as `(secret :name)`. |
+| Key                       | Type           | Required | Purpose                                                  |
+|---------------------------|----------------|----------|----------------------------------------------------------|
+| `:port`                   | integer        | no       | TCP port the HTTP server binds to (on `0.0.0.0`). Default: `3000`. |
+| `:sentry :dsn`            | `SecretString` | no       | Sentry DSN for error reporting from both `quire` and `quire-ci`. Omit to disable. |
+| `:secrets`                | table          | no       | Named secrets exposed to `ci.fnl` jobs as `(secret :name)`. |
+| `:github :mirror-token`   | `SecretString` | no       | Token used to authenticate pushes to per-repo GitHub mirrors. Required for mirroring to work; omit to disable. |
+
+Note: key names use hyphens, not underscores (e.g. `:mirror-token`, not `:mirror_token`).
 
 Minimal (no Sentry, no secrets):
 
@@ -38,11 +41,26 @@ the server from starting.
 Files quire reads from a checked-in `.quire/` directory in the working
 tree:
 
-- `.quire/ci.fnl` — pipeline definition (jobs, image, mirror).
+- `.quire/ci.fnl` — pipeline definition (jobs, image).
 - `.quire/Dockerfile` — image built per run when the CI executor is
   `docker` and no other image is supplied.
-- `.quire/config.fnl` — reserved for future use (notifications,
-  visibility settings, etc.); not yet read.
+- `.quire/config.fnl` — per-repo settings; read at the pushed commit's
+  SHA on every push.
+
+### `.quire/config.fnl` schema
+
+| Key                  | Type   | Required | Purpose                                                        |
+|----------------------|--------|----------|----------------------------------------------------------------|
+| `:github :mirror`    | string | no       | HTTPS URL to mirror every pushed ref to (e.g. `"https://github.com/user/repo.git"`). Requires `:github :mirror-token` in the global config. |
+
+Example:
+
+```fennel
+{:github {:mirror "https://github.com/user/repo.git"}}
+```
+
+The file is read via `git show <new-sha>:.quire/config.fnl`, so changes
+take effect on the push that includes the commit updating the file.
 
 ## SecretString values