Several Projects in One Repository
One repository can hold the documentation of several Meldoc projects, driven by a single meldoc.config.yml. Each project keeps its own directory, its own document tree, and its own sync state, and one command run covers all of them.
Requires CLI 1.3.0 or newer. An older CLI does not understand baseDirs and reads such a config as a single project rooted at the repository — check with meldoc version before relying on it.
Declare the projects
List them under baseDirs, each with the project alias and the directory that holds its documents:
workspaceAlias: dundler-paper
baseDirs:
- projectAlias: dundleros-api
baseDir: api/docs
- projectAlias: dundleros-web
baseDir: web/docs
prune: true
One config file covers one workspace. All projects listed must belong to workspaceAlias.
Overlapping directories, duplicates, absolute paths and paths escaping the repository are rejected when the config loads — before anything reaches the network.
Running commands
Every command processes all configured projects in one run:
meldoc push # both projects
meldoc pull # both projects
meldoc validate # both projects
Add --project <alias> to limit a run to one:
meldoc push --project dundleros-api
The summary names the outcome per project:
Succeeded: dundleros-api, dundleros-web
A failure in one project does not stop the others. The run continues, finishes the rest, exits non-zero, and lists which projects succeeded and which failed.
Commands that require --project
Some commands act on a single named document or registry, and the same alias may exist in more than one project. Rather than guess, they ask you to say which:
new · delete · archive · unarchive · track add · track remove · track clear · templates list · templates show
meldoc new --alias returns-policy --project dundleros-web
With only one project configured, the flag stays optional.
Keep in mind:
--projectonmeldoc initmeans something different — there it writes the project alias into a new config file. On every other command it selects which of the configured projects to run.
Which project owns a file
The owner of a file is the project whose directory is the longest match for its path. Matching is segment by segment, so api/docs-old is not inside api/docs.
A file outside every project directory is ignored. meldoc ci names such files in its output, so a document in the wrong place is visible rather than silently unsynced.
push by explicit path fails before any request when the path belongs to another project, and pull checks every destination before it writes.
patterns select which files inside a project are documents. They narrow a project and cannot widen it past its directory.
Per-project scope
scope and scopeChildren can be set on a single project as well as on the config as a whole:
workspaceAlias: dundler-paper
scope: [handbook]
baseDirs:
- projectAlias: dundleros-api
baseDir: api/docs
scope: [api-reference] # replaces the config-level scope
- projectAlias: dundleros-web
baseDir: web/docs # inherits scope: [handbook]
- projectAlias: dundleros-ops
baseDir: ops/docs
scope: [] # opts out of the inherited scope entirely
A project that states its own scope replaces the config-level one. A project that says nothing inherits it. scope: [] is not silence — it is how a project opts out of a scope the others inherit.
prune, in contrast, is a single config-level setting and applies to every project. There is no per-project form, so before turning it on, check what a full push would remove from each project:
meldoc push --project dundleros-api --dry-run
Independent sync state
Cache entries and tracked records carry the project that owns them, and the pull cursor is one cursor per project. Two projects therefore sync independently, and the same alias may exist in both without collision.
Publishing from CI
One run covers the whole commit. meldoc ci takes the git diff once and routes the changed and deleted paths to the project that owns each one, so a commit touching several documentation trees is a single publish:
meldoc ci --all --token "$MELDOC_TOKEN"
See CI/CD Integration for the full pipeline setup.
Moving from one project to several
Existing single-project configs keep working unchanged — the old baseDir + projectAlias form is read as a list of one project.
Two things to know when you convert:
The directory bounds a project only under baseDirs. A single baseDir keeps its original meaning — where to put a new document, not what to look at — so upgrading the CLI does not make a repository stop syncing files kept outside it.
Local state carries over by itself. Each cache and tracked record is stamped once with the project that owns its path, and the file is rewritten by the first command allowed to write it. meldoc scan without --force, docs, validate and any --dry-run still touch nothing.
The pull cursor is the exception: a cursor has no path to identify it by. Keep a top-level projectAlias naming the project that inherits it, and that project keeps its place in the sync stream:
workspaceAlias: dundler-paper
projectAlias: dundleros-api # inherits the pre-upgrade cursor
baseDirs:
- projectAlias: dundleros-api
baseDir: api/docs
- projectAlias: dundleros-web
baseDir: web/docs
Without it, that project does one full pull. A top-level projectAlias naming no configured project is rejected rather than quietly becoming the owner of your existing state.
--base-dir overrides a single project’s folder, so under baseDirs it fails with an explanation instead of being silently ignored — use --project instead.
What’s next?
Configuration — Config file and frontmatter reference.
Command Reference — Full reference for every CLI command.
CI/CD Integration — Publish docs automatically from CI/CD pipelines.