mel agent (command line)
Run Mel's agent for one request from a terminal or a script, with approvals, JSON output and exit codes.
mel agent runs Mel's agent for one request from a terminal or a script. It works on the folder you run it in, on your own Mel account, with the same agent, tools and models as the Mel app.
mel agent "fix the failing test"The answer streams to your terminal. What the agent does while it works (the commands it runs, the files it changes) is printed on a separate line each, so you can pipe the answer without them.
Before you start
Sign in to the Mel app once. mel agent uses the same account and the same settings: it runs on your credits, or on your own model keys if you have added them in Settings > AI. A Free account with no key of its own gets the same message in the terminal as in the app.
What it does
- Works on the current folder as the project (or the folder you give with
--cwd). - Runs one request. If the agent reaches its tool-call limit while it is still changing things, Mel carries on by itself, at most 20 times in a row.
--max-creditsstops it starting another one once that many credits are spent. - Saves the conversation like any other: it appears in the Mel app's conversation list, titled from your request. Use
--no-saveto keep nothing. - Opens no window and needs no display.
- Stops what it started when it ends: background jobs the agent left running are stopped, and unless you pass
--quietor--jsonit tells you how many.
Give it the request
mel agent "explain what changed since main" # the words after the options
mel agent --prompt "add a --verbose flag" # or --prompt
echo "summarise the open TODOs" | mel agent # or on standard input, when nothing else is givenOptions
| Option | What it does |
|---|---|
--prompt TEXT | The request. You can also put it after the options, or pipe it in. |
--model ID or auto | A model from Settings > AI, or auto. Without it, the model your Settings start a new conversation on. A model Mel does not offer is refused, not replaced. |
--mode NAME | The Auto mode when the model is auto: balanced, cost-efficient, genius or open-weights. |
--max-credits N | Do not start another continuation once N credits are spent. It never cuts a turn that is running, so a run can spend N plus its last turn. 0 means no cap. |
--timeout-secs N | End the run N seconds after it starts. 0 means no limit. |
--cwd DIR | Work in DIR instead of the current folder. |
--yes | Approve commands and file edits without asking. It never answers anything that always asks (see below). |
--json | Print events as JSON lines on standard output instead of the answer's text. |
--quiet | Print on standard error only what needs you: approval questions, refusals and a run that did not succeed. |
--no-save | Keep nothing: the conversation is not saved or listed, the full text of long tool results is not kept, no result e-mail is sent, and Mel's automatic memory is off for the run. |
-h, --help | The options, the approval rules and the exit codes. |
Approvals
The agent asks before it runs a command or changes a file, as it does in the app. Where the question goes depends on where you run it.
At a terminal (standard input and standard error are a terminal), each question is printed as a card on standard error and you answer. Commands and file edits take y or N; an edit shows the same diff the app shows. A command that cannot be undone, a change outside your project, a connector call, a file that holds secrets and control of your screen always ask, and take only the word yes typed out. --yes never answers those. A card is shown whole: a long line wraps and is never cut. A card too long to show whole (past 200 lines or 20 000 characters) says what it left out and takes only a typed yes. Commands that only read, from a closed list, run without a card, as they do in the app.
Not at a terminal (a pipe, a script, a scheduled job), nobody can answer. Without --yes, every approval is refused by name, for example Not run: a command needs a person; run mel agent in a terminal or pass --yes for commands and edits., and the run goes on with the refusal. With --yes, commands, background commands and file edits are approved, and everything that always asks is still refused.
| The request | At a terminal | At a terminal with --yes | Not at a terminal | Not at a terminal with --yes |
|---|---|---|---|---|
| A command, a background command, a file edit | You answer y or N | Approved | Refused | Approved |
| Anything that always asks | You type yes | You type yes | Refused | Refused |
An approval nobody answers for 30 minutes is denied and the run ends.
Output
- Standard output is the answer, and nothing else (or, with
--json, the event lines). - Standard error is for you: one line per tool call, notices from Mel, the approval cards, and a closing line with what the run did and cost.
- On a terminal, control characters in a model's text are shown as visible marks, so a model cannot rewrite your screen. A pipe gets the text as it is.
Stopping it
Press Ctrl-C. The agent stops the way Stop does in the app: a running command is stopped, the conversation is saved, and the exit code is 130. Press it twice to leave at once.
JSON events
With --json, standard output is one JSON object per line, each with an event word first.
event | When | Fields |
|---|---|---|
turn_start | once, first (a run refused before it starts has only an end) | schema, mel_version, cwd, model, mode, interactive, approvals, saved, max_credits, timeout_secs |
model | the model that answers is known or changes | label |
text | a piece of the answer | delta |
tool_start | a tool call begins | index, title, summary |
tool_end | it ended | index, state (ok, failed, denied) |
diff | a file was changed | path, adds, dels |
notice | a line Mel says about the run | text |
approval_asked | a call needs an approval | id, kind, summary, always_asks, will, adds, dels |
approval_answered | it was answered | id, kind, answer, by, reason |
usage | a segment of the run ended | segment, model, token and tool counts, total_ms, credits_milli, byok, budget_capped |
end | once, last | reason, exit_code, message, conversation, title, usage |
A field that is not known is left out, never written as zero: credits_milli is present only when Mel measured the cost, and 0 with byok: true means your own key paid. summary is one line with secrets masked. File contents and command output are never in the stream. schema is 1; within a schema number the stream only grows, so ignore a field or an event you do not know.
In turn_start, mode is the Auto mode's own word. Balanced is written responsive there; the other modes are cost-efficient, genius and open-weights. --mode takes either spelling.
{"event":"turn_start","schema":1,"mel_version":"0.1.64","cwd":"~/projects/shop","model":"auto","mode":"responsive","interactive":false,"approvals":"refuse","saved":true}
{"event":"tool_start","index":1,"title":"Run command","summary":"cargo test --lib"}
{"event":"tool_end","index":1,"state":"ok"}
{"event":"text","delta":"All tests pass."}
{"event":"end","reason":"completed","exit_code":0,"message":"completed","conversation":"1727700000-fix-the-failing-test","title":"Fix the failing test"}Exit codes
| Code | reason | Meaning |
|---|---|---|
| 0 | completed | The request was carried out. |
| 2 | bad_usage | The command line was wrong, or the request was a Mel slash command, not a request. |
| 3 | signed_out | No Mel account is signed in on this computer, or the session ended. |
| 4 | plan_unconfirmed | Mel's server could not be asked about your plan, and nothing stands in for the answer. |
| 7 | save_failed | The run finished but the conversation could not be written to disk. |
| 10 | stopped | The turn was stopped without a signal. |
| 11 | error | Mel's server or a model provider ended the run. |
| 12 | context_exceeded | The conversation is larger than the model's window. |
| 13 | auth_required | The session was refused during the run. |
| 14 | credits_exhausted | Out of credits and no key of your own to run on. |
| 15 | vanished | The turn's thread ended without a result. |
| 18 | approval_expired | An approval waited 30 minutes with no answer. |
| 19 | deadline_exceeded | --timeout-secs passed. |
| 22 | rate_limited | Your account's daily or per-minute ceiling was reached. |
| 23 | credit_cap | --max-credits ended the run. |
| 24 | plan_refused | Your plan does not include the Mel app. |
| 25 | budget_capped | The run hit its tool-call limit while still changing things and was not carried on: the work may be unfinished. Open the conversation in the Mel app and send "keep going". |
| 130 | interrupted | Ctrl-C. |
| 141 | output_closed | Standard output was closed by its reader. |
| 143 | terminated | The process was terminated. |
Where mel agent and Mel's cloud tasks share a code (3, 4, 7, 10 to 15, 18, 19, 22 and 23), it means the same for both, so one script can read both.
Limits to know about
mel agenthas no--resume. To continue a run, open its conversation in the Mel app.- A request whose first word is a slash and a name (
/plan,/compact,/pin, a saved prompt's name) is refused with exit code 2: those are the app's commands. A path is fine (/etc/hosts is wrong, why?), and so is a request with a word before the slash. --no-saveturns off Mel's automatic memory for the run; it does not stop the agent from using its ownremembertool if it chooses to.- The agent cannot ask you a question in the middle of a run. If it tries, it goes on without an answer and the line says so.
- It does not start other agents: orchestration needs panes, which a terminal run does not have.
- Windows: the Mel program is a windowed program, so
cmd.exeand PowerShell do not wait for it to finish. To get its exit code in%ERRORLEVEL%, and to be asked about a command or a file change in the console, run it asstart /wait mel agent "...". Closing the console gives the run up to four seconds to stop the turn and save it.