Subcommands
Every pre-REPL `minara <subcommand>` invocation
Pre-REPL subcommands are dispatched from
apps/agent/src/gateway/cli.ts and each
delegates to a focused module under apps/agent/src/gateway/*-cli.ts. Every
subcommand in this page runs once, prints its result, and exits.
minara / minara chat
Start the interactive REPL. Bare minara and minara chat are
equivalent entry points. The process drops into readline after
running the first-run wizard (if needed), connecting to configured
MCP servers, and printing the cheat sheet.
minara
minara chatSee Slash Commands for what's available inside the REPL.
minara setup / minara init
Run the interactive first-run wizard. Configures the LLM provider
(Anthropic / OpenAI / OpenRouter / Minara gateway), logs into
Minara, probes your existing ~/.minara/ data dir for importable
state, scaffolds the workspace, runs doctor, and prints a cheat
sheet.
minara setup
minara init # aliasImplementation:
apps/agent/src/gateway/setup-wizard.ts.
minara auth status
Print every configured auth profile plus a summary of which
*_API_KEY env vars are set.
minara auth statusCurrently status is the only auth action. More actions will be
added under the same namespace rather than at the top level.
minara login <provider>
Authenticate with a provider and persist the credential to the
encrypted profile store under $dataDir/.
minara login minara
minara login anthropic
minara login anthropic --api-key sk-ant-...
minara login anthropic-api-key --api-key sk-ant-...
minara login openai
minara login openai --api-key sk-...
minara login openrouter --api-key sk-...
minara login xai
minara login xai --api-key xai-...
minara login ollama --api-key <key>
minara login ollama --api-key <key> --base-url http://localhost:11434
minara login minara --base-url https://api.minara.exampleProviders: minara, openai, openai-api-key, anthropic,
anthropic-api-key, openrouter, xai, ollama.
minara login minara (no --api-key) uses Minara's device sign-in
flow. It prints a short code and a verification URL — open the URL in
any browser (your own machine or a phone), approve the request, and the
CLI detects the new session automatically. No loopback port to forward,
works headless / over SSH. The session is a refresh-rotating OAuth
session (same as the web UI sign-in); on servers that predate the
device grant the CLI falls back to a Google-passthrough sign-in that
saves a single long-lived token. Pass --api-key <KEY> instead to save
a long-lived API key.
openai-api-key is a shorthand for openai --api-key …. The xAI OAuth
flow opens auth.x.ai in your browser and listens on
127.0.0.1:56121/callback; in SSH sessions, forward the port first:
ssh -L 56121:127.0.0.1:56121 <host>.
minara login ollama saves an Ollama Cloud key (from
ollama.com/settings/keys). Pass --base-url to point at a self-hosted or
local Ollama (for example http://localhost:11434) instead of the cloud
default https://ollama.com.
minara login openai uses OpenAI's device-code flow (the same one
the official codex CLI ships). It prints a short user code and a
URL — open the URL in any browser (your own machine, a phone, a
laptop), enter the code, and the CLI detects the new session
automatically. No loopback port to forward, works headless / over SSH
out of the box. As a fast path, if ~/.codex/auth.json exists and has
fresh tokens (you've already run the codex CLI), Minara imports them
and skips the device-code round trip.
The prior PKCE-loopback flow was retired in 2026-05 — OpenAI's public
Codex client_id rejects arbitrary loopback redirect_uris with
AuthApiFailure: unknown_error, so the redirect-based flow never
worked for third-party integrations.
OpenAI OAuth and OpenAI API-key profiles live in separate auth-store
slots and coexist; auto-select prefers OAuth when both are configured.
OPENAI_API_KEY env alone does NOT auto-select OpenAI for the LLM
(commonly used only by TTS / embeddings tools); run
minara login openai --api-key $OPENAI_API_KEY to opt the LLM path in.
Anthropic mirrors the same shape: anthropic does the Claude.ai
PKCE OAuth flow, anthropic-api-key writes a direct API key from
console.anthropic.com into the dedicated anthropicApiKey profile
slot. Both can coexist — auto-select prefers OAuth, and you can switch
between them at any time via Settings → Provider in the web UI. The
API-key slot survives gateway restart without depending on
$dataDir/env being sourced (the env-file path was the pre-1b936e08
behavior and has been retired).
Flags:
--api-key <key>: pass the key non-interactively. Otherwise the wizard prompts for it.--base-url <url>: override the provider's default base URL (only meaningful foropenrouterandminara).
Implementation:
apps/agent/src/gateway/auth-cli.ts.
minara logout <provider>
Clear a stored profile. The provider list matches login.
minara logout minara
minara logout openai
minara logout openai-api-key
minara logout anthropic
minara logout anthropic-api-key
minara logout xaiminara skills <action>
Manage vendored external SKILL.md packages under
apps/agent/src/skills/external/. See The Skill System
for how external skills are surfaced to the agent.
minara skills list
minara skills search <query> [--owner <owner>] [--limit <n>]
minara skills install <owner/repo>[@<skill>] [--id <prefix>] [--force]
minara skills add <git-url> [--ref <ref>] [--id <id>] [--subpath <dir>] [--note <text>] [--force]
minara skills upgrade <id> [--ref <ref>]
minara skills remove <id>Actions:
list: print every installed external skill with its upstream URL, ref, commit, license, and updated-at timestamp.search <query>: search the skills.sh ecosystem, ranked by install count. Printsowner/repo@skillids to pass toinstall. Optional--ownerrestricts to one GitHub owner.install <owner/repo>[@<skill>]: install a skill from the skills.sh ecosystem. Downloads via the bundledskillsCLI, then writes a tracked Minara package under the runtime skills dir. A bareowner/repoinstalls every skill in the repo;@skillinstalls one. Warns when an installed skill has no LICENSE.add <git-url>: clone the repository, detect the license, and register the skill. Refuses to proceed if the upstream has no LICENSE and--forceis not passed.upgrade <id>: re-fetch an existing skill. Optional--refpins to a tag or commit.remove <id>: delete the vendored directory and its.minara-skill.jsonmanifest.
Implementation:
apps/agent/src/gateway/skills-cli.ts.
minara scenarios <action>
Manage learned scenarios from the self-learning scenario system
(Phase 2). Requires SCENARIO_LEARNING=1 in .env.
minara scenarios pending # show graduation queue
minara scenarios list [--state=<state>] [--sort-by-usage]
minara scenarios show <id> # full detail (JSON)
minara scenarios approve <id> # graduate → active in classifier
minara scenarios reject <id> --reason=<reason> # reject with reason
minara scenarios deprecate <id> # remove graduated scenario
minara scenarios purge # clean up old entriesActions:
pending(default) — list scenarios that passed the Wilson confidence gate and are awaiting operator approval.list— all learned scenarios.--state=graduatedfilters;--sort-by-usageorders bytimes_useddescending.show <id>— dumps the fullLearnedScenarioas JSON (metaPlan, analyze, keywords, confidence, source turns).approve <id>— transitionsquarantined → graduatedand hot-reloads the scenario into the classifier immediately.reject <id> --reason=...— transitions torejected. Default reason:operator_rejected.deprecate <id>— transitions a graduated scenario torejectedand removes it from the in-memory classifier.purge— deletesrejected/ staleproposedentries older than 90 days + old miss candidates older than 30 days.
Source:
apps/agent/src/gateway/scenarios-cli.ts.
minara agents <action>
Manage Custom Agents — saved bundles of system prompt + skill subset + tool subset + risk ceiling + triggers. See Custom Agents for the full guide.
minara agents list [--archived]
minara agents get <id>
minara agents create --from <file.json>
minara agents update <id> --from <patch.json>
minara agents archive <id>
minara agents run <id> [--input "<text>"] [--test]
minara agents export <id>
minara agents import [--from <file.json>]Actions:
list(default) — print every registered agent with its version, risk ceiling, discovery mode, and attached triggers.--archivedincludes soft-deleted rows.get <id>— dump the fullAgentDefinitionas JSON, including snapshot bookkeeping.create --from <file.json>— insert from a JSON file conforming toAgentDefinitionSchema. Interactive create lives in the REPL (/agents create).update <id> --from <patch.json>— apply a partialAgentUpdatePatch. Bumpsversionon any meaningful change. Rejected if the agent'ssourceisfile:...— file-sourced rows are PATCH-locked; edit the file on disk instead.archive <id>— soft-delete. Tears down attached cron and event triggers. In-flight workflow instances that reference the agent continue against their stored snapshot.run <id> [--input "..."] [--test]— start an ad-hoc run. Streamsworkflow:*events to stdout until the run terminates, then prints the final__adhoc__output payload.--testtags the instancetest_run=1, which forces the fund-confirm gate even whenMINARA_SKIP_FUND_CONFIRM=1is set.export <id>— print the agent's JSON to stdout. Pipe to a file for sharing.import [--from <file.json>]— insert from JSON via file or stdin. Inverse ofexport.
Source:
src/gateway/agents-cli.ts.
minara script-risk <action>
Inspect the script risk gate audit log. Every gateScriptRisk()
decision (reject / confirm / allow) writes one row to the
script_risk_decisions SQLite table; this command surfaces it.
minara script-risk list [--verdict=<reject|confirm|allow>]
[--session=<id>] [--workflow=<id>]
[--tool=<name>] [--since=<iso>]
[--limit=<N>] [--json]
minara script-risk show <id>Filters:
--verdict— only show rows whose verdict matches.--session/--workflow/--tool— narrow to a specific session / workflow definition / tool name.--since— ISO-8601 timestamp; only show decisions newer than this.--limit— cap result count (1..1000, default 50 forlist, 100 for the HTTP endpoint).--json— emit raw JSON instead of the human-readable table.
show <id> dumps a single decision row with the full findings
array and the truncated evidence preview (the script body itself is
NEVER stored — only its sha256).
Source:
apps/agent/src/gateway/script-risk-cli.ts.
minara btc-cycle refresh
Maintainer-only refresh of the BTC halving cycle data committed under
apps/agent/src/skills/builtin/btc-cycle/data.ts.
Pulls new daily OHLC tuples from Binance (BTCUSDT 1d klines) primary,
falls back to Bitstamp on failure, and rewrites data.ts in-place.
minara btc-cycle refresh # binance primary, bitstamp fallback
minara btc-cycle refresh --dry-run # preview, don't write
minara btc-cycle refresh --from 2025-10-01 # override start date
minara btc-cycle refresh --promote-ath # if a new ATH is detected, fold into CYCLES[last]
minara btc-cycle refresh --promote-bottom 2026-10-24 36800
# append a new cycle entry whose
# botDate / botPx is the just-confirmed bottomBehavior:
- Default window: from
BTC_DAILY_OHLC[last].ts + 1dto today. - Detects a new ATH (any candle whose
highexceeds the currentCYCLES[last].topPx) and prints a warning unless--promote-athis passed. - Detects the post-top low across embedded + fetched candles and
prints it as informational. Bottom promotion is human-judgement
(R7 confirmation requires 3+ months sideways) —
--promote-bottomis the operator flag. - Writes
DATA_REFRESHED_ATto the current ISO timestamp.
Available also as npm run btc-cycle:refresh -- <flags> for direct
invocation outside the gateway.
Source:
apps/agent/src/cli/btc-cycle-refresh.ts.
minara institution <action>
Operator-facing batch surface for Institution Mode self-learning
(persistence, Phase B reflections, finalize). Mirrors the REPL
/institution-* commands but runs non-interactively — the cron
entry point + audit / batch finalize live here.
minara institution history [--ticker BTC] [--limit 20] [--json]
minara institution finalize <run_id> [--reason "closed at +12%"]
minara institution reflect-pending [--max N] [--json]
minara institution reflect <run_id> --window 1d|7d|30d|90d|180d|365d|lazy [--json]
minara institution helpActions:
history(default) — list recent runs frominstitution_runswith PM rating + holding status + per-window alpha summary.--jsonemits the same data plus all reflection rows for downstream tooling.finalize <run_id>— flip a run'sholding_statustofinalizedso the daily reflect cron stops accumulating reflections on it. Idempotent on already-finalized runs.--reasonis stored for audit.reflect-pending— the daily cron entry point. Walks everyopen/auto_stalerun, evaluates the next-due standard window (1d / 7d / 30d / 90d / 180d / 365d), pulls Yahoo prices, computesraw_return+alpha_returnvs the asset-class benchmark, asks the quick LLM for a 2–4 sentence reflection, and persists. Auto-stale promotion (open → auto_stale) happens here when a run exceedsINSTITUTION_AUTO_STALE_DAYS(default 90). Pair withcron/ systemd-timer for daily 03:00 UTC.reflect <run_id> --window ...— manually trigger a single reflection for one run.--window lazyis equivalent to the Phase 0 retrospective refresh path (current-time snapshot, no(run_id, window)UNIQUE collision); the standard windows (1d...365d) anchor the exit price tostarted_at + window.
Exit codes: 0 success, 1 runtime error, 2 usage error.
Source:
apps/agent/src/gateway/institution-cli.ts.
minara profile <action>
Manage personalization (financial profile + tags + custom prompt)
from the shell. Mirror of the REPL /profile slash command but
positional, with no pickers — best for scripts and CI. Tag names accept
either canonical form ("Risk Profile") or slug form (risk-profile).
minara profile show # snapshot
minara profile set risk-profile Conservative # set a tag
minara profile clear risk-profile # clear a tag (sets value=null, source=user)
minara profile prompt show # print custom prompt
minara profile prompt set "Reply concisely." # set custom prompt
minara profile prompt clear # clear custom prompt
minara profile help # full usage + tag tableAll writes are recorded with source: "user", which beats both
learned_preference (preference-system bridge writes) and inferred
(autoscan rebuild) under the three-tier precedence rule.
Source:
apps/agent/src/gateway/profile-cli.ts.
minara preferences <action>
Manage learned preferences mined by the preference-evolution system
(Financial Auto-Memory). M1 shipped read-only commands; M2 adds
approve / reject / deprecate for operator overrides. The
prefs alias is also accepted. Approving a preference here works
even when PREFERENCE_LEARNING=0 — manual overrides are always
available.
minara preferences pending # awaiting approval
minara preferences list # all preferences
minara preferences list --state active # filter by state
minara preferences list --kind hard_constraint # filter by kind
minara preferences list --dimension asset_class # filter by dimension
minara preferences show <id> # full detail (JSON)
minara preferences approve <id> [--reason "..."] # proposed → active
minara preferences reject <id> [--reason "..."] # proposed → rejected (terminal)
minara preferences deprecate <id> [--reason "..."] # active → deprecated
minara preferences undo <id> # M3: strong-signal auto-activations, within the undo windowTransitions are CAS-guarded — concurrent writers (REPL + CLI + REST across the same DB) can't double-apply or silently overwrite each other. A failed CAS surfaces as a non-zero exit + clear error message ("invalid transition from X (or another writer beat us to it)").
undo is the M3 exit path for rows that the keyword scanner
auto-activated via a strong signal (never, 绝不, kill switch, …).
Eligibility: auto_activated_at IS NOT NULL AND within
PREFERENCE_HARD_UNDO_WINDOW_HOURS (default 24h). Manual approvals
and stale auto-activations must use deprecate instead — the CLI
surfaces a targeted error message pointing at the right path.
Source:
apps/agent/src/gateway/preferences-cli.ts.
minara learning <action>
Observability + offline tuning infrastructure for the self-optimization loop (decision capture → multi-horizon backtest → reward → methodology instance BO).
minara learning stats [--json]
minara learning tune-methodology --dry-run [--json]
minara learning tune-methodology profiles show [--json]
minara learning audit run [--window-days N] [--json]
minara learning audit show [--latest | --pass <id>] [--json]
minara learning audit trend [--days N] [--json]
minara learning audit findings [--severity high|medium|low] [--latest | --pass <id>] [--json]
minara learning replay --config <path.json> # LEARNING_CONFIG BO, placeholder
minara learning helpstats [--json]
Readonly data-readiness report covering trade_history,
methodologies, decision_history, decision_outcomes, and reward
distribution. Always safe to run — ignores LEARNING_TUNING_ENABLED.
Key fields:
READY_FOR_BO=true|false— the gate for running BO cycles (≥100 evaluated trades + ≥20 unique methodology hits).decision_history— BUY/SELL/HOLD counts + capture source distribution + quoted-price coverage (hallucination defense stats).outcome_coverage— per-horizon counts (1d/3d/1w/1m).rewards— mean / std / p50 per decision type + top-5 asset classes by decision volume.
tune-methodology --dry-run [--json]
Lists the (template, asset_class) buckets that would be processed by
the next BO cycle, sorted by tunability_score. Prints each bucket's
gate pass/fail and the skipped-bucket breakdown by first-failed gate.
Does NOT invoke the Python BO harness — this is plan-only.
Full execution (beyond --dry-run) is intentionally unwired: it
requires METHODOLOGY_INSTANCE_TUNING_ENABLED=true and the Python
harness under tools/tuning/ to be
activated by an operator.
tune-methodology profiles show [--json]
Prints the effective BUILTIN_PROFILES merged with any JSON override
file (default path: $MINARA_DATA_DIR/methodology-tuning-profiles.json).
Use for debugging why a specific asset class is/isn't getting tuned.
replay --config <path>
Placeholder for the LEARNING_CONFIG BO replay harness (a separate
track from methodology instance tuning). Gated by
LEARNING_TUNING_ENABLED=true; short-circuits to
{ skipped: "tuning_disabled" } otherwise.
audit run [--window-days N] [--json]
Runs one inline pass of the methodology audit subsystem and persists
the report to methodology_audit_reports. Six dimensions: synthesis
decision stability, graduation false-positive rate, attribution
integrity, asset-class coverage, quarantine churn, and cron health.
Composite 0-100 with bands healthy / watch / degraded / alarm.
Never mutates learning state — the e2e test asserts byte-level
immutability of the four learning tables before and after every
pass. Honours DISABLE_METHODOLOGY_AUDIT=1 (returns band=disabled
placeholder, does not persist).
audit show [--latest | --pass <id>] [--json]
Prints a single audit report. --latest (default) returns the most
recent row; --pass <id> looks up a specific pass id.
audit trend [--days N] [--json]
Composite score history over the last N days (default 30). Plain text shows an ASCII sparkline followed by per-row timestamps, composite, band, and pass id prefix.
audit findings [--severity high|medium|low] [--latest | --pass <id>] [--json]
Drills into the findings list of a single report. Each finding
carries a severity, the dimension that produced it, a message, and
structured metrics. Advisory actions (e.g. requantize,
investigate_attribution) are listed alongside with the CLI command
the operator would run.
Source:
apps/agent/src/gateway/learning-cli.ts.
minara research <topic> [--mode light|heavy]
Run the deep-research pipeline directly, bypassing the REPL. Prints the generated summary and exits. Useful for scripted research runs and cron jobs.
minara research "BTC ETF flows this quarter"
minara research "macro risks for Solana" --mode heavyModes:
light(default): single-pass research with a small tool budget.heavy: multi-phase research with a methodology and verify step. Slower, more thorough, more expensive.
Implementation lives in apps/agent/src/deep-research/ and is invoked via
app.deepResearchPipeline.run(...).
minara doctor [--probe-llm] [--anonymous]
Run a full health check and print a colorized report. Checks LLM auth, Minara auth, MCP servers, tool registration, workspace files, env vars, data directory, SQLite state, and memory health (a section covering methodology graduation/quarantine counts, role_memory pending-72h backlog, embedding-state distribution, edge totals + top entities, and snapshot dirty counters). Exits non-zero if any check fails.
minara doctor
minara doctor --probe-llm # also send a tiny ping to verify LLM connectivity
minara doctor --anonymous # bucket every count to <10 / 10-99 / 100-999 / ...Flags:
--probe-llm— calls the configured model with a one-token prompt. Without it, the LLM check only validates credentials and selection.--anonymous— replaces every numeric count in the memory health section with a bucket label so the output can be safely shared in an issue or screenshot without leaking deployment scale. Buckets:<10,10-99,100-999,1000-9999,10000+.
Honours MINARA_DATA_DIR so operators running against a non-default
data directory diagnose the right database.
Implementation:
apps/agent/src/gateway/doctor-cli.ts.
minara doctor --fix [--apply] [--only <actions>]
Idempotent automated maintenance over the memory + learning stores.
Every action satisfies three contracts: idempotent (replay-safe),
reversible or non-destructive (UNIQUE constraints catch replays;
demotion only ever raises quarantine), and no LLM calls by
default. Without --apply, the command runs as a dry-run that lists
what would happen and writes nothing — including no audit rows.
minara doctor --fix # dry-run report
minara doctor --fix --apply # run the default action set
minara doctor --fix --apply --only edges,embeddings # restrict to a subset
minara doctor --fix --apply --only reflect_pending # opt into the LLM-backed actionDefault action set (runs when --only is omitted):
embeddings— backfill rows withembedding_state IN ('pending','failed')viaMemoryStore.backfillEmbeddings(). Skips cleanly whenEMBEDDING_PROVIDER=disabled.edges— replay the deterministic memory_edges extractor over every memory + role_memory row. UNIQUE constraint makes the second run insert zero new edges.methodology_demotion— quarantine methodologies whose Wilson lower bound has fallen belowLEARNING_CONFIG.demotionWilsonThreshold(default 0.40) AND have at leastLEARNING_CONFIG.minUsesBeforeDemotionuses (default 20). Always raisesquarantinefrom0to1; never lowers it, never touches confidence.
Opt-in action (NOT in the default set; LLM-backed):
reflect_pending— invoke the role-reflector for every role with pending rows past the policy's age threshold. This callsllm.createMessage()for Stage 1 classification + Stage 2 lessons. Excluded from the default set so--applynever spends tokens unintentionally.
Hard safety envelope (covered by negative tests):
- never graduates a methodology (Wilson upward stays manual)
- never activates a
learned_preferencesrow (hard_constraint especially never auto-activates) - never
DELETEs any row (orphans surface in the dry-run report only) - never rewrites
role_memory.reflection(LLM authorship attribution must stay intact) - never modifies
audit_log(append-only)
Every applied action writes an audit_log row tagged
tool_call='doctor.fix.<name>' with structured detail; dry-run
leaves the table untouched. Honours MINARA_DATA_DIR.
Implementation:
apps/agent/src/gateway/doctor-fix.ts.
minara memory export [<out-dir>] [--include-constraints] [--sign]
Snapshot the agent's learned memory to a markdown tree humans can
git diff, grep, hand-edit, and (with --sign) round-trip back via
memory import. Output layout under <out-dir>:
<out-dir>/
index.md # toc + schema_version + instance_id
methodologies/<asset_class>/<id>.md # per-methodology, with frontmatter
preferences/<dimension>/<id>.md # per-preference (active state only)
preferences/README.md # constraint-exclusion banner
trade-cases/<id>.md # one file per reflected role_memory
assets/<TICKER>.md # compiled-page snapshots
signature.txt # optional: line-per-file HMACDefault <out-dir> is <dataDir>/exports/<timestamp>/. The path is
outside the LLM sandbox (<dataDir>/sandbox/files), so a
prompt-injected memory cannot leak the export back through a
read_file tool call. Passing an explicit <out-dir> that resolves
into the sandbox is rejected with refusing to export into the LLM sandbox.
Flags:
--include-constraints— without this flag,hard_constraintpreferences are excluded from BOTH the per-preference files AND the asset compiled-page surface (they encode user-specific risk caps; one-way leakage hazard). The flag opts in.--sign— compute a per-file HMAC-SHA256 against this instance's local key (instance_meta.hmac_key) and write a manifest atsignature.txt. The manifest enablesmemory importchannel A (preserves confidence + state). The HMAC key itself never leaves the SQLite DB; only the SHA-256 fingerprint (instance_id, first 16 hex chars) appears in frontmatter.
Honours MINARA_DATA_DIR.
Implementation:
apps/agent/src/gateway/memory-export-cli.ts.
minara memory import <in-dir> [--apply] [--approve-hard-constraints] [--allow-path <abs>]
Round-trip the markdown tree produced by memory export back into
the agent's stores. Two channels distinguish trusted same-instance
restores from unsigned third-party bundles.
minara memory import <in-dir> # dry-run
minara memory import <in-dir> --apply # commit writes
minara memory import bundle1 --allow-path /tmp/imports # outside-root overrideChannel selection (per-file):
- Channel A — signed.
signature.txtis present AND the file's HMAC verifies againstinstance_meta.hmac_keyAND the bundle'sinstance_idmatches this instance. Methodology imports preserveconfidence/quarantine/times_used(viawriteMethodology's INSERT OR REPLACE — same-id replays are idempotent). Preferences keepstate='active'when present.hard_constraintpreferences NEVER auto-activate, even on channel A — the user must approve via/preferences. - Channel B — unsigned (default fall-through). Methodologies go
through
MethodologyStore.create()and land atquarantine=1, confidence=initialConfidence; dedup-match returns the existing row's stats. Preferences land instate='proposed'viaPreferenceStore.create(); dedup_key collisions skip silently.role_memoryrows arrive as fresh pending entries; reflections are NEVER re-imported.
A bundle marked signed but with one tampered file degrades that file to channel B without invalidating the rest of the bundle.
Flags:
--apply— required for any write. Without it, the command runs as a dry-run that prints the per-file disposition and leavesaudit_loguntouched.--approve-hard-constraints— opt into importinghard_constraintpreferences. Even with this flag set, imports are rejected whenMINARA_NON_INTERACTIVE=1is set or the process has no TTY (defense in depth — a hard constraint should only land via a human-driven session).--allow-path <abs>— permit imports from outside<dataDir>/exports/. Relative<in-dir>resolves under--allow-pathwhen set, otherwise under the exports root.
Per-file safety (both channels): a prompt-injection scan checks
every body before dispatch (rejects ignore previous instructions,
imperative fund verbs, rating-coercion patterns); schema_version
must match MEMORY_EXPORT_SCHEMA_VERSION; asset_class must be in
the live enum; dimension + kind must be in the typed preference
enums. Every applied action — applied or rejected — writes an
audit_log row tagged memory_import.signed or
memory_import.unsigned (only on --apply).
Honours MINARA_DATA_DIR.
Implementation:
apps/agent/src/gateway/memory-import-cli.ts.
minara model <action>
Inspect or persist the active LLM model. Writes to ~/.minara/env
when you use a model so the next boot picks it up.
minara model # list (default)
minara model list
minara model show # show the currently persisted model
minara model use claude-sonnet-4-6Actions:
list(default): print every model the registry knows about with its provider, context window, and cost.show: print the currently persistedAGENT_MODELvalue.use <model>: persistAGENT_MODEL=<model>to~/.minara/env.
Implementation:
apps/agent/src/gateway/model-cli.ts.
minara tools <action>
Enumerate the tool registry or dump a tool's full JSON Schema. Boots the full app so the output reflects exactly what the agent sees, including env-gated tools that only appear when their provider is configured.
minara tools # list (default), grouped by tool set
minara tools list
minara tools show get_priceActions:
list(default): every registered tool, grouped by tool set, with its permission tier and description.show <name>: full JSON Schema forparametersplus description.
Implementation:
apps/agent/src/gateway/tools-cli.ts.
minara config <action>
Dot-path CRUD over safety.json and financial-profile.json
under $dataDir/. Lets you edit configuration without hand-editing
JSON files.
minara config # list (default)
minara config list
minara config path # print config file paths
minara config get safety.daily_spend_cap
minara config set safety.daily_spend_cap 500Actions:
list(default): print all current values from both config files.path: print the absolute paths of the config files.get <key>: read a dot-path key.set <key> <value>: write a dot-path key. Values are parsed as JSON if possible, otherwise treated as strings.
Implementation:
apps/agent/src/gateway/config-cli.ts.
minara gateway <action>
Configure outbound messaging terminals (Telegram, Discord, Slack, Lark, WeCom, DingTalk, WeChat OA, QQ, LINE, Mattermost, Teams, Google Chat, BlueBubbles, Matrix, WhatsApp, Signal, Email, Home Assistant — 18 platforms total) used by the agent to send alerts and notifications.
minara gateway # list (default)
minara gateway list
minara gateway add # interactive picker, no positional id
minara gateway add telegram # jump straight to one provider
minara gateway test telegram
minara gateway remove telegramActions:
list(default): enumerate every configured messaging provider and its status.add(no provider id): drop into an interactive picker that lists every implemented platform (numbered 1 through 18), shows which are already configured (✓) vs not (○), and accepts a number, a provider id (case-insensitive), orq/ blank to quit. Three invalid attempts auto-cancel with exit code 0. After saving one provider, a next-action menu offerst(ping test),a(configure another), orq(quit). This is the recommended starting point for new operators.add <provider>: interactively collect required fields for a specific provider and write them into~/.minara/env. Masked input for secrets; blank lines skip a field.test <provider>: send a test message via the configured provider. Instantiates the gateway viaspec.factory({dataDir})and calls.send({text: "✅ Minara gateway test ping"}).remove <provider>: strip the provider's env lines.
Implementation:
apps/agent/src/gateway/gateway-cli.ts.
The picker logic exports two pure parsers (resolvePickerInput,
resolveNextActionInput) and a top-level helper
isProviderConfigured(spec, values) shared with runList, all
covered by 21 unit tests in
tests/unit/gateway/gateway-add-interactive.test.ts.
minara serve
Start the HTTP API gateway — the same surface that npm run serve
and node dist/gateway/server.js expose, but reachable through the
minara CLI so operators who installed via the quick installer
never have to cd into the clone directory.
minara serve # foreground, Ctrl+C to stop
minara serve --ui # gateway + Web UI (preview) in one shell
minara serve --ui-dev # gateway + Vite dev server (hot reload)
minara serve -p 9090 --auth-token $TOK # override port + bearer
minara serve --daemon # detach, write PID + log files
minara serve --status # is the daemon running?
minara serve --stop # graceful SIGTERM, up to 10sFlags:
-p, --port <N>— listen port. Also readsGATEWAY_PORT; default8080.--auth-token <T>— bearer token required on/v1/*. Also readsGATEWAY_AUTH_TOKEN. Empty disables auth (dev only).--ui— co-launch the Web UI in preview mode on port4173. Ifapps/web-ui/dist/is missing or older thanapps/web-ui/apps/agent/src/, Minara auto-builds it before spawning preview. A file lock underapps/web-ui/dist/.build.lockprevents concurrent rebuilds.--ui-dev— co-launch the Web UI in Vite dev mode on port5173(hot reload). Mutually exclusive with--ui.--ui-port <N>— override the UI port (preview defaults to4173, dev to5173).--no-build— skip the auto-build check. Assumesapps/web-ui/dist/is fresh; exits non-zero with a clear error if it is missing.--ui-pid-file <path>/--ui-log-file <path>— override the per-UI pidfile / logfile paths (daemon mode only). Defaults to$MINARA_DATA_DIR/web-ui.pidand$MINARA_DATA_DIR/logs/web-ui.log.-d, --daemon— spawn a detached child that keeps running after the terminal closes. With--uior--ui-dev, the daemon tracks both the gateway and the Web UI subprocess.--stop— read the PID file, sendSIGTERM, wait up to 10 seconds for graceful shutdown, then remove the PID file. With--ui, also drains the UI subprocess and removesweb-ui.pid(with a PID-recycling guard so a stale pidfile pointing at an unrelated process is removed without signaling it).--status— report whether the daemon is running. Exits0if alive,3if not (LSB init-script convention). Reports both gateway and UI PIDs when both are running.--pid-file <path>— override the gateway PID file path (default:$MINARA_DATA_DIR/server.pid, typically~/.minara/server.pid).--log-file <path>— override the log file path (default:$MINARA_DATA_DIR/logs/server.log).
The daemon child re-execs the same minara serve command without
--daemon and inherits the parent's environment, so .env values
loaded before the fork flow through to the background process.
Signal handling mirrors the foreground path: SIGTERM / SIGINT
drain the ApiGateway + call app.shutdownAsync() so in-flight
inbound messaging work finishes before the SQLite handle closes.
For production-grade supervision (restart-on-crash, journal
integration, boot-time start), wire minara serve into systemd or
your preferred supervisor instead of relying on --daemon.
Co-launching the Web UI
With --ui or --ui-dev, minara serve spawns the Web UI as a
child process and orchestrates both lifecycles:
- Foreground: outputs from both processes are prefixed with
[gateway]/[ui]so the terminal multiplexes cleanly. - Daemon (
--daemon): writes a second pidfile ($MINARA_DATA_DIR/web-ui.pid) for the UI subprocess. Both stdout and stderr go to separate log files (server.logandweb-ui.log). --stopdrains the UI subprocess first (so its readiness probe does not race a half-shut gateway), then SIGTERMs the gateway daemon, then cleans up both pidfiles.- PID-recycling guard: if the UI pidfile points at a PID that the
OS has reused for an unrelated process (a shell, editor, etc.),
--stopremoves the pidfile but does NOT signal the recycled process. The check usespsargv matching againstnode/npm/vite/tsxplusvite/web-uiin the argv list. - Auto-build inspection: before spawning Vite preview,
inspectWebUiDist(repoRoot)compares the mtime ofapps/web-ui/dist/index.htmlagainstapps/web-ui/apps/agent/src/,package.json,vite.config.ts, andapps/web-ui/index.html. Any source file newer than the dist triggers a rebuild.--no-buildskips this check and is the right flag for CI / production deploys where the build pipeline already produced a freshdist/.
Implementation:
apps/agent/src/gateway/serve-cli.ts.
minara serve and npm run serve share the same
startServerForeground() helper so both paths boot through one code
path. The arg parser is exported as parseServeArgs and pinned by
14 unit tests in
tests/unit/gateway/serve-cli-args.test.ts.
End-to-end smoke (cold build, foreground / daemon, PID-recycle
guard, --no-build error) lives in
scripts/smoke-serve-ui.sh.
minara update
Self-update to the latest published version of the agent. Detects the install source (global npm, vendored, Docker) and invokes the right upgrade path.
minara updateImplementation:
apps/agent/src/core/update-check.ts.
minara migrate
Two modes:
-
Schema migration / hermes import (legacy, no positional sub): Initialize or migrate the SQLite schema; optionally import from a hermes / openclaw dataset. Safe to run repeatedly; migrations are idempotent.
minara migrate # schema only minara migrate --from hermes # import from ~/.hermes minara migrate --from openclaw --openclaw ~/oc # custom path minara migrate --dry-run --verbose # report only -
M5 bundle export / import / manifest (
export/import/manifestpositional sub-command):minara migrate export [--packages defaults|all|csv] [--output PATH] [--passphrase-env ENV] minara migrate import <bundle.tar.gz> [--strategy merge|replace|audit-only] [--packages defaults|all|csv] [--confirm-hard] [--passphrase-env ENV] minara migrate manifest <bundle.tar.gz>The bundle is a
.tar.gzcontaining per-package JSON files plusmanifest.jsonand (optionally)secrets.json.enc. The 10 packages and their default-on flag:Package Default Notes profile✓ financial_profilerow + 11-dimuser_tags(preservesuser/learned/inferredsource).preferences✓ learned_preferences(active + deprecated).hard_constraintrows require--confirm-hardon import.methodologies✓ All graduated methodologies, full asset-class coverage. memories✓ memoriesrows inpersonalization/preference/strategy/trade_note/observationcategories.scenarios✓ learned_scenarios(graduated). LLM behavior may differ across instances.workspace✓ USER.md,SOUL.md,MEMORY.md,AGENTS.mdfrom~/.minara/workspace/.trade_history— Full trade_historytable. Often large; reconstructible from chains.external_skills— Skill clone-URL list. Import writes a pending-skill-imports.jsonfor manualskills addfollow-up.settings— Allowlisted env vars only (no *_KEY/*_SECRET/*_TOKEN). Import writes apending-env.shto source.secrets— ⚠️ API keys + OAuth + wallet keys. Forced AES-256-GCM + PBKDF2 encryption; import requires --strategy=replace.--packagesacceptsdefaults,all, comma-separated ids, or-idto remove (e.g.defaults,trade_history,-scenarios).
# Quick export of the default 6 packages
minara migrate export --output ./bundle.tar.gz
# Inspect a bundle without importing
minara migrate manifest ./bundle.tar.gz
# Dry-run import — no writes
minara migrate import ./bundle.tar.gz --strategy audit-only
# Real import with hard-constraint preferences allowed through
minara migrate import ./bundle.tar.gz --strategy merge --confirm-hardImplementation:
apps/agent/src/gateway/migrate-cli.ts +
apps/agent/src/gateway/migrate-bundle-cli.ts +
apps/agent/src/learning/migration/.
minara strategy-rl <action>
Operator entry point for the opt-in Strategy Skill RL pilot. Requires
MINARA_STRATEGY_SKILL_RL_ENABLED=1. Promotion evaluation defaults to
dry-run; candidates are promoted or rejected only when the operator passes
explicit apply flags.
Usage:
minara strategy-rl evaluate <candidate-version-id> [--baseline <version-id|builtin>] [--apply] [--reject-on-failure] [--min-episodes <n>] [--min-baseline-episodes <n>] [--min-mean-delta <n>] [--max-invalid-rate <n>] [--limit <n>] [--session <id>] [--user <id>] [--json]
minara strategy-rl promote <candidate-version-id> [same options as evaluate]
minara strategy-rl evaluations [--candidate <version-id>] [--limit <n>] [--json]
minara strategy-rl evaluation <evaluation-id> [--json]
minara strategy-rl external-context health [--json]
minara strategy-rl external-context collect --goal <text> --symbol <symbol> --interval <tf> [--as-of <iso>] [--source kb_search|fmp_news|web_search] [--lookback-days <n>] [--max-items <n>] [--freeze] [--json]
minara strategy-rl external-context audit-suite [--suite <id>] [--all] [--json]
minara strategy-rl benchmark seed-defaults [--json]
minara strategy-rl benchmark seed-external-context-defaults [--json]
minara strategy-rl benchmark cases [--suite <id>] [--all] [--json]
minara strategy-rl benchmark add-case --goal <text> --symbol <symbol> --interval <tf> [--suite <id>] [--name <text>] [--tag <tag>] [--external-context-json <json>|--collect-external-context] [--external-context-as-of <iso>] [--external-context-source kb_search|fmp_news|web_search] [--json]
minara strategy-rl benchmark run <candidate-version-id> [--suite <id>] [--case <id>] [--baseline <version-id|builtin>] [--max-iterations <n>] [--external-context-ablation] [--apply] [--reject-on-failure] [--json]
minara strategy-rl benchmark runs [--candidate <version-id>] [--suite <id>] [--limit <n>] [--json]
minara strategy-rl benchmark get <run-id> [--json]
minara strategy-rl benchmark report <run-id> [--json]
minara strategy-rl preference add --text <text> [--user <id>] [--session <id>] [--source explicit_user|feedback|inferred] [--weight <n>] [--inactive] [--json]
minara strategy-rl preference list [--user <id>] [--session <id>] [--all] [--limit <n>] [--json]
minara strategy-rl preference update <preference-id> [--text <text>] [--weight <n>] [--active|--inactive] [--json]External context workflow:
external-context health --jsonchecks whether the provider and source tools are registered. This is read-only and does not call the news APIs.external-context collect ... --as-of <iso> --freeze --jsonpreviews a normalized replay snapshot and fingerprint before it is saved into a benchmark case.--as-ofis the historical generation time; source providers should not return items known after it.benchmark seed-external-context-defaultscreates the curatedstrategy-rl-external-context-smokesuite.external-context audit-suite --suite strategy-rl-external-context-smoke --jsonvalidates that every active case has replayable context, stable fingerprints, and no temporal leakage before a benchmark run. The audit usesevalStartTimeas the generation cutoff when present, otherwiseendTime, and reports warnings such ascontext_asof_after_cutoff,context_window_end_after_cutoff,item_after_cutoff, anditem_missing_timestamp.benchmark run ... --external-context-ablationruns the normal candidate/baseline comparison plus a no-context candidate ablation for context cases.benchmark report <run-id> --jsonemitsexternalContext,externalContextAudit,contextAblation, per-casecontextDelta, and the standardizedcontextAblation.effect.verdict.
The context ablation path is for attribution and test reporting only. It does not enter promotion evidence and does not change the promotion gate.
Source:
apps/agent/src/gateway/strategy-rl-cli.ts.
Exit codes
All subcommands follow a shared convention:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Command ran but failed (network, auth, validation) |
| 2 | Usage error (bad arguments, unknown subcommand) |
The REPL (minara / minara chat) only exits on /quit, signal,
or unrecoverable error.