Skip to content

feat(cms-189): installable MDCMS skill pack + non-interactive mdcms init#102

Merged
iipanda merged 3 commits intomainfrom
feat/cms-189-installable-skill-pack
Apr 16, 2026
Merged

feat(cms-189): installable MDCMS skill pack + non-interactive mdcms init#102
iipanda merged 3 commits intomainfrom
feat/cms-189-installable-skill-pack

Conversation

@iipanda
Copy link
Copy Markdown
Collaborator

@iipanda iipanda commented Apr 16, 2026

Summary

  • Ships a 9-skill installable pack under skills/<slug>/SKILL.md, distributed via skills.shnpx skills add Blazity/mdcms. Works cross-agent (Claude Code, Cursor, Gemini, Codex, Copilot, and 40+ others).
  • Master skill (mdcms-setup) detects repo state and routes to the focused skill for each phase: self-host, brownfield vs greenfield init, schema refine, Studio embed, SDK integration, MDX components, day-to-day sync.
  • mdcms init gains a non-interactive mode so AI agents (and CI) can drive it end-to-end: -y / --yes / --non-interactive, plus --directory, --directories, --default-locale, --no-import, --no-git-cleanup, --no-example-post. Missing required input surfaces as INIT_MISSING_INPUT instead of hanging on a TTY prompt.
  • Existing interactive mdcms init behavior is unchanged. Value resolution order: flag → env var → config → stored credential → prompt (skipped in non-interactive).

Skills in the pack

Skill Purpose
mdcms-setup master orchestrator; phases 1–7
mdcms-self-host-setup Docker Compose backend, env, first boot
mdcms-brownfield-init import existing MD/MDX repo via mdcms init --non-interactive
mdcms-greenfield-init empty-repo scaffold + first push
mdcms-schema-refine defineType / Zod / reference() + schema sync
mdcms-studio-embed <Studio /> catch-all route in host app
mdcms-sdk-integration @mdcms/sdk fetch, drafts vs published, SSR
mdcms-mdx-components register custom MDX components for Studio + host
mdcms-content-sync-workflow daily pull/push + CI automation

Spec delta

  • docs/specs/SPEC-008 — documents the non-interactive surface (flag table, value resolution order, INIT_MISSING_INPUT error) alongside the existing interactive wizard. No Studio / backend contract changes; no apps/studio-review impact.

Test plan

  • bun test --cwd apps/cli ./src/lib/init.test.ts — 18/18 pass (11 new, 7 pre-existing).
  • bun test --cwd apps/cli ./src — 203/203 pass.
  • bun x prettier --check <changed paths> — clean.
  • bun run check — CLI typecheck clean; packages/studio has a pre-existing @tiptap/pm type-resolution failure reproducible on untouched origin/main, unrelated to this PR.
  • Manual: run mdcms init --non-interactive --server-url … --project … --environment … --api-key … --directory … against a dev backend and confirm config + schema + import complete without any prompt.
  • Manual: npx skills add from a local checkout into ~/.claude/skills/ and verify the master orchestrator triggers on "set up MDCMS".

Notes for reviewers

  • Skill descriptions lean "pushy" on purpose to avoid undertriggering. Happy to tone them down.
  • Skills reference apps/studio-example as the source of truth for Studio embed / MDX component wiring rather than inlining possibly-drifting code snippets. Corrections welcome if I've mis-stated any current contract detail.
  • No Claude-Code-specific plugin bundle in this PR. The pack stays cross-agent; a plugin wrapper can land later when we have an MCP server / hooks / subagents worth bundling.

Closes CMS-189.

Summary by CodeRabbit

  • New Features

    • Non‑interactive/CI mode for init (-y/--non-interactive) with flags for directories, default locale, and toggles: --no-import, --no-git-cleanup, --no-example-post; help text updated.
  • Behavior Changes / Error Handling

    • Non‑interactive runs fail fast on missing required inputs; directories and flag values are validated; config overwrite and confirmations auto-resolve (production defaults where applicable).
  • Tests

    • Expanded unit and integration tests around flag parsing and headless init flows.
  • Documentation

    • Added a Skills Pack and detailed guides for init, schema, SDK, sync, Studio embed, and self‑hosting.

