Commands
sofie gen: rewrites the generated files (wiring, contracts’gen/,.env.example,AGENTS.md); run it after changing routes, modules, aggregates or screens.sofie check: every one of the rules;app/build.rsruns it, so a finding failscargo build.sofie fix: applies the fixes that have exactly one form, then reports the rest.sofie explain NAME: a route, area, module, event, job, task, read model, aggregate, screen, screen component or flag.sofie routes: the route table.sofie components: every component a screen template may use, with its props, and the template syntax.sofie tasks: each#[task]with the--name valuearguments it reads; the binary runs one with<app> task MODULE.NAME [--name value]....sofie dev: runs the app, rebuilding and reloading on changes.sofie feature add|remove NAME: turns asofiefeature on or off inapp/Cargo.toml, editing only that dependency’s features.sofie new module NAME,sofie scaffold tests,sofie scaffold screen KEY: new code in its place, wired.sofie new migration MODULE NAME,sofie new aggregate MODULE Name,sofie new event MODULE Name,sofie new listener MODULE Event handler,sofie new task MODULE handler,sofie new search MODULE Aggregate,sofie new plan MODULE name,sofie new mail MODULE name [--list LIST],sofie new area MODULE NAME ACCESS,sofie new account-screen AREA SCREEN,sofie new impersonation PERMITTED_AREA MEMBER_AREA,sofie new tenancy ORGANIZATION_AREA MEMBER_AREA,sofie new route MODULE AREA METHOD PATH handler [--screen NAME] [--fields FIELDS] [--read-model Name] [--title TITLE] [--back HANDLER],sofie new menu MODULE AREA handler LABEL: stubs in their place, thensofie genandsofie check.sofie build [--image]: the release binary, and with--imageits container image.sofie bench: load tests of the routes, held to a baseline.sofie fuzz [--seed N] [--requests N]: sends every route generated valid and broken inputs, signed in and out, and reports each 500, dropped answer or crash with its input, span tree and log lines; a local database only.sofie seed [--volume N]: fills the local database through the app’s own POST routes, first with each module’sseeds/<area>.<handler>.json(a JSON array of inputs), then N generated inputs per route, as the membersofie benchsigns in with.sofie mcp: these tools over the Model Context Protocol, each generator withdry_run, and the app’s own tools below.cargo test --offline: the tests.
Adding code
Section titled “Adding code”- A module:
sofie new module NAME, then set its tier insrc/module.rs. - A route:
sofie new route, or one line insrc/areas/<area>/routes.rsnaming a handler inactions/orqueries/, such asroutes.post("/orders", actions::place_order); thensofie gen. - A screen:
sofie new route MODULE AREA get PATH handler --screen NAME(a path naming an aggregate, such as/orders/{order}, gets a read model of its fields and a screen showing them;--fields a,bpicks them), orsrc/areas/<area>/screens/<name>.htmlrouted withroutes.screen("/path", "<name>", queries::loader); thensofie gen. - An aggregate:
sofie new aggregate, orsrc/<aggregate>/mod.rswith#[derive(Aggregate)], re-exported fromlib.rs, and a migration creating its table; thensofie genandsofie check. - An event and its listener:
sofie new event, thensofie new listenerin each module reacting to it. - Tests:
sofie scaffold testswrites them for what the modules declare. Scaffolded tests live inapp/tests/scaffolded/, one file per run; extend them there; hand-written tests go inapp/tests/<topic>.rs. Write each as#[test_app] async fn name(app: TestApp), as the scaffolded ones are;#[tokio::test]only where#[test_app]cannot run it, with a line saying why.
Generated from sofie at 4aa7c05.
