mindvm CLI
The mindvm CLI lives beside the server it talks to, in
studio-apps-ng.
It is the primary authoring surface: a local mindvm/ folder is the source
of truth, and the CLI’s verbs move it to and from the platform.
Being in the same repository is what makes mindvm validate worth running. It
imports the server’s own schemas, resolver and JavaScript parse — the same code,
not a copy — so a folder that validates locally validates on push. There is no
second definition of what a valid agent is to drift from the first.
Install
Section titled “Install”git clone https://github.com/mind-vm/studio-apps-ngcd studio-apps-ng/apps/mindvmmake cli # builds bin/mindvmConfigure
Section titled “Configure”Three environment variables. There is no config file and no login command:
the CLI holds no state between invocations, so what it is talking to is always
visible in the environment rather than in a dotfile somebody set up months ago.
export MINDVM_URL=https://platform.mindvm.ai # the serverexport MINDVM_ORG_ID=<uuid> # the organisation to act inexport MINDVM_API_KEY=mvk_… # a machine credentialMint a key in the console under API keys. It is shown once. A key scoped
read is refused every unsafe method, which is what a CI job that only watches
runs should carry; an unscoped key writes.
MINDVM_TOKEN takes a bearer token instead, for a person driving the CLI
under their own account rather than a workstation’s key.
The loop
Section titled “The loop”mindvm init # a folder with one working agentmindvm validate # offline: schema, resolution, JS syntaxmindvm dev # push itmindvm dev --watch # push on every savemindvm run starter "2 + 2?" # push, run, stream the tracemindvm eval starter # push, run the suites, exit non-zero on a failuremindvm deploy # push, then publish a version per agentmindvm status # what the server holds against what is on diskmindvm pull # bring server-side files (promoted routines) downEvery command takes --dir (default mindvm).
Scaffolds a folder with one agent that works: a persona, a skill with both
halves — the prompt a model reads and the module a script requires — and an
eval that passes. Running init, dev and eval in that order shows the whole
loop before you have written anything.
validate
Section titled “validate”The offline gate. It runs the JSON Schemas, follows every declaration in
agent.jsonc, and compiles each JavaScript skill. Issues name the file and
carry a hint, because the reader is usually a coding tool.
Builds a manifest from the folder and pushes it. Idempotent: an unchanged
folder writes no new draft, so --watch in a loop costs one read per save.
A push is all-or-nothing. Three agents stored and a fourth rejected would leave your folder and the server disagreeing about what exists, so a fatal issue stores none of it and the response names what to fix.
Pushes, opens a session, and streams the turns as they happen — the JavaScript the model wrote, what it returned, and the answer. Not a transcript at the end.
Pushes, runs every suite for the agent, prints each case, and exits non-zero if any failed. That exit code is the interface: edit the files, run it, read the code. A tool that had to parse prose to learn whether it had improved things could not iterate.
mindvm eval starter || echo "still failing"deploy
Section titled “deploy”Pushes, then freezes each agent’s current draft as the next numbered version.
Deploying an unchanged folder returns the version that already carries its hash
rather than minting a duplicate, so deploy in a loop is safe.
status
Section titled “status”Compares the folder against the server without changing either: in sync, changed locally, not synced, or on the server only.
Brings server-side files down — a routine promoted from a successful run is an
ordinary file in the agent’s folder, and this is how it reaches your disk. A
file that differs locally is left alone and reported; --force overwrites.
The whole gate is two commands and an exit code:
- run: mindvm validate- run: mindvm eval my-agent env: MINDVM_URL: ${{ vars.MINDVM_URL }} MINDVM_ORG_ID: ${{ vars.MINDVM_ORG_ID }} MINDVM_API_KEY: ${{ secrets.MINDVM_API_KEY }}validate needs no server and no credential, so it belongs on every pull
request. eval needs both, and is the one that says whether the change was an
improvement.