Command line
Command line
Mesh is not released yet. These pages describe Mesh 1.0.
mesh builds and inspects your project. It does not run your application’s actions. Run it from the project root containing mesh.config.ts, after installation:
mesh <command> [options]
Commands and exit codes
| Command | What it does |
|---|---|
mesh init |
Writes mesh.config.ts and the folders, asking where your entity files are and where generated code goes |
mesh build |
Reads the entity files and writes .mesh/ |
mesh build --check |
The guard: rebuilds in memory, writes nothing, fails on any difference with what is committed |
mesh inspect [entity] |
Prints the model as JSON, with the source position of every declaration |
mesh explain <entity> <action> |
Prints the plan that action’s handler follows |
mesh db push |
Pushes the schema straight to the database. Development only |
mesh migrate generate [--allow <change>] |
Writes a SQL migration into migrations/ |
mesh migrate apply |
Applies the migrations that have not been applied |
mesh export generators |
Copies the built-in templates into the project; see Customising generated code |
mesh --help |
Lists the available commands, including those added by enabled adapters and extensions |
Square brackets mark an optional argument; angle brackets mark one you must supply. --check changes a build into a read-only comparison. --allow <change> permits a named destructive or ambiguous migration change; it never applies the migration.
The db and migrate commands come from the data adapter, which is why meshfw never imports a query library. Enabled extensions can add commands too; mesh --help lists the commands for your project.
Exit codes: 0 success, 1 errors were found, 2 usage error.
init
mesh init
Writes the project configuration and folders, asking the same questions as the starter. See Configuration for the file it writes; the Quick start creates a complete runnable app instead.
build
mesh build
Reads your entity files, checks them and writes the types, action functions, input validators and schema to the configured output folder. Rebuild after changing an entity file, then commit the source and generated changes together.
What a build error looks like
Every diagnostic names the file, the line and the column, both 1-based, and says what to do:
src/domain/todo/todo.mesh.mx:22:9 error &titel is not a member of :Todo. Did you mean &title?
The same shape is used for an unknown declaration, one the build does not implement, a duplicate input name, a free variable in an expression and a capability the adapter does not declare. Nothing is silently dropped.
The guard
mesh build --check
It runs the whole build, regenerates in memory, writes nothing, and fails if the result differs from what is committed. It catches two mistakes: a hand edit to a file in .mesh/, and an entity file you changed without rebuilding.
It is exact because the build is deterministic. The same entity files produce the same bytes, so a difference means something really changed.
Put it in the same script as your tests:
"scripts": { "test": "mesh build --check && bun test" }
inspect
mesh inspect Todo
Prints the model as JSON: every attribute with its type and constraints, every action with what it accepts, every relationship, computed field and policy, each with the source position of the declaration it came from. Omit Todo to inspect the whole domain. It is the first thing to look at when a build error mentions a rule you did not expect, and it is what to paste into a bug report.
explain
mesh explain Todo complete
Prints the plan the generated handler follows. The plan is chosen at build time; the handler then performs it without deciding anything at run time.
Todo.complete (update)
strategy read-then-write: check notDoneYet reads &done
steps &done = true
policy &list.ownerId === actor.id folded into the statement as a filter
checks notDoneYet
Two lines are worth learning:
strategyis one statement (atomic) orread-then-write, andexplainsays why: acheckorwhenthat readsself, arunstep, or an expression Mesh cannot translate.Todo.completereads then writes becausecheck :notDoneYetreads&done;Todo.renameis one statement because it has no check.folded into the statementmeans the rule costs no extra query. A rule that cannot fold runs in memory on the row read inside the transaction instead.
explain prints a plan, not SQL. Queries are assembled at run time from the entity’s filter, the caller’s filter and the policies, because which of those apply is only known when the call arrives.
Migrations
During development, pushing the schema is quicker:
mesh db push
It creates the tables and columns and records no history. It is a development tool: never run it against a database whose contents you care about.
For anything you keep, generate a migration:
mesh migrate generate
mesh migrate apply
mesh migrate generate compares the committed schema with the model, and refuses a destructive or ambiguous change unless you name it: dropping a column, changing its type, renaming it, making an optional column required.
mesh migrate generate --allow drop:Todo.title
The name after the colon is the entity and the column, without the colon the entity file writes them with.
The migration is a plain SQL file in migrations/, and you commit it. Generating never applies anything; applying is a separate, explicit command. So a new machine, and your production environment, reach the same shape with mesh migrate apply.
Next
- Configuration — what the commands read and which adapter adds database commands.
- Project structure — what each command reads and writes.
- Working with AI agents —
inspectandexplainare the tools an agent uses.