Scripting and CI

Run DCode from a script or a CI job: one prompt in, an answer or JSON out.

On this page

dcode -p runs one prompt without the workspace and exits. It reads the folder it runs in, does the task and prints the answer, so a script or a CI job can use it.

Run one prompt

shell
dcode -p "Explain the failing tests in this repository"
  • --model "Raven Max" picks the model; without it, your saved choice, else Raven Flash. --fallback-model "Raven Flash" is used when the chosen one is busy.
  • --attach <path> adds a file, an image or a PDF; repeat it for more.
  • --max-turns <n> stops the run after that many turns.
  • --cwd <path> runs in another folder, and --add-dir <folders...> lets the agent work in more folders.
  • --worktree [name] runs in a new git worktree on the branch dcode/<name>, so the run's changes stay apart from your working tree.

A run never stops to ask about updates. Every flag is on CLI reference.

Permissions in a run

Nobody can answer a question during a -p run, so a step that would ask is refused. That is why -p runs in yolo (Full access) unless you pass another mode. Choose what the run may do:

shell
# read and plan onlydcode -p "Plan the migration to the new API" --mode plan# ask-before-changes, with the tools the job needs allowed up frontdcode -p "Run the tests and fix what fails" --mode build --allowed-tools "Bash(npm test:*) Edit"# no shell for this rundcode -p "Summarise the open TODOs" --disallowed-tools "Bash"

--allowed-tools takes tool names such as Edit, rules such as Bash(npm test:*), and MCP tools such as mcp__github__*, separated by spaces. A rule that is not a tool rule stops the run before it starts. What each mode allows is on Permission modes.

Output formats

--output-formatWhat is printed
textThe answer, and nothing else. The default.
jsonOne JSON object when the run ends. --json does the same.
stream-jsonOne JSON object per line for each event as it happens, then a closing line whose type is "result", with the fields of json.

Any other value stops the run with a message, so a typo never turns into plain text a parser cannot read. The JSON object has these fields:

FieldWhat it holds
sessionIdThe session, to pick it up again with --resume.
traceId, turnIdIds of the run and its turn, for support.
responseThe answer.
structuredOutputWith --json-schema: the answer as a JSON value.
turnResponsesWhen the run took more than one turn: each turn's answer.
usageThe run's tokens, when they are known.
eventCountHow many events the run had.
projectionstatus, turnCount, totalTokenCount, contextUsed and contextWindow of the session.

Answers that match a JSON Schema

shell
dcode -p "List the packages in this repository" --json-schema schema.json

--json-schema takes JSON text or a file. The answer must be JSON that matches the schema: if the first answer does not, DCode asks once more in the same session; if that one does not match either, the run prints Error: the answer did not match --json-schema with the reason and exits with 1. With text output the JSON value is printed on one line; with json it is in structuredOutput.

Several messages on standard input

shell
printf '%s\n' '{"type":"user","message":{"role":"user","content":"Find the slowest test"}}' \  '{"type":"user","message":{"role":"user","content":"Now make it faster"}}' \  | dcode --input-format stream-json --output-format stream-json

Each line with "type":"user" runs one turn, all in the same session, and each ends with its own result line. content is a string, or a list whose text parts are joined. Lines of other types are skipped. A line that is not JSON is skipped with a message on standard error, and the run then exits with 1.

Sign in on a CI machine

Set DCODE_API_KEY to an API key from your dashboard (Create a key). It signs in for that run without a browser:

shell
export DCODE_API_KEY="<your key, from your CI secrets>"dcode -p "Review the changes on this branch and list the risks" --mode plan --output-format json > review.json
  • The key is held in memory for the run only. It is not saved, printed or logged, and it is taken out of the environment before anything runs, so the agent's own commands never see it.
  • If the key is refused, the run prints DCODE_API_KEY was refused. Check the key in your Dipole ML Inc. account dashboard. and exits with 1.
  • Requests made with an API key are paid from your API credits (API credits).

Without DCODE_API_KEY, a run uses the sign-in saved on the machine by dcode login. With neither, it prints Not signed in. Run `dcode login` to sign in with your Dipole ML Inc. account, then try again. and exits with 2.

Sessions in scripts

shell
# give the session an id you choose, and a namedcode -p "Read the codebase and summarise it" --session-id 6f1c3c1e-3a0b-4c2e-9d7a-2b9f7c1d0e11 --name nightly-summary# carry on in the same sessiondcode -p "Now list the riskiest modules" --resume sess_6f1c3c1e-3a0b-4c2e-9d7a-2b9f7c1d0e11# carry on in a copy, leaving the original as it wasdcode -p "Try another approach" --continue --fork-session

--session-id takes a UUID, with or without sess_ in front, and refuses one that already exists. --continue picks up the latest session in the folder.

Work towards a goal

shell
dcode --target "All tests pass on Node.js 22"

--target sets the session's goal and works on it without the workspace. --target-replace replaces a goal the session already has. It cannot be used with -p. Unlike -p, it does not switch to yolo; pass --mode to choose the mode.

A browser in a run

--browser-use headless lets a run use a browser without a window, and --browser-executable <path> names the Chrome or Chromium to use.

Exit codes

CodeMeaning
0Done.
1Something failed: a wrong flag or value, an empty prompt, a refused API key, an answer that did not match --json-schema, a stdin line that was not JSON, or an error during the run.
2No sign-in.
3Node.js is too old (22.13 or newer is needed).

An error is one plain line on standard error, with the run's traceId. --verbose, or DCODE_LOG_CONSOLE=1, prints the full error output.