…cms init`

Ships a 9-skill installable pack under `skills/<slug>/SKILL.md`, distributable
via `npx skills add Blazity/mdcms` (skills.sh CLI). A master orchestrator
(`mdcms-setup`) detects repo state and routes to focused skills for
self-hosting, brownfield/greenfield init, schema refinement, Studio embed,
SDK integration, custom MDX components, and day-to-day sync.

To make skills drivable without TTY prompts, `mdcms init` gains a
non-interactive mode: `-y` / `--yes` / `--non-interactive`, plus
`--directory`, `--directories`, `--default-locale`, `--no-import`,
`--no-git-cleanup`, `--no-example-post`. Missing required inputs surface
as `INIT_MISSING_INPUT` instead of hanging on a prompt. Existing
interactive behavior is unchanged.

- apps/cli/src/lib/init.ts: flag parser + value resolution order
- apps/cli/src/lib/init.test.ts: +11 tests covering parser and flow
- docs/specs/SPEC-008: documents new flags and value resolution order
- skills/: new top-level distributable pack with README + 9 SKILL.md files
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 16, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 313a256f-8dc4-42fa-81cd-069da72d3391

📥 Commits

Reviewing files that changed from the base of the PR and between 2d074f7 and a3d4230.

📒 Files selected for processing (1)
  • .changeset/quiet-agents-init.md

📝 Walkthrough

Walkthrough

Adds a non-interactive mode to mdcms init with flag parsing and fail-fast behavior for CI, centralizes init control flow around parsed flags, extends unit and integration tests (including an in-memory credential store), and adds a nine-document Skills Pack describing init, setup, schema, sync, SDK, MDX, self-hosting, and Studio embed workflows.

Changes

Cohort / File(s) Summary
CLI init implementation & tests
apps/cli/src/lib/init.ts, apps/cli/src/lib/init.test.ts
Introduced InitFlagOptions and parseInitOptions(args), updated createInitCommand to drive behavior from flags (--non-interactive/-y, --no-import, --no-git-cleanup, --no-example-post, --directory/--directories, --default-locale), added runtime errors for missing/invalid inputs in non-interactive mode, directory/locale validation, and extensive unit/integration tests plus an in-memory CredentialStore test helper.
CLI spec update
docs/specs/SPEC-008-cli-and-sdk.md
Expanded cms init documentation with a “Non-Interactive Mode” section: new flags, input resolution order (flags → env → config → stored credential → prompt), non-interactive defaults/behavior, and INIT_MISSING_INPUT error semantics.
Skills Pack index & skills
skills/README.md, skills/mdcms-*/SKILL.md (multiple files)
Added Skills Pack index and nine new skill docs: mdcms-setup, mdcms-brownfield-init, mdcms-greenfield-init, mdcms-schema-refine, mdcms-content-sync-workflow, mdcms-sdk-integration, mdcms-mdx-components, mdcms-self-host-setup, mdcms-studio-embed — each describing workflows, prerequisites, steps, gotchas, and delegation.
Changeset
.changeset/quiet-agents-init.md
New changeset documenting non-interactive init flags and behavior for CI/agents.
Other docs/meta
(implicit reductions/additions across docs)
Minor alignment/formatting adjustments within the CLI + spec docs to reflect new flags and usage examples.

Sequence Diagram

sequenceDiagram
    actor User
    participant CLI as CLI Process
    participant Parser as Argument Parser
    participant Validator as Input Validator
    participant Discovery as Content Discovery
    participant Server as Remote API
    participant FS as File System

    User->>CLI: run `npx mdcms init --non-interactive ...`
    CLI->>Parser: parseInitOptions(args)
    Parser-->>CLI: InitFlagOptions
    CLI->>Validator: resolve/validate server, project, environment, api-key
    alt missing required input in non-interactive
        Validator-->>CLI: RuntimeError (INIT_MISSING_INPUT)
        CLI-->>User: exit code 1, stderr message
    else inputs present
        CLI->>Discovery: find content directories & locales
        Discovery-->>Validator: available dirs/locales
        Validator->>CLI: validate --directory(s), --default-locale
        CLI->>FS: write `mdcms.config.ts` (overwrite if non-interactive)
        alt --no-import not set
            CLI->>Server: import content (POSTs)
            Server-->>CLI: import results, manifest data
            CLI->>FS: write manifest
        else --no-import set
            CLI-->>CLI: skip import and manifest write
        end
        alt --no-example-post not set
            CLI->>FS: scaffold `example.md`
        end
        CLI-->>User: exit code 0, success output
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I parsed the flags beneath the moonlit tree,
Prompts tucked in pockets, non‑interactive and free.
Configs sprout like carrots, skills blooming near,
A tiny rabbit cheers — setup done, hip‑hip‑hooray, clear! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and clearly summarizes the two main changes: introducing an installable MDCMS skill pack and implementing non-interactive mode for the mdcms init command.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cms-189-installable-skill-pack

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/cli/src/lib/init.ts (1)

1077-1081: ⚠️ Potential issue | 🟡 Minor

Don’t announce example.md when --no-example-post skipped it.

scaffoldedType is set for every empty-repo init, so the outro currently says the example post was created even when lines 650-667 intentionally skipped writing it. Gate this message on actual file creation to keep non-interactive logs accurate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cli/src/lib/init.ts` around lines 1077 - 1081, The outro always reports
"Example post created" because it checks scaffoldedType which is set for every
init; instead, gate the stdout.write on whether the example file was actually
created: add a boolean (e.g., exampleCreated) that is set to true where the
example post write occurs (the branch that currently writes the example file)
and set false when the --no-example-post path skips it, then change the final
message that uses scaffoldedType/selectedDirectories to only run if
exampleCreated is true; reference the existing symbols scaffoldedType,
selectedDirectories and the example-file write branch to locate where to set and
check exampleCreated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/cli/src/lib/init.ts`:
- Around line 617-628: The code path handling empty repos only uses
initOpts.directories[0] and silently drops additional repeatable --directory
values; update the logic in the branch that checks dirGroups.size === 0 to
either iterate over initOpts.directories and set selectedDirectories to all
provided values (so every requested directory is scaffolded), or explicitly
reject multiple values when initOpts.nonInteractive is true by validating
initOpts.directories.length and throwing/printing an error; modify the block
referencing initOpts.directories, dirName, selectedDirectories and the
prompter.text fallback to preserve or validate all entries rather than only
using the first one.
- Around line 61-76: The parsing logic currently allows empty inline values for
flags like --directory, --directories, and --default-locale to slip through;
update the flag-handling code so inline empty values are validated the same as
space-separated forms by reusing or mirroring readInitFlagValue's check: when
you detect a flag token that may contain an '=' (e.g., '--directory=' or
'--default-locale='), treat an empty string after '=' as missing and throw the
same RuntimeError({ code: "INVALID_INPUT", message: `Flag "${flag}" requires a
value.`, statusCode: 400, details: { flag } }) used in readInitFlagValue;
alternatively call readInitFlagValue for space-separated cases and add a utility
that validates and rejects '' for '='-style tokens in the code paths that
currently handle --directory, --directories, and --default-locale (also apply
the same change to the other flag parsing block mentioned around the other
parsing function).

In `@skills/mdcms-brownfield-init/SKILL.md`:
- Around line 66-68: The line "Creates (or joins) the project and environment on
the server." incorrectly claims reuse; either remove "or joins" or explicitly
document the exact precondition/recovery path for the init command: state that
init will attempt to create the project/environment and will exit with an error
on project-create 409, describe what the caller should do on that error (e.g.,
manually join or pass an explicit flag), and reference the init behavior and the
project-create 409 response so readers know the expected flow.

In `@skills/mdcms-content-sync-workflow/SKILL.md`:
- Around line 92-120: The workflow's MDCMS push step uses the interactive-safe
command `npx mdcms push --validate`, which will skip new/deleted candidates in
non-interactive CI and can cause schema sync failures; update the `MDCMS push`
job to run a headless-safe command such as `npx mdcms push --validate --force`
(and add any CLI flag your tool uses for non-interactive confirmation like
`--yes` or `--confirm` if available) so pushes on `content/**` or
`mdcms.config.ts` changes apply created/deleted items and schema updates
reliably; modify the `run:` line under the `MDCMS push` step to include these
flags.
- Around line 135-138: Update the SKILL.md bullet that instructs readers to
"check `mdcms push --help` for the current deletion flag" because the CLI
doesn't expose a dedicated deletion flag; instead, reword the text to explain
that deletions are handled interactively by `mdcms push` (it will classify "both
modified" or prompt before deleting) and mention the actual available flags
(`--force`, `--dry-run`, `--validate`, `--published`, `--sync-schema`) and how
`--force` affects deletion behavior (non-interactive overwrite). Refer to the
`mdcms push` command and the `--force`/`--dry-run` flags when updating the
paragraph.

In `@skills/mdcms-sdk-integration/SKILL.md`:
- Around line 55-65: Replace the incorrect SDK calls and shape assumptions: use
the SDK methods cms.get(type, input) and cms.list(type, input?) instead of
getDocument/listDocuments, and update any downstream usage to expect the
paginated envelope returned by list (access the items via the .data property,
e.g., iterate over posts.data rather than posts); update examples that showed
const about = ... and const posts = ... to call cms.get("page", { path: "about"
}) and cms.list("post", { limit: 20 }) semantics and adjust subsequent code to
use the list response's data field.

In `@skills/mdcms-self-host-setup/SKILL.md`:
- Around line 40-43: The checklist uses the wrong S3 env-var prefix
`MDCMS_S3_*`; update the doc to reference the correct storage env names `S3_*`
(e.g., replace any occurrence of `MDCMS_S3_*` with `S3_*`) so they match the
server/compose contract; double-check related mentions (the checklist item
listing `Database credentials`, `S3/MinIO credentials`, `Auth provider
settings`, and `MDCMS_STUDIO_ALLOWED_ORIGINS` / `<Studio />`) and adjust only
the S3 variable names to `S3_*` while leaving other env names unchanged.

In `@skills/mdcms-setup/SKILL.md`:
- Around line 36-44: The repo-scan heuristic that runs the find command will
pick up the skill pack’s own SKILL.md and misclassify empty repos as brownfield;
update the detection used before invoking
mdcms-brownfield-init/mdcms-greenfield-init to exclude skills/ and other
docs-only paths (e.g., skills/*/SKILL.md, docs/, .github/) or restrict the
search to likely content roots (e.g., content/, pages/, docs/content/) so only
true user-managed Markdown/MDX files trigger mdcms-brownfield-init; ensure the
same exclusion logic is applied where the check is repeated (lines referenced
around the find invocation and the branch that calls
mdcms-brownfield-init/mdcms-greenfield-init).

