Skip to main content

The DartWay agent toolkit

The methodology of the framework, written for an agent instead of for a reader. Every project created by dartway create has it; dartway setup-ai installs it into a project you already have, and dartway update carries it forward. The source is toolkit/ in the monorepo; the installer is packages/dartway_cli/lib/src/toolkit_installer.dart.

dartway setup-ai --base-branch develop

Why the framework ships this at all​

DartWay is highly opinionated: less freedom in how to do things, more consistency and speed. The contract lives in the shared package and every call has exactly one handler with an access rule. A feature is a folder with exactly one public file. Styles live in the app's own UI kit and nowhere else. None of that is guessable from the API surface — an agent reading only pubspec.yaml writes correct Dart in the wrong shape, confidently, at speed, everywhere.

That is the failure worth naming. An agent that does not know the conventions does not produce compile errors you fix in a morning; it produces a second architecture inside the first one, faster than a person can review it. The toolkit exists so the agent writes in the conventions a person on the project would — and so the conventions checker agrees with it afterwards.

Toolkit and code evolve in the same repository and the same pull request: a change to a package's public API updates the affected skills with it. A skill that has fallen behind the API is worse than a missing one — the agent writes non-working code with full confidence.

What gets installed​

AGENTS.md # Codex: owner text + managed connection block
CLAUDE.md # Claude: owner text + managed connection block
.agents/
DARTWAY.md # shared managed policy
dartway-toolkit.json # revision and install choices
skills/dartway-*/SKILL.md # Codex skills
.claude/
CLAUDE.md # pointer to shared policy
skills/dartway-*/SKILL.md # generated Claude copies
commands/ # shared skill wrappers
settings.json # Claude permissions, merged

create, setup-ai and update accept --agent codex|claude|both. The default is both; later installs preserve the recorded choice unless explicitly overridden. Switching removes only managed DartWay skills and connection blocks for the deselected agent. Custom skills and owner instructions are preserved. Codex permissions are not inferred from Claude settings.

toolkit/AGENTS.md is the shared policy source, installed with project tokens as .agents/DARTWAY.md. Marked dartway-toolkit:start / dartway-toolkit:end blocks in root instructions tell both agents to read it. Malformed blocks refuse installation before files are changed. Skills have one source in toolkit/skills/.

The manifest moves from .agents/dartway-toolkit.json to .agents/dartway-toolkit.json; the first upgrade reads existing settings from the old location. Commit managed files and root connection blocks. Project findings remain in docs/dev_notes/. Framework laws are the checker error set; project conventions override defaults.

The skills​

A task runs left to right: dartway-requirements → dartway-plan → implementation with the layer skills → dartway-finish.

SkillFor
dartway-requirementsRead-only analysis before a task: what the project already has, the debt in the way, the questions worth asking, options with their trade-offs
dartway-planRead-only planning once the requirements are agreed: an end-to-end plan; Risks to guard selects from the risk survey and spec, with a class (1–6) and expected outcome per item, or No must-test risk: <why>
dartway-runBringing the project up locally — the order of the steps and the real ports — and confirming it is alive
dartway-feature-scaffoldA feature end to end: its folder, its entry point and DwFeatureSpec, its layers
dartway-contractThe shared package: data objects, requests and commands, refusal codes, validation, generation
dartway-serverHandlers and the call context, rows and queries, auth hooks, jobs, routes
dartway-data-layerThe Flutter side of calls: requests, commands, actions, refusal texts
dartway-realtimeChannels, publishing, update actions
dartway-accessAccess rules, channel rules, roles, identities and keys
dartway-migrationsWriting, checking and applying migrations
dartway-uploadsFiles: upload purposes and their rules, the public and the private bucket, rows that store a file id
dartway-testingSix must-test risk classes, rare tests outside them through the gate, agent rules and the boundary that owns each test
dartway-navigationThe router: zones, route descriptors, guards
dartway-ui-kitThe kit as source inside the app, and the ban on raw styles outside it
dartway-on-deviceWhat only a real phone shows: keyboard, focus, scroll and viewport behaviour on iOS and iOS web, with the known workarounds
dartway-finishBefore a commit or PR: fast gates and changed/mirrored tests locally when CI carries full suites, full local fallback otherwise; audit the diff and apply only what is confirmed
dartway-updatePlan an exact target, resolve the plugin, apply and verify notes, then record dispositions
dartway-push-deliveryServer-side push delivery
dartway-analyticsEvents tracked in the app and on the server, stored in the project's Postgres
dartway-mediaVideo and audio through the media plugin; the controls are the project's own kit widgets
dartway-documentationWhere descriptions live — DwFeatureSpec, doc comments, registries in code — and what docs/adr/ and docs/dev_notes/ must earn
dartway-framework-notesFiling a finding back to the framework as an issue: what must not travel, the labels, the marker a workaround leaves in the code

