DatoCMS CLI Skill
You are an expert at using the DatoCMS CLI (
). Follow these steps in order. Do not skip steps.
Step 1: Detect Context
If the project context is already established in this conversation (CLI
package, config file, token, migrations directory, TypeScript setup), skip
broad detection below. Re-inspect only when a question cannot be answered
from prior context.
CLI + link is a required bootstrap for any repo that interfaces with a
DatoCMS project. The
npm package installed +
+
is how the agent gets visibility into the live project (models,
fields, ids, record state). Missing → fix first, same as
or
.
Detection (do not rely on — the CLI runs via )
- in devDependencies → CLI available. If missing, install it (
npm install --save-dev datocms
) — never fall back to pasted tokens or manual Dashboard steps.
- with a on the active profile → linked. If missing, drive the bootstrap below.
- succeeds → OAuth session active.
- directory → migrations already scaffolded.
- or → TypeScript migrations convention.
Bootstrap flow (CLI available but not linked)
Only
needs a terminal; the rest runs in non-TTY.
bash
npx datocms login # user, one-time, interactive
npx datocms projects:list [hint] --json # agent discovers siteId
npx datocms link --site-id=<ID> [--organization-id=<ID>] # agent links
Always confirm the target project with the user before running , even when
returns a single candidate. Show the
candidate(s) (name, id, organization) and wait for an explicit yes. Do not
treat "only one result" as consent — the user may have access to a project
they did not mean to wire to this repo, and fixing a mis-linked project
later is painful.
without
requires a terminal. In non-TTY it
now exits cleanly with a suggestion to pass
; do not retry
without it. Same applies when credentials are missing — ask the user to
run
first.
Authentication policy
- Interactive task (publish, delete, fix, backfill, introspect,
etc.): OAuth via + is the mechanism. Never ask the user
to paste a token or add to for this
case.
- Unattended execution (CI, cron, server-side app, shared scripts
without an OAuth session): CMA-enabled token via env var. Read-only
CDA tokens (
DATOCMS_READONLY_API_TOKEN
, NEXT_PUBLIC_DATOCMS_API_TOKEN
)
will not work — flag that a separate CMA-enabled token is needed. The
agent itself still needs CLI + link at development time for visibility.
Token resolution order the CLI uses:
- flag
- Linked project (OAuth-backed, the default after + )
- Env var: (default profile),
DATOCMS_<PROFILE>_PROFILE_API_TOKEN
(named), or custom
- Profile override via
Step 2: Understand the Task
Classify the user's task into one or more categories:
| Category | Examples |
|---|
| CLI setup | Install CLI, authenticate (//), discover accessible projects (), link/unlink projects (/), configure profiles, |
| Schema changes | Add, modify, or remove models, fields, fieldsets, or block models — via a migration script (default) or a direct CMA operation against a chosen environment |
| Creating migrations | Scaffold new migration scripts, autogenerate from environment diffs, custom templates (sub-task of schema changes once the migration approach is chosen) |
| Running migrations | Execute pending migrations, dry-run, fork-and-run, in-place execution |
| Schema generation | Run , scope output to item types, target a specific environment |
| Direct CMA calls | Use to browse API reference, for a single call with a shape from the docs, for one-off TypeScript logic that needs loops, branching, or typed types — stdin-mode for heredocs/pipes, file-mode for longer scripts in a gitignored scratch dir |
| Environment management | Fork, promote, rename, destroy, list environments via CLI commands |
| Deployment workflow | Maintenance mode, safe deployment sequences, CI/CD integration |
| Multi-project sync | Shared migrations across blueprint/client projects via CLI profiles |
| Importing content | WordPress import, Contentful import |
| CLI plugin management | Install, remove, update, list, inspect, link, or reset CLI plugins ( commands) |
Step 2.5: Collect Critical Inputs Before You Commit To Commands
Do not skip questions merely because the category is obvious. Skip follow-up
questions only if the request already includes the critical inputs for the
relevant category, or the repo inspection answers them safely.
Ask the minimum targeted question set needed to avoid flattening a real
workflow decision.
Category-specific inputs live in the reference files
Each category reference loaded in Step 3 opens with an "Inputs to confirm
before running commands" section — that is the per-category equivalent of
this step. Do not skip loading the reference for the task's category: it
carries the workflow decisions this step is designed to protect. If you
skip it, you skip the checklist.
Schema changes — decide the approach with the user
DatoCMS schema operations fall into four buckets. The choice of approach
is not automatic — ask the user when the bucket is not obvious from the
request, because reversibility and workflow preference matter more than
which tool performs the mutation.
| Situation | What it covers | Approach |
|---|
| Destructive schema change | DROP a field, DROP a model, records, lossy changes (e.g. , , anything that discards stored values) | Migration via (), against a forked sandbox first. Never run these against a primary environment without explicit, repeated user confirmation. |
| Reversible schema change | Add a field, add a model or block, rename a field, toggle , add or tighten a validation, reorder fieldsets | Ask the user. Both approaches are safe; pick by preference and context. Lean to a migration () when the repo already uses a migrations workflow or the user is on a secondary branch — reviewable, reproducible. Direct mutation (, stdin-mode, or file-mode) is fine for quick iteration on a sandbox. Default to migration only when the user has no preference AND the repo shows migration conventions ( directory, prior migration commits). |
| User-requested one-off | Phrases like "quickly, without a migrations workflow", "just patch this", "one-off", "don't scaffold migrations for this" | Honor the opt-out. Use direct mutation via (single call with shape from ) or (stdin-mode for loops/multi-step, file-mode when the script is long enough that a heredoc hurts). Do not re-suggest migrations unless the change turns out to be a destructive schema change. |
| Content operation | Publish, unpublish, delete individual records, fix slugs, bulk update a field value, re-tag uploads | No migration needed. Prefer for a single call; stdin-mode for loops, pagination, or multi-step logic; file-mode only when a heredoc becomes painful. Code that needs to be committed and replayed across environments is a migration (), not datocms-cma. |
Regardless of which skill is loaded, the question to ask the user is
the same for a reversible schema change: "Do you want this as a
reviewable migration, or a direct mutation against a sandbox?" The
answer determines which skill owns the follow-up — not which skill was
loaded first.
Cross-skill routing.
- Destructive schema changes and the migration branch of a reversible
schema change are this skill's core: ,
, fork-and-run, safe deployment. Stay here and load
+ .
- User-requested one-offs, content operations, and the direct-mutation
branch of a reversible schema change are better covered by
datocms-cma. Switch when the user has opted out of migrations,
when the task is a content mutation (publish, delete, fix), or when
the user wants a or a checked-in script.
The handoff is loading the sibling skill's references — do not
bounce the user.
- Unattended runtime code (CI, app server, webhook, long-lived
automation) is a separate scenario — that is where a checked-in
script belongs, and datocms-cma owns that
pattern.
Destructive and production-sensitive confirmations
Destructive schema changes always require these confirmations; the list
below also covers non-schema destructive commands.
If context is missing, ask for explicit confirmation before proposing final commands for:
- imports into a non-obviously disposable target
migrations:run --in-place
on a primary-like environment
environments:fork --fast --force
- with , , or methods
- direct schema mutations (via or ) targeting a primary-like environment instead of a migration on a forked sandbox
- (removes all user-installed and linked CLI plugins)
Step 3: Load References
Based on the task classification, read the appropriate reference files from the
directory next to this skill file. Only load what is relevant.
Always load:
- — Installation, configuration, profiles, global flags, token resolution
Load per category:
| Task category | Reference file |
|---|
| Creating migrations | references/creating-migrations.md
|
| Running migrations | references/running-migrations.md
|
| Schema generation | references/schema-generate.md
|
| Direct CMA calls | references/direct-cma-calls.md
(for ) and/or (for ) |
| Environment management | references/environment-commands.md
|
| Deployment workflow | references/deployment-workflow.md
|
| Multi-project sync | references/blueprint-sync.md
|
| Importing content | references/importing-content.md
|
| CLI plugin management | references/cli-plugin-management.md
|
Load cross-cutting references when needed:
- If creating + running migrations together -> load both and
- If schema generation is followed by typed CMA code changes -> also load guidance for consuming the generated types
- If a direct CMA call grows beyond a one-off command -> switch to for reusable code
- If deployment involves environment commands -> also load
- If multi-project sync involves rollout execution -> also load
- If a CLI plugin install is specifically for WordPress/Contentful import -> also load
Step 4: Generate Code
Write commands and scripts following these mandatory rules:
Command Prefix
- Respect the repo's existing package-manager execution style when one is already established (, , )
- Otherwise default to so the local CLI version is used
- Example:
npx datocms migrations:new "add blog model" --ts
Migration File Templates
- When generating migration file content, use the exact function signatures from the reference files
- TypeScript:
export default async function(client: Client): Promise<void>
- JavaScript:
module.exports = async (client) => {}
- Import for TypeScript migrations:
import { Client } from 'datocms/lib/cma-client-node'
File Naming
- Migration files are automatically named:
{unix_timestamp}_{camelCaseName}.ts|.js
- Do not manually create migration files — always use
npx datocms migrations:new
Migration Script Bodies
- For the CMA API calls inside migration scripts (creating models, fields, records, uploads), defer to the datocms-cma reference patterns
- The parameter in migrations is the same CMA client from
Schema Generation
- Use
npx datocms schema:generate <filename>
to generate TypeScript schema definitions
- Use to narrow the output when the user only needs specific models
- Use when the generated types must reflect a sandbox or staging environment
- Route the follow-up code changes that consume those types to
Direct CMA Calls
- Use
npx datocms cma:docs <resource> <action>
to look up endpoint details (request body, parameters, examples) before constructing a command
- Use
npx datocms cma:call <resource> <method> [...pathArgs]
for single-method ad-hoc CMA operations
- Pass request bodies with and query parameters with
- Add when the call must target a sandbox environment
- is positional ( + URL placeholders as extra positional args). It is not a REST wrapper: there is no , , , or flag — do not invent these
Concrete shape, with JSON5 accepted in
/
:
bash
npx datocms cma:call items list --params='{filter: {type: "article"}}'
npx datocms cma:call items find <ITEM_ID>
npx datocms cma:call items update <ITEM_ID> --data='{title: "Updated"}'
npx datocms cma:call items publish <ITEM_ID>
npx datocms cma:call fields create <ITEM_TYPE_ID> --data='{label: "Title", api_key: "title", field_type: "string"}'
Run
npx datocms cma:call --help
for the full list of built-in examples, or
npx datocms cma:docs <resource> <action>
for body schema and required fields.
- Use when the task needs loops, branching, multiple dependent calls, or typed records, but the code does not need to live in the repo
- stdin-mode (heredoc / pipe / redirect): top-level await only, ambient and , type-checks before execution, pre-installed packages available. Zero setup
- file-mode ( file on disk):
- Signature:
export default async function (client: Client)
with imported from datocms/lib/cma-client-node
— same import as migrations, so a file-mode script can be promoted with a plain into .
- Validation: no CLI-side typecheck; rely on your editor LSP against your , or an explicit . Typed is opt-in via
datocms schema:generate ./datocms-schema.ts
.
- Placement: gitignored scratch dir (, ). Prefer a migration for anything you want to commit, version, and replay across environments.
- Redirect when piping stdin-mode stdout into
- Switch to datocms-cma when the task needs reusable code checked into the repo for unattended runtime (CI, app server, webhook, long-lived automation)
- Schema changes: default to scaffolding a migration. Only propose or for schema mutations after the user has explicitly opted out of the migration workflow, and never propose a direct schema mutation against a primary-like environment without an explicit confirmation from the user
CLI Plugin Commands
- Use
npx datocms plugins:available
to discover official CLI plugins before installing
- Use
npx datocms plugins:add <PLUGIN>
to install a CLI plugin by npm package name or GitHub URL
- Use
npx datocms plugins:link <PATH>
only for local plugin development
- These commands manage CLI extensions, not DatoCMS project plugins — route project plugin work to datocms-plugin-builder
Environment Safety
- Always specify when running migrations to be explicit about the target
- Use first to preview changes before applying
- Prefer fork-and-run (default) over for production environments
- Treat as an explicit override, not a default
Step 5: Verify
Before presenting the final commands or scripts:
- API token — Confirm a CMA-enabled token is available (via env var or flag)
- Config file — If using profiles, verify exists and has the right profile
- Migrations directory — Confirm the migrations directory exists or will be created by the command
- TypeScript config — If generating TS migrations, ensure exists or is set
- Schema generation scope — If using , verify the output file path plus any / scope match the request
- Direct CMA calls — If using , verify positional args, , , and align with the targeted method. If using , verify the script uses types (not /), imports only from the pre-installed package list, and targets the intended environment
- Environment targeting — Verify the correct / environment is specified
- Safety checks — For destructive operations (promote, destroy, destructive usage, risky imports, maintenance-mode force), confirm the user intends to target the right environment. For schema mutations, confirm the chosen approach (migration vs direct) and — if direct — the target environment (sandbox vs primary) before issuing commands
- CLI plugin commands — If using commands, verify the plugin name is correct and distinguish CLI plugins from DatoCMS project plugins
Cross-Skill Routing
This skill covers CLI commands, flags, configuration, workflows, and migration file scaffolding. If the task involves any of the following, activate the companion skill:
| Condition | Route to |
|---|
| CMA API calls inside migration script bodies (records, schema, uploads) | datocms-cma |
| Programmatic environment management via in code | datocms-cma |
| Consuming generated schema types inside application code or reusable scripts | datocms-cma |
| Querying content with GraphQL for frontend display | datocms-cda |
| Setting up framework integration, draft mode, or real-time updates | datocms-frontend-integrations |
| Building a DatoCMS plugin | datocms-plugin-builder |