---

Outside diff comments:
In `@apps/cli/src/lib/init.ts`:
- Around line 1077-1081: The outro always reports "Example post created" because
it checks scaffoldedType which is set for every init; instead, gate the
stdout.write on whether the example file was actually created: add a boolean
(e.g., exampleCreated) that is set to true where the example post write occurs
(the branch that currently writes the example file) and set false when the
--no-example-post path skips it, then change the final message that uses
scaffoldedType/selectedDirectories to only run if exampleCreated is true;
reference the existing symbols scaffoldedType, selectedDirectories and the
example-file write branch to locate where to set and check exampleCreated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bbcce7f5-f318-4670-82fd-a0b4caa1d223

📥 Commits

Reviewing files that changed from the base of the PR and between 425652f and 10085e3.

📒 Files selected for processing (13)
  • apps/cli/src/lib/init.test.ts
  • apps/cli/src/lib/init.ts
  • docs/specs/SPEC-008-cli-and-sdk.md
  • skills/README.md
  • skills/mdcms-brownfield-init/SKILL.md
  • skills/mdcms-content-sync-workflow/SKILL.md
  • skills/mdcms-greenfield-init/SKILL.md
  • skills/mdcms-mdx-components/SKILL.md
  • skills/mdcms-schema-refine/SKILL.md
  • skills/mdcms-sdk-integration/SKILL.md
  • skills/mdcms-self-host-setup/SKILL.md
  • skills/mdcms-setup/SKILL.md
  • skills/mdcms-studio-embed/SKILL.md

