📚 Reference

Generated, not hand-copied.


Everything below is read from the real source at request time — the AI vocabulary contract and GRAIN's token slots. Change the source, this page changes with it.

Actions

Generated from grain/ai/contract.ts's ACTIONS registry — the single source of truth. Payload fields marked * are required; hints are MCP-style behaviour flags.

verbpayloadaccepts (surface kinds)depthhintswhat it does
item.archiveno argsitemlightidempotentArchive an item (stands in for task.complete on the optimistic light path).
say.settext*:stringreflectionlightidempotentWrite a noted line back into a reflection surface.
say.streamno argssay-streamlightidempotentStream a reflection line out token by token.
demo.runno argsscreenheavyidempotentPlay a scripted AI-acting demo on the current screen.
desk.stopno argsscreenlightreadOnly, idempotentAsk the AI to halt the current run (mediated — never a force-kill).
chat.sendtext*:stringchat-loglightSend a chat message; the AI's reply streams back over SSE.
note.appendtext*:string (markdown)notepadlightAppend one markdown entry to the notepad.
note.replacetext*:string (markdown)notepadlightdestructive, idempotentRewrite the whole notepad from one markdown body.
navigatehref*:string (root-relative path, e.g. /notes)screenlightreadOnly, idempotentChange screens — same-origin, root-relative href only (validated at the door).
field.setvalue*:string (plain text; replaces the field's current value)fieldlightdestructive, idempotentPrefill a registered form field with drafted text — the human reviews and submits; the AI never submits.
Surface kinds

Every kind at least one verb above accepts.

kind
chat-log
field
item
notepad
reflection
say-stream
screen
Render ops

The effect kinds the client dispatcher applies (see AI-INTERFACE.md).

opmeans
replaceswap the target's HTML — the confirmed/committed fragment
appendadd HTML to the end of the target (a chat log, a plan list, the console)
removedelete the target element
flasha transient note; also rolls back an optimistic pending state
typestream one text token into the target, or (done) settle it
spotlightshow the AI as actor — dim everything, light (and optionally pulse) the target
logappend one provenance-tagged entry to the interaction timeline (the unified human+AI log)
navigatechange the browser's location (href) — same-origin, root-relative only
choicesthe AI asks the human to pick — a chat bubble with a row of choice buttons (each a chat.send)
fillprefill a registered form field's value — persists for human review (the AI never submits)
The one door

The HTTP surface every human/AI interaction enters through.

endpointmeans
POST /intentthe one door — every human/AI interaction enters here
GET /streamthe per-session SSE channel render ops are pushed back over
GET /ai/manifestthe machine-readable index of what's operable right now
Token slots

Every custom property GRAIN's default theme sets on :root — override these to re-skin (see RE-SKIN-VIA-TOKENS.md), never a component's own CSS.

tokendefault value
--paper#E2E0D8
--paper-2#E8E6DF
--panel#E8E6DF
--ink#1C1B17
--ink-muted#6E6C64
--ink-faint#ABA89F
--hairline#1C1B17
--line-softrgba(28, 27, 23, .14)
--font-smooth"Redaction", "Times New Roman", Georgia, serif
--font-grain"Redaction 50", "Redaction 35", "Times New Roman", Georgia, serif
--font-accent"Redaction 70", "Times New Roman", Georgia, serif
--font-grain-fine"Redaction 35", "Times New Roman", Georgia, serif
--font-monoui-monospace, "SF Mono", "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace
--font-weight-regular400
--font-weight-medium500
--font-weight-semibold600
--font-weight-bold700
--text-xs0.8125rem
--text-sm0.875rem
--text-base0.9375rem
--text-lg1.05rem
--text-xl1.3rem
--text-2xl1.6rem
--text-3xl2.25rem
--displayclamp(2rem, 6vw, 2.75rem)
--leading-tight1.02
--leading-normal1.5
--leading-relaxed1.55
--space-10.25rem
--space-20.5rem
--space-30.75rem
--space-41rem
--space-51.25rem
--space-61.5rem
--space-82rem
--radius-sm4px
--radius-md4px
--radius-pill2px
--rule1.5px solid var(--hairline)
--border1px solid var(--hairline)
--content-max768px
--page-padclamp(1.25rem, 5vw, 2.5rem)
--color-bgvar(--paper)
--color-surfacevar(--panel)
--color-fgvar(--ink)
--color-mutedvar(--ink-muted)
--color-linevar(--line-soft)
--color-accentvar(--ink)
--color-accent-hovervar(--ink)
--color-accent-contrastvar(--paper)
--color-accent-softvar(--paper-2)
--color-primaryvar(--color-accent)
--color-primary-hovervar(--color-accent-hover)
--color-primary-contrastvar(--color-accent-contrast)
--color-primary-softvar(--color-accent-soft)
--color-successvar(--ink)
--color-success-hovervar(--ink)
--color-success-contrastvar(--paper)
--color-success-softvar(--paper-2)
--color-dangervar(--ink)
--color-danger-hovervar(--ink)
--color-danger-contrastvar(--paper)
--color-danger-softvar(--paper-2)
--color-ok-bgtransparent
--color-ok-fgvar(--ink)
--color-archived-bgtransparent
--color-archived-fgvar(--ink-muted)
--type-fontvar(--font-smooth)
--font-basevar(--text-base)/var(--leading-relaxed) var(--type-font)
--ai-veil-alpha22%
--ai-veilcolor-mix(in srgb, var(--ink) var(--ai-veil-alpha), transparent)
--ai-veilcolor-mix(in srgb, var(--paper) 70%, transparent)
--ai-veiltransparent
--ai-focus-move0.65s
--ai-focus-easeease-in-out
--z-ai-veil9000
--z-ai-spot9001
--z-ai-surface9002
--paper-grain-opacity0.09