Project Instructions
DYNAMO.md lets you give Dynamo standing instructions for a project — coding conventions, architecture notes, do's and don'ts — that load into every session automatically, no need to repeat yourself.
Scaffold a starter — `dynamo init`
Starting fresh? Run dynamo init to drop a starter DYNAMO.md in the current directory, pre-filled from what Dynamo can detect about your stack — the project name, your package.json scripts, the engine (Unity, Unreal, or Godot), and your git remote.
dynamo init # scaffold DYNAMO.md here
dynamo init --rules # also drop a commented .dynamo/rules/example.mdIt never clobbers your work: if a DYNAMO.md, CLAUDE.md, or AGENTS.md already exists, init prints a diff of what a fresh starter would add rather than overwriting it — merge anything useful, or pass --force. Like git init, it scaffolds in the directory you run it from.
DYNAMO.md
Drop a DYNAMO.md file in your project and its contents are injected into the system prompt at the start of each session.
Dynamo looks for instruction files at three layers, and merges them — the closer layer wins on conflicts:
- Personal — your config dir (applies across all your projects)
- Git root — the repository root
- Working dir — the directory you launched Dynamo in
At each layer, Dynamo resolves the main file through a fallback chain — the first one that exists is used:
DYNAMO.md → CLAUDE.md → AGENTS.mdSo an existing CLAUDE.md or AGENTS.md is picked up automatically. Alongside the main file, a DYNAMO.local.md overlay (gitignore it) is layered on top for personal, uncommitted tweaks.
One source of truth
The fallback chain already reads an existing CLAUDE.md or AGENTS.md, but you don't have to keep two copies in sync. Make DYNAMO.md the canonical file and point the others at it with a one-line @import:
# CLAUDE.md (or AGENTS.md)
@./DYNAMO.mdYou write the brief once. Dynamo loads DYNAMO.md (first in the chain), and any CLAUDE.md- or AGENTS.md-aware tool loads its own file — which imports the same content. One source, every tool.
Coming from an always-on skill? If you've been forcing a project-wide brief into every session through an always-on skill, that's what DYNAMO.md is for now — move the free-form rules into DYNAMO.md, and keep skills for named, on-demand workflows.
@import
Compose instructions across files with the @import directive — a line that starts with `@` inlines another markdown file at that point:
# Project Rules
@./conventions.md
@/docs/architecture.mdPath resolution:
| Form | Resolves relative to |
|---|---|
@./file.md, @../file.md | the importing file |
@/path/file.md, @bare/path.md | the project root |
Imports nest up to depth 5. Cycles are detected and marked inline ([IMPORT CYCLE]); a path that doesn't exist is marked [IMPORT NOT FOUND] rather than failing the load. HTML comments are stripped before the scan, so commented-out @ lines don't import. @import works inside .dynamo/rules files too.
Path-Scoped Rules
For instructions that should only apply to certain files, put markdown files in .dynamo/rules/. Each rule has YAML frontmatter declaring which paths it covers:
---
paths:
- "src/**/*.ts"
- "!src/**/*.test.ts"
---
Use the project's logging helper, never bare `console.log`.- Glob matching — supports
matchBase(a bare*.tsmatches at any depth) and negation (!pattern). - Delivered on demand — a rule's body is injected as a model hint only when a file-op tool touches a matching path (
read_file,write_file,edit_file,move_file,rename_file,delete_file, orgit_diff). Rules are not loaded into the system prompt up front, so they cost nothing until they're relevant. - Size caps — 4 KiB per rule and 8 KiB aggregate; anything beyond is truncated with a footer.
DYNAMO.md vs Memory
Dynamo keeps two kinds of standing context, deliberately separate:
DYNAMO.md | Memory (.dynamo/memory/) | |
|---|---|---|
| Who curates it | You — or the model on request, via dynamo_md_save | The model itself, via memory_save |
| What it holds | The team brief: conventions, architecture, workflows | What the model learns about you and the project |
| Lives where | Committed to the repo, shared with the team | Gitignored, personal to your checkout |
Memory is never auto-promoted into `DYNAMO.md`. Moving something into the shared brief is a deliberate step you take — because memory can hold machine-specific or half-formed notes (local paths, hostnames) that aren't safe to commit to a file the whole team reads.
When to use what
| You want… | Put it in |
|---|---|
| Project-wide context the model needs every session | DYNAMO.md |
Personal notes on top of the shared DYNAMO.md | DYNAMO.local.md (gitignore it) |
| Defaults across every project you open | DYNAMO.md in your config dir |
| Guidance only when editing certain files | a .dynamo/rules/ file with paths: |
| A repeatable workflow the model runs on request | a Skill |
| A fact the model should remember for you | Memory |
Configuration
All of this is on by default. Tune it under ai.instructions in dynamo.yaml:
ai:
instructions:
enabled: true
fallback_files: [DYNAMO.md, CLAUDE.md, AGENTS.md]
max_bytes_per_file: 32768
max_bytes_total: 65536
path_scoped_rules:
enabled: true
dir: .dynamo/rulesSet enabled: false to turn off DYNAMO.md loading entirely, or path_scoped_rules.enabled: false to keep DYNAMO.md while disabling .dynamo/rules.