Comment thread apps/cli/src/lib/init.ts
Comment thread apps/cli/src/lib/init.ts
Comment thread skills/mdcms-brownfield-init/SKILL.md Outdated
Comment thread skills/mdcms-content-sync-workflow/SKILL.md Outdated
Comment thread skills/mdcms-content-sync-workflow/SKILL.md Outdated
Comment thread skills/mdcms-sdk-integration/SKILL.md Outdated
Comment thread skills/mdcms-self-host-setup/SKILL.md
Comment thread skills/mdcms-setup/SKILL.md Outdated
iipanda added 2 commits April 16, 2026 18:50
CLI:
- parseInitOptions: reject empty inline flag values (`--directory=`,
  `--directories=`, `--default-locale=`) with the same error interactive
  space-separated forms already use.
- Empty-repo scaffold path: reject multiple `--directory` values since
  scaffolding only supports one starter directory.
- Outro "Example post created" now gated on a real `exampleCreated`
  boolean rather than the presence of a scaffolded type, so
  `--no-example-post` no longer advertises a file it never wrote.
- Tests: +3 cases covering inline empty rejection, multiple-directory
  rejection in empty-repo mode, and the outro suppression.

Skills:
- mdcms-brownfield-init: drop "or joins" claim. Init creates; server
  returns 409 on conflict and init exits. Added an "Attaching to an
  existing project" subsection covering the recovery path.
- mdcms-content-sync-workflow: CI example now runs with `--force`
  and `--sync-schema` alongside `--validate`, because push silently
  skips new/deleted candidates in non-interactive mode without
  `--force`. Deletion note rewritten to name the real push flag
  surface (`--force`, `--dry-run`, `--validate`, `--published`,
  `--sync-schema`) — there is no dedicated deletion flag.
- mdcms-sdk-integration: replace invented `getDocument`/`listDocuments`
  with the actual `cms.get(type, input)` / `cms.list(type, input)`;
  list examples iterate the paginated envelope via `response.data`;
  removed the invented `path` parameter on `get` in favor of `id` /
  `slug` per SPEC-008.
- mdcms-self-host-setup: fix S3 env var names — prefix is `S3_*`,
  not `MDCMS_S3_*`, matching `.env.example`.
- mdcms-setup: Phase 2 `find` command now excludes `skills/`,
  `docs/`, `apps/docs/`, `.github/`, and repo-level `README`/
  `CHANGELOG`/`LICENSE`/`SKILL.md`, so installing this skill pack
  into a repo doesn't self-trigger the brownfield path.
@iipanda iipanda merged commit 7e904c9 into main Apr 16, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant