Quick Rundown
Intro to clay
Everything you need to go from an empty terminal to a workflow you drive from your phone. Install it, edit some JSON, point it at a model, decide what it is allowed to touch, and summon it from anywhere.
Page I
The first incantation
One line installs Clay with its own Python 3.11 and an offline wheelhouse. It does not touch your system Python, and it does not need one.
$ curl -fsSL https://claycli.org/install.sh | sh $ export PATH="$HOME/.local/bin:$PATH" $ clay --version
Clay lands in ~/.local/share/clay with its launcher at ~/.local/bin/clay. Add the Qt desktop app by passing -s -- --ui to the same installer.
See what came with it
Clay ships a library of workflows. List them, then run one by its segments.
$ clay workflows # everything installed $ clay workflows coding # filter by name $ clay workflows --paths # show the files behind them $ clay run templates content quick-explainer $ clay run -f ./my-workflow.json
clay --project-dir /path/to/project run …Page II
The shape of a workflow
A workflow is made up of JSON files. workflow.steps lists the steps in order. actionSets holds the actions inside each step. That is the whole language.
{
"workflow": {
"steps": ["ask", "draft", "save"]
},
"actionSets": {
"ask": [
{
"id": "topic",
"type": "humanDecision",
"prompt": "What should I write about?"
}
],
"draft": [
{
"id": "article",
"type": "scramda2",
"prompt": "Write three paragraphs about {topic}.",
"includedData": ["topic"]
}
],
"save": [
{
"id": "saved",
"type": "writeFile",
"file": "draft.md",
"content": "article"
}
]
}
} idnames the output."id": "topic"stores that action's result under the nametopic, for anything later to use.includedDataasks for it back. List the names this action needs and they arrive as data.{name}drops a value into text.{topic}becomes whatever the person typed, before the prompt ever reaches the model.whenandwhenNotgate an action. Point one at an earlier output and the action runs only if that answer means yes — or no.false,done,0,no,stopand empty mean no; anything else means yes. So a model answeringYESbranches your workflow directly.
Agents are loops you wrote
The loop action runs a sub-workflow over and over. continueKey names the output that tells it to stop. A loop, a gate, and outputs you named yourself — that is the entire harness. The model fills in text and answers questions. Your JSON decides what happens next.
{
"id": "session",
"type": "loop",
"file": "iteration.json",
"iterations": 12,
"continueKey": "keep_going"
} Check it before you run it
$ clay lint ./draft.json # unknown fields, bad references $ clay dryrun ./draft.json # walk it without executing $ clay create my-workflow # build one interactively
Page III
Binding a model
Every AI step posts to an OpenAI-compatible server. By default that is a server on your own machine, which means your prompts and your files never leave it.
# the default, if you set nothing at all $ export GOPHER_URL=http://127.0.0.1:8080
Point it anywhere you can reach — another machine on your network, or a hosted endpoint if you decide you want one. That decision is yours, and it is one environment variable.
Name your models once
Model profiles live in ~/.clay/config.json. Give each one a name, and any action can ask for it by name instead of hard-coding a model into twenty different workflow files.
{
"id": "plan",
"type": "scramda2",
"modelProfile": "code",
"prompt": "Write an implementation plan for {goal}",
"includedData": ["goal"]
} Page IV
Gates and wards
Workflow files are programs. They can write files, read files, and run commands. Clay gates all three separately, and every gate names exactly what it is about to do before it does it.
- writes — asked before anything reaches disk.
- reads — asked before anything is opened.
- commands — asked before anything is executed.
Switch them from any prompt, mid-run. One grammar, and it works the same in the terminal, in the desktop app, and in a Telegram chat.
/manual # show current settings /manual on # master switch, everything asks /manual writes off # one gate at a time /manual reads on /manual commands on
Directories are approved, not assumed
File actions only reach directories you have approved. Approve them ahead of time, or answer the prompt when a run asks — once, always, or not at all.
$ clay dirs list $ clay dirs add /path/to/project $ clay dirs forget /path/to/project
Page V
The far summoning
Clay can run a Telegram bot as your remote control. You get a menu of your workflows in a chat. Tap one and it starts. When it needs an answer, the question arrives as a message — you reply, and your reply goes back in as the answer.
The bot is a front-end, exactly like the desktop app. It never runs a workflow itself; it asks the clayd daemon to run it. The work happens on your machine whether or not your phone stays awake, and one workflow runs at a time per bot.
$ export TELEGRAM_BOT_TOKEN='123456:token-from-BotFather' $ export TELEGRAM_ALLOWED_USERS='123456789' $ clay run system messaging telegram
Choose what appears in the menu
The buttons come from the action itself, so the bot only ever offers the workflows you listed.
{
"id": "bot",
"type": "telegram",
"workflows": [
{"label": "Coding", "path": "workflows/system/coding4/main.json"},
{"label": "Research", "path": "workflows/templates/research/main.json"}
]
} Your gates come with you. Send /manual from the chat to switch them, and approve writes, reads, and commands from your phone before they happen — the same grammar as page IV.
Or leave it running headless
The daemon keeps workflows alive across terminals, reboots, and disconnects. Attach whenever you want to look.
$ clay daemon start $ clay daemon run templates research main $ clay daemon list $ clay daemon tail wf-0001 $ clay daemon attach wf-0001
That is the whole engine
Simple JSON structure, a model you chose, gates you set, and a chat window if you want one. The rest is just workflows — and you can read every one of them before it runs.