Configuration reference
The default file is pipeline.config.json beside the package root. CLI --config and MCP tool argument config select another path. The file is plain JSON; there is no layer merge and no environment-variable substitution.
Start from pipeline.config.example.json. The tables below cover every key read by the pipeline.
Secret policy
A credential value must be a reference of the form role://<role>/<field>. The role identifies the credential's purpose, not a vault item's name. The loader resolves references in memory through stado credentials get --role ROLE --field FIELD; STADO_BIN selects the executable. Without Stado, set GLINA_CREDENTIALS_FILE to an owner-only JSON file of role → field → value. A group- or world-readable file is refused.
Every field directly under credentials, plus models.brama.key, models.brama.bearer, and models.openai_compatible.bearer, must be a reference when present. An inline value is refused before resolution:
config key 'models.openai_compatible.bearer' holds an inline value; secrets must be role://<role>/<field> references
glina config check --config pipeline.config.json resolves references, checks that exactly one supported model backend is usable, and prints the original configuration with all referenced values replaced by <resolved: ok>. A missing role or field, an unsupported backend, and an inline credential exit unsuccessfully with the failing path. It does not make a model request or prove the provider is reachable. It refuses a resolved handoff file because that file contains inline secrets; check the original file instead.
Browser and studio
| Key | Type | Default | Used by |
|---|---|---|---|
browser.weles.command |
string | weles-mcp |
Program that starts the Weles MCP server. |
browser.weles.args |
string array | none | Its arguments. |
browser.weles.engine |
string | none | Browser name passed to weles_browser_start. |
browser.weles.headless |
boolean | none | Headless flag passed to weles_browser_start. |
browser.playwright_mcp.command |
string | required | Program that starts the Playwright MCP server, for a user without Weles. |
browser.playwright_mcp.args |
string array | required | Its arguments. |
credentials.username |
Role reference | required for create |
Filled into the login-user selector. |
credentials.password |
Role reference | required for create |
Filled into the login-password selector. |
studio.loginUrl |
URL string | required for create |
First navigation. |
studio.generateUrl |
URL string | required for create |
Generation page. |
studio.selectors.loginUser |
CSS selector | required | Username field. |
studio.selectors.loginPassword |
CSS selector | required | Password field. |
studio.selectors.loginSubmit |
CSS selector | required | Login submit control. |
studio.selectors.promptInput |
CSS selector | required | Prompt field. |
studio.selectors.generateSubmit |
CSS selector | required | Generation submit control. |
studio.artifact.expression |
JavaScript expression | required | Evaluated in the page after submission until it returns an http… string. The wait ends when the link appears or the page closes. |
artifact.downloadHeaders |
object of string values | {} |
Headers added to the final artifact download. This is top-level artifact, not studio.artifact. |
Declare exactly one browser layer: browser.weles drives Weles through its MCP stdio server; browser.playwright_mcp drives the Playwright MCP server, passing the studio selectors as Playwright targets and reading the artifact link from the Result section of its browser_evaluate reply. No browser section, an empty one, any other key under browser, or both layers is refused by name, for example both browser.weles and browser.playwright_mcp are declared: keep the one this pipeline uses.
The example config uses placeholder addresses under studio.example.com; the workflow itself has no provider-specific URL or selector.
Model routing
Declare exactly one backend. models.brama uses the organization router and signs requests; models.openai_compatible uses an OpenAI-compatible provider without Brama and sends an unsigned bearer request. models.backend, models.openrouter, and other backend keys are refused. See model backend.
| Key | Type | Default / requirement |
|---|---|---|
models.brama.url |
URL string | Optional override of Stado's published ~/.stado/forwards/brama.local address. Missing both is refused; /v1/chat/completions is appended. |
models.brama.key |
Role reference | Required HMAC agent-auth secret. |
models.brama.bearer |
Role reference | Required bearer token. |
models.brama.agent_id |
Role reference/string | Required identity sent as x-agent-id and used in the signature. |
models.brama.model |
string | Required model alias; no default. |
models.openai_compatible.url |
URL string | Required provider base URL; /v1/chat/completions is appended. |
models.openai_compatible.bearer |
Role reference | Required bearer token. |
models.openai_compatible.model |
string | Required model identifier. |
llm.maxRounds |
integer | Required for sculpt jobs unless --rounds is given; no built-in cap. |
llm.maxTokens |
integer | Required for sculpt jobs; refused as sculpt needs a reply length: set llm.maxTokens in the pipeline config. |
For a provider without Brama, replace the entire models.brama object with, for example:
{"models":{"openai_compatible":{"url":"https://provider.example","bearer":"role://provider/token","model":"example-model"}}}
The URL is the server base, not a /v1 endpoint. A completion failure reports the provider URL, HTTP status or transport error. config check validates local configuration and vault access, not that remote request.
Verification
| Key | Type | Default | Meaning |
|---|---|---|---|
verify.enabled |
boolean | enabled unless exactly false |
Controls the gate inside create and sculpt; standalone verify always runs. |
verify.triTarget |
number | none — no budget is checked | Nominal triangle target; the sculpt prompt names it when set. |
verify.triTolerancePct |
number | required once triTarget is set |
Extra percentage accepted; maximum is target × (100 + tolerance)/100. |
verify.requireMaterials |
boolean | true |
Require at least one material. |
verify.requireAnimations |
boolean | false |
Require clips and at least one changing float channel. |
verify.minAnimationClips |
integer | none — no minimum | Minimum clip count; the sculpt prompt names it when set. |
verify.render |
boolean | false |
Import through Blender and render one smoke frame at the scene's own render size. |
verify.throwOnFail |
boolean | false for direct API use |
Internal job mode: turn an ok:false report into VerifyError. Jobs force it to true; operators normally should not set it. |
Blender
| Key | Type | Default | Meaning |
|---|---|---|---|
blender.enabled |
boolean | false in example |
Enables post-processing for studio (create) jobs. Sculpting always needs Blender regardless of this flag. |
blender.processCode |
string | none | Python body after studio GLB import; receives INPUT_PATH and OUTPUT_PATH globals. Export still happens afterward. |
blender.mcp.command |
string | none | Explicit MCP command. When set, args below are used. |
blender.mcp.args |
string array | [] |
Arguments for explicit command. |
blender.mcp.uvx |
boolean | true |
With no explicit command, false selects bare mcp-for-blender; otherwise uvx is used. |
blender.mcp.uvxBin |
string | uvx |
uvx executable name/path. |
With defaults, the spawn is uvx mcp-for-blender. glina setup provisions Blender, uvx, and the matching Blender add-on; glina setup --check reports installed prerequisites without changing them. glina doctor probes an actual MCP tool round-trip through the add-on. A running MCP server alone does not prove Blender is connected.
Resolved handoff files
The operational command glina config export --config input.json --out resolved.json resolves references locally, adds "_resolved": true, and writes mode 0600. The marker tells the worker loader the inline values came from the vault. The file contains real secrets: use it only as a short-lived worker handoff and delete it after use. config check refuses that file; it cannot safely print its values.
Local asset workspace
Imported user data is not configuration. It lives under $XDG_DATA_HOME/glina when XDG_DATA_HOME is set, otherwise ~/.local/share/glina. workspace.json indexes exact accepted GLB copies under assets/ and identifies one active asset. Manifest replacement and new-file installation are atomic; no credential value is stored in the manifest.