CLI
Create a project
Create a Mayura project from a starter or a template with mayura init, interactively or with flags, then validate and inspect it.
mayura init creates a new project. You choose between two kinds of starting point:
- A starter is a complete application you can run, test and ship: configuration read from the environment,
tests and CI. Four are servers, with a worker, a Dockerfile and a compose file;
cli-agentis a command-line assistant. Start here for a real project. - A template is one small file that shows one feature, with a
package.jsonandtsconfig.jsonaround it. Start here to learn a single idea.
Both run offline out of the box: no API key and no network.
npx mayura initThe interactive wizard
Run mayura init with no options in a terminal and it asks, in order:
- Start from: a starter or a template.
- Which one, with a one-line summary of each.
- Which model provider (starters only). Templates use scripted test models and need no provider.
- Where should it go? The default is
./<name>.
It then shows the plan: how many files it will create, and any existing files it would replace. Replacing files needs an explicit yes, and the answer defaults to no. After it writes the files it prints the next steps:
cd refunds
npm install
npm run devFor a template the next steps are npm install, npm run build and npm start. Press Ctrl+C at any question to
cancel; nothing is written, and the command exits with code 1.
The wizard needs a terminal on both input and output. With --json, or when input or output is piped, use the flags
below instead.
Choosing a model provider
For a starter, the wizard offers:
| Choice | What it asks for |
|---|---|
| Offline (the default) | Nothing. The starter uses rule-based stand-in models. |
| OpenAI, Anthropic | Model (Anthropic defaults to claude-sonnet-5) and API key |
| Groq, Google Gemini, Mistral, DeepSeek, xAI, OpenRouter, Together, Fireworks | Model and API key. These use the provider's OpenAI-compatible chat-completions endpoint. DeepSeek is set up with its beta endpoint, JSON mode and strict tool calls (MAYURA_MODEL_OUTPUT=json_object, MAYURA_MODEL_STRICT_TOOLS=true), and its model defaults to deepseek-flash. |
| Cloudflare AI Gateway | Account ID, gateway name, the gateway token (for an authenticated gateway, saved as MAYURA_MODEL_GATEWAY_TOKEN), then which API to use through it. Unified (OpenAI-compatible): any provider, with a provider/model name such as deepseek/deepseek-flash; a deepseek/ model gets DeepSeek's settings, and an openai/ model sends its output limit as max_completion_tokens (MAYURA_MODEL_TOKEN_LIMIT_FIELD). OpenAI Responses API or Anthropic Messages API: that provider's own API and Mayura's adapter for it, with the gateway's endpoint saved as MAYURA_MODEL_ENDPOINT and MAYURA_MODEL_PROVIDER set to openai or anthropic. In every case the provider's key is optional when the gateway stores it. |
| Azure OpenAI | Resource name, deployment name, API version, model and API key |
| Another OpenAI-compatible provider | An HTTPS URL ending in /chat/completions, a short id for the provider, model and API key |
For every real provider it also asks for your prices (dollars per million input and output tokens, from the provider's pricing page) and two spending caps: the most one model call may cost (default $0.05) and the most one agent run may cost (default $0.50). Mayura needs these because it accounts for every call's cost before making it; see Costs and budgets.
The API key is typed masked. The wizard writes these settings to a .env file in the new project, readable only by
you, and never prints the key or puts it in the plan:
MAYURA_MODEL_PROVIDER=anthropic
ANTHROPIC_API_KEY=<your key>
MAYURA_MODEL=claude-sonnet-5
MAYURA_MODEL_INPUT_MICROS_PER_MILLION_TOKENS=3000000
MAYURA_MODEL_OUTPUT_MICROS_PER_MILLION_TOKENS=15000000
MAYURA_MODEL_MAX_CALL_COST_MICROS=50000
MAYURA_MAX_RUN_COST_MICROS=500000OpenAI uses OPENAI_API_KEY. Compatible providers use MAYURA_MODEL_API_KEY plus MAYURA_MODEL_PROVIDER_ID,
MAYURA_MODEL_ENDPOINT and MAYURA_MODEL_AUTH. The starters' .gitignore excludes .env, and mayura dev loads it.
If the directory already has a .env, the wizard leaves it untouched and tells you to add the settings yourself (each
starter's .env.example lists them). You can switch providers later by editing .env.
Non-interactive: plan, then apply
With flags, init is plan-first. Without --apply it writes nothing and prints what it would do:
mayura init --starter approval-workflow --directory ./refunds
mayura init --starter approval-workflow --directory ./refunds --apply| Option | Meaning |
|---|---|
--starter <name> or --template <name> |
What to create. Give exactly one. |
--directory <dir> |
Where to create it. Required. A relative path is resolved from the current directory. |
--apply |
Write the files. |
--confirm <digest> |
Allow replacing existing files. Only with --apply. |
The plan lists every file with its operation (create, replace or unchanged) and a SHA-256 digest of its
content. For a file it would replace, the JSON plan also includes a short text diff. The whole plan has one digest.
If the plan replaces any existing file, --apply alone is refused. Review the replacements, then run the command again
with the digest the plan printed:
mayura init --template basic-agent --directory ./my-agent --apply --confirm <plan digest>The digest covers the target directory and the exact before and after content of every file, so it only works for the plan you reviewed. If any target file changes between planning and writing, nothing is written. The target directory must not be, or pass through, a symbolic link.
The project name comes from the directory's last segment, lower-cased (for example ./Refunds becomes refunds).
The generated package.json pins mayura to the CLI's exact version.
Every new project also gets an AGENTS.md, with a CLAUDE.md that points to it. It tells AI coding assistants to
read the documentation shipped inside the installed mayura package, so they follow the API of the version you
actually have.
Starters
mayura starters lists them. Each one runs offline with npm run dev and npm test, and ends its README with what
it does not do. The server starters use SQLite locally and PostgreSQL when DATABASE_URL is set.
| Starter | What it is |
|---|---|
approval-workflow |
Refund approvals. An intake agent opens a durable workflow that checks policy, waits for an operator to approve the exact payment in the operator console, issues it and notifies the customer. Includes a reviewed migration of in-flight runs from workflow v1 to v2. |
support-agent |
Customer support chat with a React UI and streamed replies. Order tools act only for the signed-in customer, memory is kept per customer, card numbers, emails and phone numbers are redacted, and opening a return starts a durable follow-up workflow. |
research-team |
Multi-agent research as one durable workflow: a planner, up to four parallel researchers over a source library and a writer whose citations are checked, under one shared budget. The report is stored as a content-addressed artifact, with optional OpenTelemetry traces. |
event-automation |
Signed webhooks start durable workflow runs in which a triage agent acts on a ticket tracker through MCP tools under explicit permissions. Forged, stale and replayed deliveries start nothing, and assigning an urgent ticket waits for operator approval. |
cli-agent |
A command-line assistant: assistant chat, or one request such as assistant list files in src, about the folder you run it in. File tools stay inside that folder and never open .env files, you confirm every write, skills load from skills/, and replies stream. npm run dev starts the chat. |
Browse the source at packages/cli/starters.
Templates
mayura templates lists them. Each creates src/index.ts, package.json, tsconfig.json, README.md and
mayura.project.json. They use scripted test models, so they run without a key.
| Template | What it shows | Extra packages |
|---|---|---|
typed-tool-runner |
An agent calling a typed tool | none |
basic-agent |
The smallest agent with a structured answer | none |
durable-approval |
A durable workflow step that waits for human approval, on SQLite | better-sqlite3 |
parallel-research |
Two child agents run in parallel and joined | none |
native-memory |
Scoped memory with provenance, correction and deletion | better-sqlite3 |
guarded-streaming-app |
An authenticated local server, guarded output and the browser client | none |
code-mode-workflow |
An approval-gated durable Code Mode workflow in the QuickJS sandbox | better-sqlite3, quickjs-emscripten-core, @jitl/quickjs-wasmfile-release-sync |
capability-policy |
A tool that needs an explicit permission, granted and denied | none |
Browse the source at packages/cli/templates.
mayura.project.json, validate and inspect
Every project has a mayura.project.json: a plain JSON catalog of its agents, workflows and tools. The CLI reads it
without importing any of your code.
{
"format": "mayura.project.v1",
"name": "approval-workflow",
"template": "approval-workflow",
"definitions": [
{ "kind": "agent", "id": "refunds.intake", "version": "1", "source": "src/intake.ts" },
{ "kind": "workflow", "id": "refunds.approval", "version": "2", "source": "src/workflow.ts" }
],
"tools": [
{ "id": "refunds.issue", "version": "1", "effects": "write", "capabilities": ["payments:refund"] }
]
}mayura validate --file ./refunds/mayura.project.json
mayura inspect --file ./refunds/mayura.project.jsonvalidate checks the file's shape and prints the project name. inspect lists its definitions and tools with their
effects and capabilities. The rules are strict: exactly these keys, a lower-case name, template set to a known
starter or template name, source paths under src/ ending in .ts, and no duplicate definition.
Good to know
- The catalog is descriptive. Nothing checks it against your code, so update it when you add an agent, workflow or tool.
initnever runsnpm installfor you.