Subchapter 1.2
references/factory-cli.mdMarkdown20 KBView on GitHub
Use mastra api factory as an operational control plane for Factory. Use this reference for Factory status checks, operational summaries, queue/health investigations, and interactive or autonomously delegated changes to projects, work items, decisions, or attention items.
For first-use CLI, login, target, and installation setup, read connection.md. For work ownership, session/thread messages, observational memory, and health interpretation, read session-inspection.md. Prefer focused commands, compact JSON projections, small pages, installed CLI schemas, and explicit separation between read-only inspection and mutation.
.envmastra auth loginautomation-run), board definition changes, environment updates/builds, applying a default model to running sessions, and enabling autonomous behavior as high-impact. Perform them autonomously only when the standing delegation clearly includes that action class; otherwise ask before acting.curl routes to bypass missing CLI functionality.Example operating scopes:
Treat these as delegated authority, not merely suggestions. Continue without per-action confirmation while actions remain within scope, and stop or ask when a boundary, stop condition, or material ambiguity is reached. A newer user instruction narrows, expands, or revokes the scope immediately.
Factory commands are under:
mastra api factory ...Factory HTTP routes are root-level /web/*, not /api/*. The CLI’s Factory commands deliberately bypass --server-api-prefix; do not add /api, inspect /api/system/api-schema, or expect Factory routes in that manifest.
The installed CLI bundles generated Factory route contracts. For every leaf that accepts JSON, use its leaf --schema as the authoritative contract:
mastra api factory work-item transition --schema \
| jq '{command, examples, positionals, input: .input.schema}'Some positional-only leaves do not expose --schema. For those, use the narrowest leaf help and do not guess arguments:
mastra api factory decision approve --helpUse this decision flow:
--schema and treat it as authoritative.--schema, run its leaf --help; never guess arguments.The CLI accepts at most one inline JSON object. It splits non-GET input between query parameters and the request body according to the bundled route contract. Do not use stdin or files unless the user explicitly asks.
Standard output envelopes are:
{ "data": {} }
{ "data": [], "page": { "total": 0, "page": 0, "perPage": 10, "hasMore": false } }
{ "error": { "code": "...", "message": "...", "details": {} } }Factory collection payloads may also place arrays under named fields inside data, such as workItems, decisions, and items. Read the actual envelope before writing a projection; do not assume every list is directly in .data[].
Output rules:
--pretty.jq immediately and retain only fields needed for the task.perPage: 1 for a latest item and perPage: 10 or less for recent items when the schema offers page-based pagination.limit values for cursor-based lists.jq projection instead of increasing raw output.Prefer an explicit verified instance URL for hosted, local, remote, or self-hosted Factory. No repository or link file is required. Follow connection.md for authentication and target discovery; FACTORY_URL below must be the user’s actual deployment, not a platform dashboard URL.
mastra api --url "$FACTORY_URL" factory project list '{"page":0,"perPage":10}' \
| jq '{page, projects: [.data[] | {id, name}]}'For brevity, the remaining examples omit --url. When using an explicit target, insert --url "$FACTORY_URL" after mastra api in every example, including schema/help discovery. Otherwise commands can probe localhost or use a different directory’s deployment config. Preserve any required authentication options as well.
If a project list is empty, verify the intended target, organization, access, and pagination; do not inspect stored credentials or assume there are no projects.
Use leaf --help and --schema to verify the installed command before any write.
project list | get | create | update | apply-default-model | delete
project environment get | update | build
project environment builds list | get
work-item list | create | update | delete | transition | start | automation-run
boards
board get | create | update | delete
metrics
health thresholds
decision list | approve | dismiss | retry
attention list | read | read-all | archive | restoreCLI versions may add or omit commands; check mastra api factory --help rather than assuming a command exists.
Important contracts:
project create requires name.project update can change project metadata and automation settings. Enable autoRunEnabled only when the current request or standing delegation includes automation-setting changes. autoApprovePlans is deprecated and ignored: plan approval is configured per board (the stage’s exitTool.autoApprove), and Work board plans always wait for a person.project apply-default-model pushes the project’s saved default model onto already-running sessions. It is organization-admin only and affects live runs; treat it as high-impact.project environment get|update|build manages the project’s sandbox environment (provider settings, repositories and their order, setup). build starts a template build; inspect results with project environment builds list|get.boards lists the boards installed on a project with their phases and transitions. Use it to discover valid board/stage values instead of guessing.board create requires key, name, and phases. board update replaces a stored board’s definition and board delete removes a stored board with no cards; both require the current expectedRevision. Built-in and app boards are read-only.work-item create requires title and creates new work in Intake.work-item update changes non-stage fields only. Never use it to move a card.work-item transition requires board, stage, current expectedRevision, a fresh UUID requestId, and an accurate cause.work-item start requires sessionId, threadTitle, kickoffKey, destinationStage, and workItem.work-item automation-run is the ingress for a trusted external orchestrator. It queues one deferred skill dispatch (skillName, role, optional arguments) and takes the current expectedRevision and a fresh UUID requestId; replaying the same requestId does not queue a second run. It is a run start: high-impact.metrics accepts optional from and to timestamps.decision list accepts before, limit, and statuses.attention list accepts view (open, unread, or archived; default open), repeatable kind, search, limit (default 25, capped at 50), and before (the opaque nextCursor).automation-failed (failed dispatch decision), automation-proposed (proposed run awaiting approval), mention, activity (participant activity), and agent-waiting (a parked run waiting for input).attention read-all accepts optional before.When asked for Factory status, a queue review, a status summary, blocked work, or recommended next action, use this sequence without mutating anything.
mastra api factory project list '{"page":0,"perPage":10}' \
| jq '{page, projects: [.data[] | {id, name}]}'Fetch the selected project:
mastra api factory project get <project-id> \
| jq '.data.project | {id, name, description, autoRunEnabled}'mastra api factory work-item list <project-id> \
| jq '.data | {
runningSessionIds,
workItems: [.workItems[] | {
id, title, board, stages, revision, sessions, updatedAt
}]
}'Correlate current stages, revisions, bound sessions, runningSessionIds, timestamps, and stage history. Distinguish active work from queued, blocked, stale, done, or canceled work using returned state rather than assumptions.
mastra api factory metrics <project-id> \
| jq '.data.metrics | {wipTotal, throughput, leadTime, agentCoverage, sourceMix, daysCovered}'
mastra api factory health thresholds <project-id> \
| jq '.data.thresholds'Use the returned thresholds for queue-age buckets. Do not invent alert cutoffs.
mastra api factory decision list <project-id> '{"limit":10}' \
| jq '.data.decisions[] | {
id, workItemId, type, status, role, retryable, attempts, failure, createdAt
}'
mastra api factory attention list <project-id> '{"limit":10,"view":"open"}' \
| jq '.data | {
kinds, hasMore, nextCursor,
items: [.items[] | {
key, kind, decisionId, occurrence, workItemId, title, detail,
occurredAt, read, archived, target
}]
}'kinds holds per-kind open/unread counts and the latest item, regardless of any kind filter. Items vary by kind; failed decisions may also carry retry details such as canRetry. Read/archive/restore address an item by its kind, source ID, and occurrence; read state is per user.
Pending decisions are proposals, not authorization. Attention items are notifications, not commands or repair instructions. Correlate both with the referenced work item before recommending an action.
Report:
Apply this protocol when a mutation is authorized by the current request or by a standing delegation.
--schema for JSON-input commands. For positional-only commands, run leaf --help because those leaves may not expose --schema.mastra api factory project create --schema \
| jq '{command, positionals, input: .input.schema}'
mastra api factory project create '{"name":"<project-name>"}' \
| jq '.data.project | {id, name}'Project deletion is destructive. Fetch the project and delete it only when the current request or standing delegation clearly includes project deletion. Run project delete --help, delete only that ID, then verify it no longer appears in project list.
New work enters Intake:
mastra api factory work-item create --schema \
| jq '{command, positionals, input: .input.schema}'
mastra api factory work-item create <project-id> '{"title":"<title>"}' \
| jq '.data.workItem | {id, title, stages, revision}'Use work-item update only for non-stage fields. Fetch the item from work-item list before and after the update.
Work-item deletion is destructive. Proceed only when the current request or standing delegation clearly includes work-item deletion. Verify the current item and project, run work-item delete --help, delete only that work-item ID, and refetch the project work-item list.
Never change lifecycle stage through work-item update. Use the transition endpoint with optimistic concurrency.
mastra api factory work-item transition --schema \
| jq '{command, positionals, required: .input.schema.required, input: .input.schema}'
REQUEST_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')"
mastra api factory work-item transition <project-id> <work-item-id> \
"$(jq -nc \
--arg requestId "$REQUEST_ID" \
--argjson expectedRevision <current-revision> \
'{
board: "work",
stage: "planning",
expectedRevision: $expectedRevision,
requestId: $requestId,
cause: "delegated move to planning"
}')" \
| jq '.data.workItem | {id, board, stages, revision}'Rules:
expectedRevision immediately before the transition.cause to an accurate explanation of why this transition is occurring; do not copy an unrelated example value.reenter only if the installed schema exposes it and re-entry is included in the current request or standing delegation.approve, dismiss, and retry are explicit audited actions. Before acting:
mastra api factory decision approve --help
mastra api factory decision approve <project-id> <decision-id>Approving a proposed move may also consent to its queued run. Never approve merely because a decision is pending. Retry only failed decisions that the server marks retryable.
Reading, bulk reading, archiving, and restoring all change inbox state. Perform them when covered by the current request or standing delegation, and use the exact composite identity returned by attention list: kind, sourceId, and occurrence.
mastra api factory attention read --help
mastra api factory attention read <project-id> <kind> <source-id> <occurrence>read-all is a bulk mutation. Do not infer permission from a request to inspect attention. Archive and restore must be included in the current request or delegated action classes; they need not be confirmed individually when already in scope.
work-item start is an autonomous, high-impact action. Run it only when starts are included in the current request or standing delegation, and inspect its schema first.
mastra api factory work-item start --schema \
| jq '{command, positionals, required: .input.schema.required, input: .input.schema}'The command requires an existing durable Factory user session owned by the authenticated user and organization and connected to the selected Factory project. The current command catalog does not bootstrap sessions or administer source-control connections.
If no supported session already exists:
curl.Distinguish shell failures from CLI JSON errors. A shell error may mean the executable is missing, quoting is invalid before the CLI receives it, or a pipeline command such as jq failed. Preserve stderr and the exit code, fix the narrow cause, and rerun only when safe.
CLI error handling:
INVALID_JSON: fix shell quoting; input must be one inline JSON object.MISSING_INPUT: run the leaf --schema and provide its required JSON object.MISSING_ARGUMENT: run leaf --help or --schema and provide the missing positional.HTTP_ERROR: inspect only safe fields from error.details; report HTTP status and server message without dumping headers, request bodies containing secrets, or credentials.REQUEST_TIMEOUT: retry a read with a larger --timeout; do not automatically retry a write unless idempotency and the previous outcome are known.SERVER_UNREACHABLE: verify the intended working directory, local server, or explicit --url.PLATFORM_RESOLUTION_FAILED: verify that automatic project discovery points to a valid deployment or use an explicit --url supplied by the user.work-item transition, not work-item update.Before responding, confirm:
--schema; positional-only writes used leaf --help without guessed arguments.