dibbla apps maintenance & proposals
Operate the maintenance agent and review its proposals from the CLI — JSON output, product exit codes, and a server-owned decision object the client never computes.
dibbla apps maintenance inspects, enables and runs an app’s maintenance
agent. dibbla apps proposals lists, shows and decides the change queue that
agent (or a governed human deploy) writes into. Every console-visible action
has a CLI equivalent, and every command has a JSON form.
The alias is always positional. A proposal id is the second argument on
show / approve / deny / retry, matching dibbla apps restart <alias> --service <name>.
These commands ship in every dibbla build, but the capability behind them is
enabled organization by organization. A 404 with
MAINTENANCE_AGENT_NOT_FOUND (exit 4) from a maintenance command means your
organization is not switched on yet — the command is correct, the capability
is not there. Ask us to enable it. The same 404 is not “unknown alias”;
the CLI does not point you at apps list for it.
Approval eligibility stays server-owned. proposals show renders the
decision object the API returned. approve / deny / retry post to the
decision endpoint and let the server enforce role, author separation and
proposal status. The CLI never calculates or stores who may click.
Exit codes
Maintenance run exits with the product outcome, not just success or
failure:
| Exit | Outcome | Meaning |
|---|---|---|
0 | found_nothing, proposed, budget_exhausted, skipped, cancelled | The run finished in a calm or deliberately bounded way. A proposal is success for the command — someone still has to review it. |
11 | finding_recorded | The agent recorded an actionable finding. Distinct from a failed command so automation can page on it. |
1 | run_error, assessment_blocked, unknown_outcome | The agent could not produce an answer, or the code is one this CLI does not recognise. |
3 | — | Authentication or permission. |
4 | — | Not found, including MAINTENANCE_AGENT_NOT_FOUND. |
5 | — | Validation (bad alias, bad mode, --check-run missing or unexpected). |
6 | — | Conflict (concurrent settings edit, proposal not ready). |
7 | — | Timed out waiting for a terminal read model. The run keeps going server-side. |
Transport failures keep this same ladder on proposal commands. An empty
proposal list is exit 0 — “none” is an answer.
dibbla apps maintenance status
Show effective settings and the latest run.
| Flag | Purpose |
|---|---|
<alias> (positional, required) | The app to inspect. |
--json | Print the raw API document (one JSON document). Unknown server fields are preserved. |
$dibbla apps maintenance status myapp 🔧 maintenance enabled for myapp deployment: dep_… model: dibbla/claude-sonnet-5 schedule: 0 3 * * * (UTC) last run: mex_… — completed (NO_FINDING)
$dibbla apps maintenance status myapp --json | jq '.settings.enabled' dibbla apps maintenance enable / disable
Opt this app into overnight maintenance, or stop new runs. History stays readable either way.
| Flag | Purpose |
|---|---|
<alias> (positional, required) | The app to change. |
-y, --yes | Confirm non-interactively. |
--json | Print the raw API acknowledgement. |
Requires owner or admin. The write carries the server’s app_version as an
optimistic-concurrency token; a conflict is exit 6.
Without a terminal on stdin and without --yes, the command refuses: exit
5, zero requests, message naming --yes. Scripts, CI and coding agents
should always pass --yes.
$dibbla apps maintenance enable myapp --yes ✓ maintenance enabled for myapp (deployment dep_…)
dibbla apps maintenance run
Start one run and wait for its terminal read model.
| Flag | Purpose |
|---|---|
<alias> (positional, required) | The app to run against. |
--async | --follow | Return once accepted, or emit status changes to one terminal object. Mutually exclusive. |
-q, --quiet | --json | Script-friendly or machine output. Mutually exclusive. |
--mode nightly | check-triage | Default nightly. check-triage requires --check-run. |
--check-run <id> | Application check run id (required for check-triage; rejected on nightly). |
--idempotency-key <key> | Stable key for this intent. Omit for a fresh random key. Reuse to replay the same execution. |
Default (neither --async nor --follow) polls until terminal and exits with
the product outcome.
--async returns as soon as dispatch is accepted. --json prints the dispatch
document (code, execution_id, run_id, replayed). dispatched,
replayed, budget_exhausted and skipped_concurrent exit 0; anything else
exits 1.
--follow --json is documented NDJSON on stdout: one execution_created line
(with dispatch), one execution_status line per status change, and exactly
one terminal summary line carrying outcome and exit_code:
{"schema_version":1,"type":"execution_created","execution_id":"mex_…","status":"running","execution":{…},"dispatch":{…}}
{"schema_version":1,"type":"execution_status","execution_id":"mex_…","status":"completed","execution":{…}}
{"schema_version":1,"type":"summary","execution_id":"mex_…","status":"completed","outcome":"found_nothing","exit_code":0,"execution":{…}}
Sync --json prints exactly one JSON document with outcome and exit_code
next to the final execution, so a caller never parses prose. The execution
object is the observation receipt: summary, fingerprint, evidence_refs,
proposal_id, deduplicated, used_tokens.
run exits 11 when the agent found something. Gate automation on the
code: page on 11, treat 0 as a finished look (including a proposal waiting
for a person). Transport failures stay on 3/4/5/6/7/1.
$dibbla apps maintenance run myapp --follow --json | jq -c 'select(.type=="summary")' $dibbla apps maintenance run myapp --async --idempotency-key nightly-2026-09-01 # the second call with the same key follows the original execution; replayed: true
dibbla apps maintenance runs
List run read models, newest first.
| Flag | Purpose |
|---|---|
<alias> (positional, required) | The app. |
--limit <N> | Maximum runs to request, 1–100 (default 25). Out of range is exit 5. |
--json | Print the raw API document. |
dibbla apps proposals list
List an app’s deployment proposals.
| Flag | Purpose |
|---|---|
<alias> (positional, required) | The app. |
--json | Print the raw API document. |
An empty queue is exit 0 and prints no proposals for <alias>.
dibbla apps proposals show
Show the proposal read model: actor, status, audit events and the API-owned
decision object.
| Flag | Purpose |
|---|---|
<alias> <proposal-id> (positional, required) | App and proposal. The id matches pr_[a-zA-Z0-9_-]{1,128}. |
--diff | Also fetch the exact server-generated diff and evidence. |
--json | Machine-readable JSON. |
With --json alone, stdout is the proposal API document. With --diff --json,
stdout is one schema-versioned document:
{"schema_version":1,"type":"proposal_review","proposal":{…},"diff":{…}}
The two inner objects are the unmodified API documents, unknown fields included. The CLI does not re-shape the diff.
Human --diff prints risk, evidence, file counts and the patch. Treat the
patch as review evidence, not as something to apply locally.
dibbla apps proposals approve / deny / retry
Decide through the server-owned endpoint.
| Flag | Purpose |
|---|---|
<alias> <proposal-id> | App and proposal. |
-y, --yes | Confirm non-interactively. |
--json | Print the raw API proposal document after the decision. |
The CLI does not check eligibility first. The API enforces role, author
separation, proposal status and immutable revision conflicts. Typed conflicts
such as PROPOSAL_NOT_READY exit 6 and name the code on stderr.
Without --yes in a non-TTY, the command refuses with exit 5 and makes zero
requests.
$dibbla apps proposals approve myapp pr_0123456789abcdef0123 --yes ✓ proposal pr_0123456789abcdef0123: queued by user_…
Auth, budget and the safety boundary
- Auth. Missing or rejected token is exit
3. Owner/admin for enable, disable, run and decide; viewers canstatus,runs,listandshow. - Budget. A dispatch that returns
budget_exhaustedis exit0— the ceiling did its job. The same outcome on a finished run isbudget_exhausted/ exit0, neverrun_error. - Idempotency. One key, one intent, one execution. Reuse is how a timeout does not double-spend.
- Four-eyes. The author of a maintenance proposal cannot approve it. That
refusal is a
3or adecision.can_decide: falseonshow, depending on the endpoint — never a client-side skip.
The how-to that uses these commands is the Maintenance agent guide.