Docs/Core Concepts/Project Instructions

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.

bash
dynamo init           # scaffold DYNAMO.md here
dynamo init --rules   # also drop a commented .dynamo/rules/example.md

It 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:

  1. 1.Personal — your config dir (applies across all your projects)
  2. 2.Git root — the repository root
  3. 3.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.md

So 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:

markdown
# CLAUDE.md   (or AGENTS.md)

@./DYNAMO.md

You 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:

markdown
# Project Rules

@./conventions.md
@/docs/architecture.md

Path resolution:

FormResolves relative to
@./file.md, @../file.mdthe importing file
@/path/file.md, @bare/path.mdthe 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:

markdown
---
paths:
  - "src/**/*.ts"
  - "!src/**/*.test.ts"
---

Use the project's logging helper, never bare `console.log`.
  • Glob matching — supports matchBase (a bare *.ts matches 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, or git_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.mdMemory (.dynamo/memory/)
Who curates itYou — or the model on request, via dynamo_md_saveThe model itself, via memory_save
What it holdsThe team brief: conventions, architecture, workflowsWhat the model learns about you and the project
Lives whereCommitted to the repo, shared with the teamGitignored, 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 sessionDYNAMO.md
Personal notes on top of the shared DYNAMO.mdDYNAMO.local.md (gitignore it)
Defaults across every project you openDYNAMO.md in your config dir
Guidance only when editing certain filesa .dynamo/rules/ file with paths:
A repeatable workflow the model runs on requesta Skill
A fact the model should remember for youMemory

Configuration

All of this is on by default. Tune it under ai.instructions in dynamo.yaml:

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/rules

Set enabled: false to turn off DYNAMO.md loading entirely, or path_scoped_rules.enabled: false to keep DYNAMO.md while disabling .dynamo/rules.