Two commands come with them. /commit writes one conventional-commit line in English and decides nothing local — whether commits carry a ticket belongs to the project's root instructions. /dartway-checkup reports the state of the whole project and what is worth taking into work next: it runs the project's gates first (dart run dartway_cli:dartway check, dart run dartway_cli:dartway generate --check, the analyzers, the tests), compares them with what CI actually runs, measures how far the project trails the framework, and only then spends reading on features — loading only the skills its findings point at, never the whole toolkit.

The names in the skills are the project's​

The toolkit's markdown carries tokens, and the installer replaces them in every installed .md file, so the skills talk about my_app_server, not about a placeholder:

TokenBecomes
__SHARED_PKG__The *_shared package
__SERVER_PKG__The *_server package
__FLUTTER_PKG__The *_flutter package
__FLUTTER_APP_FILE__The app's wiring file, <project>_app.dart
__BASE_BRANCH__--base-branch (default master)
__PROJECT_LANGUAGE__--language (default English)
__NOTES_TRACKER__--notes-tracker (default dartway/dartway), or none

The packages are detected by directory suffix at the project root on every run; exactly one *_shared, one *_server and one *_flutter are required. A token nothing fills stops the install before a file is touched: the installer reads the toolkit first, and a token this CLI does not know, or one it would fill with nothing, is named with its file — a toolkit from another framework revision than the CLI, rather than a skill that tells the agent about /lib/src/. The three flag settings are recorded in .agents/dartway-toolkit.json and replayed by the next install unless a flag names another value — see The CLI.

Managed files, project files, and the one in between​

Managed files are the toolkit's, and every install removes them and copies them again: .agents/DARTWAY.md, .claude/CLAUDE.md, every skill directory named dartway-*, and the commit.md and dartway-checkup.md commands (a retired command on the installer's list is removed the same way). Anything else in .agents/skills/ or .claude/ — a project's own skills and commands — is never touched.

So do not edit a dartway-* skill in place: the next install drops the change. To customize, copy the skill under another name and edit the copy. The source of truth is toolkit/ in the monorepo, and there is no reverse sync. Rules a project adds of its own belong in its root AGENTS.md, CLAUDE.md or its own skills.

.claude/settings.json is a toolkit default the project extends, so it is merged rather than overwritten or skipped. It pre-approves this stack's build, test and run commands — dart pub get, the analyzers, the test runners, dartway, docker compose up — so a first run is not a queue of permission prompts, and it denies reading deploy/secrets.yaml, turning a rule the skills state into one the harness enforces. Nothing destructive is on the allow list. On an install, entries the toolkit has and the project lacks are added, a value the project holds is never replaced, and every added entry is printed — the one cost of merging is an entry a project removed on purpose coming back, and printing makes that visible in the same run. A file that is not a JSON object is left as it is and reported.

docs/dev_notes/ holds the project's own findings, one committed file per finding. It is tracked, not git-ignored — a finding travels out in the pull request that carries it and survives a git worktree remove. README.md there is the toolkit's and is refreshed on every install; _coverage.md is the project's record of what /dartway-checkup has read, created once and never touched again.

.agents/dartway-toolkit.json records where the install came from — the repository or local path, the channel, the commit, the CLI version — and the settings. It records provenance, not content: a list of installed files or their hashes would be a second copy of the files, and copies drift.

Commit .agents/, selected .claude/ files, root instruction blocks and docs/dev_notes/ after every install: a clone comes with the skills in place, and the history records which version of the methodology a piece of code was written under.

Findings about the framework go back to the framework​

A rule that did not catch a mistake, two skills that disagree, an API the app had to work around — none of that can be fixed in the installed copy, and all of it is worth keeping: the rules are only ever proven wrong by real code. So a finding about the framework is filed as an issue in the repository --notes-tracker names, which defaults to the framework's own tracker, dartway/dartway. A finding about the project itself goes to docs/dev_notes/, or to the knownIssues of the feature it belongs to.

The default is deliberate. A project that never decided where its findings should go is a project whose findings stay on one laptop, and making the decision a precondition would reproduce exactly that in every project that skipped it. --notes-tracker owner/repo sends them to another repository; --notes-tracker none files nothing outside the project — the finding is written into docs/dev_notes/ like any other.

Keeping it current​

  • dartway setup-ai — the first install, or a re-install on the same channel.
  • dartway update --plan — a read-only exact-target plan and plugin resolution preflight. update --target <sha> installs that committed toolkit and resolvable plugin configuration. Migration notes stay unconfirmed until explicitly verified as applied or not applicable in .dartway/migrations.json; toolkit installation and dependency locks do not complete them. The dartway-update skill carries the plan through project edits and verification.
  • --local-repo <checkout> (or DARTWAY_MONOREPO_DIR) — install from a local monorepo checkout instead of a channel, for working on the framework and a project side by side. It records no channel. A CLI activated from a checkout uses that checkout when no channel is chosen.

A plain re-run that would move a project to another channel is refused and asks for the channel by name. The details of both commands are in The CLI.

What the toolkit does not do​

It never changes code silently. dartway-requirements and dartway-plan write nothing at all; dartway-finish shows what it would change and applies only the confirmed part. The point is a reviewer that is awake at 2 a.m., not an autopilot.