@contentrain/skills 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,76 +1,115 @@
1
1
  # `@contentrain/skills`
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/%40contentrain%2Fskills?label=%40contentrain%2Fskills)](https://www.npmjs.com/package/@contentrain/skills)
4
+ [![Agent Skills](https://img.shields.io/badge/Agent_Skills-15_skills-8B5CF6)](https://agentskills.io)
4
5
  [![GitHub source](https://img.shields.io/badge/source-Contentrain%2Fai-181717?logo=github)](https://github.com/Contentrain/ai/tree/main/packages/skills)
6
+ [![Docs](https://img.shields.io/badge/docs-ai.contentrain.io-0f172a)](https://ai.contentrain.io/packages/skills)
5
7
 
6
8
  Workflow skills and framework guides for Contentrain-aware AI agents.
7
9
 
8
- This package follows the [Agent Skills standard](https://agentskills.io) for progressive disclosure: each skill has a `SKILL.md` (loaded on activation) and optional `references/` (loaded on demand).
10
+ Start here:
11
+
12
+ - [2-minute product demo](https://ai.contentrain.io/demo)
13
+ - [Rules & skills docs](https://ai.contentrain.io/packages/rules)
14
+ - [Framework integration guide](https://ai.contentrain.io/guides/frameworks)
15
+
16
+ This package follows the [Agent Skills standard](https://agentskills.io) for **progressive disclosure**: each skill has a `SKILL.md` (loaded on activation) and optional `references/*.md` (loaded on demand).
9
17
 
10
18
  ## Install
11
19
 
20
+ ### Via npm (programmatic access to catalogs and constants)
21
+
12
22
  ```bash
13
23
  pnpm add @contentrain/skills
14
24
  ```
15
25
 
16
- Or install directly via the skills CLI:
26
+ ### Via skills CLI (install skills into your AI agent)
17
27
 
18
28
  ```bash
19
- npx skills add contentrain/contentrain-ai --skill='*'
29
+ # Install all 15 skills
30
+ npx skills add Contentrain/ai/packages/skills
31
+
32
+ # Install a specific skill
33
+ npx skills add Contentrain/ai/packages/skills --skill contentrain-normalize
34
+
35
+ # Install to a specific agent
36
+ npx skills add Contentrain/ai/packages/skills --agent claude-code
37
+
38
+ # List available skills
39
+ npx skills add Contentrain/ai/packages/skills --list
20
40
  ```
21
41
 
42
+ Works with Claude Code, Cursor, Windsurf, GitHub Copilot, OpenAI Codex, Gemini CLI, and 40+ other agents.
43
+
22
44
  ## What It Contains
23
45
 
24
46
  ### Agent Skills (standard format)
25
47
 
26
- Published under `skills/`:
48
+ Published under `skills/` — 15 production skills:
27
49
 
28
50
  | Skill | Description |
29
51
  |-------|-------------|
30
- | `contentrain` | Core architecture, MCP tools, content formats |
31
- | `contentrain-normalize` | Two-phase normalize (extract + reuse) |
32
- | `contentrain-quality` | Content quality, SEO, accessibility, media |
33
- | `contentrain-sdk` | @contentrain/query SDK usage (local + CDN) |
34
- | `contentrain-content` | Content CRUD operations |
35
- | `contentrain-model` | Model creation/update |
36
- | `contentrain-init` | Project initialization |
37
- | `contentrain-bulk` | Batch operations |
38
- | `contentrain-validate-fix` | Validation and auto-fix |
39
- | `contentrain-review` | Content quality review |
40
- | `contentrain-translate` | Multi-locale translation |
41
- | `contentrain-generate` | SDK client generation |
42
- | `contentrain-serve` | Local review/normalize UI |
43
- | `contentrain-diff` | Branch content diffs |
44
- | `contentrain-doctor` | Project health diagnostics |
52
+ | `contentrain` | Core architecture, MCP tools, content formats, i18n, security |
53
+ | `contentrain-normalize` | Two-phase normalize (extract hardcoded strings + patch source files) |
54
+ | `contentrain-quality` | Content quality, SEO, accessibility, media optimization |
55
+ | `contentrain-sdk` | Query SDK usage (#contentrain imports, QueryBuilder, type-safe access) |
56
+ | `contentrain-content` | Create and manage content entries for existing models |
57
+ | `contentrain-model` | Design and save model definitions |
58
+ | `contentrain-init` | Initialize a new Contentrain project |
59
+ | `contentrain-bulk` | Batch operations on content entries |
60
+ | `contentrain-validate-fix` | Validate content and auto-fix structural issues |
61
+ | `contentrain-review` | Review content changes before publishing |
62
+ | `contentrain-translate` | Multi-locale translation workflows |
63
+ | `contentrain-generate` | Generate the typed SDK client from models |
64
+ | `contentrain-serve` | Start the local review and normalize UI |
65
+ | `contentrain-diff` | View content diffs between branches |
66
+ | `contentrain-doctor` | Diagnose project health issues |
45
67
 
46
68
  Each skill directory contains:
69
+
47
70
  ```
48
71
  skills/{name}/
49
- ├── SKILL.md # Instructions (< 500 lines)
72
+ ├── SKILL.md # Instructions (< 500 lines, quick reference)
50
73
  └── references/ # Detailed docs (loaded on demand)
51
- └── *.md
74
+ └── *.md # Deep dives: architecture, patterns, examples
52
75
  ```
53
76
 
77
+ Example references: `contentrain/references/mcp-tools.md`, `contentrain-normalize/references/extraction.md`, `contentrain-quality/references/seo.md`.
78
+
54
79
  ### Workflow skills (backward compat)
55
80
 
56
- Published under `workflows/*` — flat markdown files from previous versions. Still functional.
81
+ Published under `workflows/` — flat markdown files retained for compatibility:
82
+
83
+ - `contentrain-init.md`, `contentrain-model.md`, `contentrain-content.md`, `contentrain-bulk.md`
84
+ - `contentrain-normalize.md`, `contentrain-validate-fix.md`, `contentrain-review.md`
85
+ - `contentrain-diff.md`, `contentrain-doctor.md`, `contentrain-serve.md`
86
+ - `contentrain-generate.md`, `contentrain-translate.md`
87
+
88
+ Still fully functional; new projects should prefer the `skills/` structure.
57
89
 
58
90
  ### Framework guides
59
91
 
60
- Published under `frameworks/*`:
92
+ Published under `frameworks/` — per-framework integration patterns:
61
93
 
62
- - `nuxt.md`, `next.md`, `astro.md`, `sveltekit.md`, `vue.md`, `react.md`, `expo.md`, `react-native.md`, `node.md`
94
+ - `nuxt.md`, `next.md`, `astro.md`, `sveltekit.md` (meta frameworks)
95
+ - `react.md`, `vue.md` (UI libraries)
96
+ - `expo.md`, `react-native.md` (mobile)
97
+ - `node.md` (backend)
63
98
 
64
99
  ## Public Exports
65
100
 
66
101
  ```ts
67
102
  import { AGENT_SKILLS, WORKFLOW_SKILLS, FRAMEWORK_GUIDES } from '@contentrain/skills'
68
103
 
69
- // Agent Skills catalog (name + description for Tier 1 discovery)
70
- console.log(AGENT_SKILLS)
104
+ // Discover skills: name + description for agent activation
105
+ AGENT_SKILLS.forEach(({ name, description }) => {
106
+ console.log(`${name}: ${description}`)
107
+ })
108
+
109
+ // Backward compat: flat workflow list
110
+ console.log(WORKFLOW_SKILLS.length) // 12
71
111
 
72
- // Backward compat
73
- console.log(WORKFLOW_SKILLS)
112
+ // Framework discovery
74
113
  console.log(FRAMEWORK_GUIDES)
75
114
  ```
76
115
 
@@ -78,15 +117,24 @@ console.log(FRAMEWORK_GUIDES)
78
117
 
79
118
  | Tier | What's Loaded | When | Token Cost |
80
119
  |------|--------------|------|------------|
81
- | 1. Catalog | `name` + `description` | Session start | ~50 tokens/skill |
120
+ | 1. Catalog | `name` + `description` (AGENT_SKILLS) | Session start | ~50 tokens/skill |
82
121
  | 2. Instructions | Full `SKILL.md` body | Skill activated | < 5000 tokens |
83
- | 3. References | `references/*.md` | Agent needs detail | Varies |
122
+ | 3. References | `references/*.md` files | Agent needs detail | Varies (50-500 tokens/file) |
123
+
124
+ This reduces always-loaded context from thousands of lines to just the essentials plus catalog.
125
+
126
+ ## Parity with `@contentrain/mcp`
127
+
128
+ `@contentrain/skills` is kept in lockstep with the MCP tool registry via cross-package parity tests (`tests/mcp-parity.test.ts`):
129
+
130
+ - `skills/contentrain/references/mcp-tools.md` must have an `### <tool>` heading for every tool in the MCP `TOOL_NAMES` registry (currently 17).
131
+ - Key skills (normalize, translate) must not reference legacy `contentrain/{operation}/...` branch prefixes — MCP now emits `cr/*`.
84
132
 
85
- This reduces always-loaded context from ~4,700 lines to ~86 lines (essential guardrails only).
133
+ When MCP's surface changes, these tests fail until the skill docs catch up.
86
134
 
87
135
  ## IDE Support
88
136
 
89
- Skills are installed by `contentrain init` for detected IDEs:
137
+ Skills are installed by `contentrain init` (and re-applied with `contentrain skills --update`) for detected IDEs:
90
138
 
91
139
  | IDE | Rules Dir | Skills Dir |
92
140
  |-----|-----------|------------|
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/skills",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "description": "AI agent skills for Contentrain — workflow procedures, framework integration guides",
6
6
  "type": "module",
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/Contentrain/ai.git",
10
10
  "directory": "packages/skills"
11
11
  },
12
- "homepage": "https://github.com/Contentrain/ai/tree/main/packages/skills",
12
+ "homepage": "https://ai.contentrain.io/packages/rules#skills",
13
13
  "bugs": {
14
14
  "url": "https://github.com/Contentrain/ai/issues"
15
15
  },
@@ -17,8 +17,14 @@
17
17
  "contentrain",
18
18
  "ai",
19
19
  "skills",
20
+ "agent-skills",
20
21
  "mcp",
21
22
  "workflow",
23
+ "claude-code",
24
+ "cursor",
25
+ "windsurf",
26
+ "copilot",
27
+ "codex",
22
28
  "vue",
23
29
  "react",
24
30
  "nuxt",
@@ -54,7 +60,8 @@
54
60
  "@types/node": "^22.0.0",
55
61
  "tsdown": "^0.21.0",
56
62
  "typescript": "^5.7.0",
57
- "vitest": "^3.0.0"
63
+ "vitest": "^3.0.0",
64
+ "@contentrain/mcp": "1.3.0"
58
65
  },
59
66
  "scripts": {
60
67
  "build": "tsdown src/index.ts --format esm,cjs --dts",
@@ -10,6 +10,34 @@ metadata:
10
10
 
11
11
  Contentrain is a Git-based, AI-first content management system. Content lives in `.contentrain/` as JSON and Markdown files, managed through MCP tools. This skill covers architecture, content formats, and tool usage.
12
12
 
13
+ ## Ecosystem Overview
14
+
15
+ Contentrain consists of 6 packages that work together:
16
+
17
+ | Package | Role | How agent uses it |
18
+ |---|---|---|
19
+ | @contentrain/mcp | 17 MCP tools (scan, apply, validate, merge, doctor...) | MCP tool calls |
20
+ | contentrain (CLI) | init, serve, generate, doctor, diff, status | Shell commands |
21
+ | @contentrain/types | Shared TypeScript contracts | Type safety |
22
+ | @contentrain/query | Generated SDK client (Prisma-pattern) | `import from '#contentrain'` |
23
+ | @contentrain/rules | Behavioral guardrails (~86 lines, always-loaded) | Auto-loaded by IDE |
24
+ | @contentrain/skills | Procedural workflows (this file) | On-demand by agent |
25
+
26
+ ### CLI Serve — Review & Approval Bridge
27
+
28
+ For workflows requiring human review (normalize, content review):
29
+
30
+ ```bash
31
+ contentrain serve # http://localhost:3333
32
+ ```
33
+
34
+ | Page | When to use |
35
+ |---|---|
36
+ | /normalize | Extraction/reuse preview and approval |
37
+ | /branches | Merge or delete pending branches |
38
+ | /validate | Review validation errors visually |
39
+ | /content | Browse models and entries |
40
+
13
41
  ## Architecture: Agent vs MCP
14
42
 
15
43
  The system separates **intelligence** (agent) from **infrastructure** (MCP tools).
@@ -94,6 +122,7 @@ slug: getting-started
94
122
  | `contentrain_apply` | Apply normalize operation (extract or reuse) |
95
123
  | `contentrain_validate` | Validate content against model schemas |
96
124
  | `contentrain_submit` | Push contentrain/* branches to remote |
125
+ | `contentrain_merge` | Merge a review-mode branch into contentrain locally |
97
126
  | `contentrain_bulk` | Run batch operations on existing content |
98
127
 
99
128
  ## Calling Sequences
@@ -121,6 +150,18 @@ apply(reuse, dry_run:true) --> [review] --> apply(reuse, dry_run:false)
121
150
  --> validate --> submit --> [repeat per model]
122
151
  ```
123
152
 
153
+ ## MUST Rules
154
+
155
+ These are enforced by MCP — violating them causes errors. Know them upfront:
156
+
157
+ - MUST call `contentrain_status` before any write operation on existing projects
158
+ - MUST call `contentrain_describe_format` before creating models or content
159
+ - MUST use `dry_run: true` before `contentrain_apply` execute
160
+ - MUST call `contentrain_validate` before `contentrain_submit`
161
+ - MUST run `npx contentrain generate` after model/content changes that affect SDK
162
+ - MUST NOT write to `.contentrain/meta/`, `.contentrain/client/`, `.contentrain/context.json` directly
163
+ - MUST NOT auto-merge normalize branches (always review mode)
164
+
124
165
  ## Key Guardrails
125
166
 
126
167
  1. **Always call `contentrain_status` first** when working with an existing project
@@ -147,3 +188,10 @@ apply(reuse, dry_run:true) --> [review] --> apply(reuse, dry_run:false)
147
188
  | [i18n](references/i18n.md) | Internationalization quality rules |
148
189
  | [Security](references/security.md) | XSS prevention, secret detection, URL validation |
149
190
  | [Workflow](references/workflow.md) | Git workflow, branch naming, conflict resolution |
191
+
192
+ ## Related Skills
193
+
194
+ - **contentrain-normalize** — Two-phase extraction and source patching
195
+ - **contentrain-serve** — Browser-based review and approval UI
196
+ - **contentrain-generate** — SDK client generation
197
+ - **contentrain-sdk** — @contentrain/query usage
@@ -147,7 +147,7 @@ contentrain_submit # Push (always review mode)
147
147
 
148
148
  - A dedicated `contentrain` branch is the single source of truth for content state, created at init and protected from deletion
149
149
  - Every write operation creates a temporary worktree on a new feature branch forked from `contentrain`
150
- - Branch naming: `contentrain/{operation}/{model}/{timestamp}` (locale included when applicable)
150
+ - Branch naming: `cr/{operation}/{model}/{timestamp}` (locale included when applicable)
151
151
  - Do not create branches manually. MCP handles Git transactions
152
152
  - Developer's working tree is never mutated during MCP operations (no stash, no checkout, no merge on the developer's tree)
153
153
  - context.json is committed together with content changes, not as a separate commit
@@ -269,13 +269,35 @@ Validate project content against model schemas.
269
269
 
270
270
  ### contentrain_submit
271
271
 
272
- Push contentrain/* branches to remote.
272
+ Push `cr/*` feature branches to remote.
273
273
 
274
274
  | Parameter | Type | Required | Description |
275
275
  |-----------|------|----------|-------------|
276
- | `branches` | string[] | No | Specific branches to push (omit for all contentrain/* branches) |
276
+ | `branches` | string[] | No | Specific branches to push (omit for all `cr/*` branches) |
277
277
  | `message` | string | No | Optional message for the push operation |
278
278
 
279
+ ### contentrain_merge
280
+
281
+ Merge a single review-mode `cr/*` branch into the content-tracking `contentrain` branch and advance the base branch via `update-ref`. Runs the worktree transaction with selective sync — dirty files in the developer's working tree are preserved rather than overwritten.
282
+
283
+ | Parameter | Type | Required | Description |
284
+ |-----------|------|----------|-------------|
285
+ | `branch` | string | Yes | Feature branch name (must start with `cr/`) |
286
+
287
+ Returns `{ action, commit, sync }` — `sync.skipped[]` lists files the selective sync skipped because the developer has uncommitted changes. The CLI surfaces this as a warning.
288
+
289
+ ## Doctor Tools
290
+
291
+ ### contentrain_doctor
292
+
293
+ Structured project health report: git install, Node version, `.contentrain/` structure, model parse, orphan content, pending branch pressure, SDK client freshness. Read-only. Local-filesystem only (`localWorktree` capability — unavailable over remote providers).
294
+
295
+ | Parameter | Type | Required | Description |
296
+ |-----------|------|----------|-------------|
297
+ | `usage` | boolean | No | Run the heavier usage-analysis branch (unused content keys, duplicate dictionary values, locale coverage). Default `false` |
298
+
299
+ Returns `{ checks[], summary: { total, passed, failed, warnings }, usage? }`. Each check carries `name`, `pass`, `detail`, optional `severity: 'error' | 'warning' | 'info'`.
300
+
279
301
  ## Bulk Tools
280
302
 
281
303
  ### contentrain_bulk
@@ -45,21 +45,21 @@ Contentrain supports two workflow modes, configured in `.contentrain/config.json
45
45
 
46
46
  ## 2. Branch Naming Convention
47
47
 
48
- All Contentrain branches follow a strict naming pattern:
48
+ All Contentrain feature branches follow a strict naming pattern:
49
49
 
50
50
  ```
51
- contentrain/{operation}/{model}/{locale}/{timestamp}
51
+ cr/{operation}/{model}/{locale}/{timestamp}-{suffix}
52
52
  ```
53
53
 
54
54
  ### Examples
55
55
 
56
56
  | Scenario | Branch Name |
57
57
  |----------|-------------|
58
- | Content update | `contentrain/content/blog-post/en/1710300000` |
59
- | Model creation | `contentrain/model/team-member/1710300000` |
60
- | Normalize extraction | `contentrain/normalize/extract/blog/1710300000` |
61
- | Normalize reuse | `contentrain/normalize/reuse/marketing-hero/en/1710300000` |
62
- | Scaffold | `contentrain/new/scaffold-landing/en/1710300000` |
58
+ | Content update | `cr/content/blog-post/en/1710300000-a1b2` |
59
+ | Model creation | `cr/model/team-member/1710300000-c3d4` |
60
+ | Normalize extraction | `cr/normalize/extract/blog/1710300000-e5f6` |
61
+ | Normalize reuse | `cr/normalize/reuse/marketing-hero/en/1710300000-0789` |
62
+ | Scaffold | `cr/new/scaffold-landing/en/1710300000-1234` |
63
63
 
64
64
  ### Rules
65
65
 
@@ -97,3 +97,10 @@ Report:
97
97
  - locale or entry count affected
98
98
  - validation outcome if run
99
99
  - submit status
100
+
101
+ ## Related Skills
102
+
103
+ - **contentrain-content** — Single-entry content operations
104
+ - **contentrain-validate-fix** — Validate after bulk changes
105
+ - **contentrain-generate** — Regenerate SDK after bulk locale copy
106
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -18,6 +18,16 @@ The user wants to create new content, add entries to a collection, populate a si
18
18
 
19
19
  ---
20
20
 
21
+ ## MUST Rules
22
+
23
+ - MUST call `contentrain_describe` before writing content (know the schema)
24
+ - MUST provide ALL required fields in entries
25
+ - MUST create entries for ALL supported locales when model has `i18n: true`
26
+ - MUST NOT set system fields (id, slug, createdAt, updatedAt, status, source)
27
+ - MUST run `npx contentrain generate` after adding new models or changing fields
28
+
29
+ ---
30
+
21
31
  ## Steps
22
32
 
23
33
  ### 1. Check Project State
@@ -53,6 +63,7 @@ If the user's request does not match an existing model, offer to create one firs
53
63
 
54
64
  - Check `.contentrain/vocabulary.json` for canonical terms. All content must use these terms consistently across locales. Do not use alternative spellings or synonyms for vocabulary-defined terms.
55
65
  - Check `.contentrain/context.json` for tone conventions (professional, casual, technical).
66
+ - **For dictionaries:** Before creating any new key, call `contentrain_content_list` on the target model and scan existing values. If the value you intend to write already exists under a different key, REUSE the existing key instead of creating a new one. MCP will also warn you via `advisories` in the save response if duplicates are detected.
56
67
 
57
68
  ### 5. Generate Content
58
69
 
@@ -114,7 +125,17 @@ contentrain_content_save({
114
125
  - Prefer batch mode -- send multiple entries in a single call when possible.
115
126
  - Locale defaults to the project's default locale if omitted, but explicit locale is recommended.
116
127
 
117
- ### 9. Handle i18n Completeness
128
+ ### 9. Review Save Advisories
129
+
130
+ After `contentrain_content_save`, check the response for an `advisories` field. If present:
131
+
132
+ - Review each advisory for duplicate value warnings.
133
+ - If a duplicate is flagged, consider whether to:
134
+ - Remove the new key and reuse the existing one instead.
135
+ - Keep both keys if they serve semantically different purposes (document the reason).
136
+ - Report any advisories to the user for their decision.
137
+
138
+ ### 10. Handle i18n Completeness
118
139
 
119
140
  If the project has multiple supported locales and the model has `i18n: true`:
120
141
 
@@ -128,7 +149,7 @@ If the project has multiple supported locales and the model has `i18n: true`:
128
149
 
129
150
  If the user defers translations, note incomplete locales in the final summary.
130
151
 
131
- ### 10. Validate
152
+ ### 11. Validate
132
153
 
133
154
  Call `contentrain_validate` to check all changes:
134
155
 
@@ -139,7 +160,9 @@ Call `contentrain_validate` to check all changes:
139
160
 
140
161
  Fix any errors reported. Acknowledge any warnings.
141
162
 
142
- ### 11. Submit
163
+ For large content operations (10+ entries), also recommend running `contentrain doctor --usage` to detect unused keys and duplicate values across the project.
164
+
165
+ ### 12. Submit
143
166
 
144
167
  Call `contentrain_submit` to push branches to remote:
145
168
 
@@ -150,7 +173,17 @@ Call `contentrain_submit` to push branches to remote:
150
173
 
151
174
  Report the Studio URL if provided in the tool response -- the user can review and approve content there.
152
175
 
153
- ### 12. Final Summary
176
+ ### After Save: SDK Regeneration
177
+
178
+ When new models are created or fields change, regenerate the SDK client:
179
+
180
+ ```bash
181
+ npx contentrain generate
182
+ ```
183
+
184
+ This updates TypeScript types for the new content. See: **contentrain-generate** skill.
185
+
186
+ ### 13. Final Summary
154
187
 
155
188
  Report to the user:
156
189
 
@@ -160,3 +193,10 @@ Report to the user:
160
193
  - The submission status (auto-merged or pending review).
161
194
  - Studio link for visual review (if available).
162
195
  - Next steps: run `/contentrain-generate` to update SDK types if models changed.
196
+
197
+ ## Related Skills
198
+
199
+ - **contentrain-serve** — Browser-based review for content branches
200
+ - **contentrain-generate** — SDK client regeneration after content changes
201
+ - **contentrain-quality** — Content quality, SEO, and accessibility rules
202
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -60,3 +60,18 @@ Summarize:
60
60
  - action taken
61
61
  - base branch affected
62
62
  - any follow-up branch still pending
63
+
64
+ ## Browser Alternative
65
+
66
+ For visual branch review, use CLI serve:
67
+
68
+ ```bash
69
+ contentrain serve
70
+ ```
71
+
72
+ Navigate to http://localhost:3333/branches to see all pending branches with diffs, and merge or delete them visually.
73
+
74
+ ## Related Skills
75
+
76
+ - **contentrain-serve** — Browser-based branch review and merge
77
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -60,3 +60,10 @@ Recommended order:
60
60
  ### 5. Re-run Doctor
61
61
 
62
62
  After changes, run `contentrain doctor` again to confirm the project is healthy.
63
+
64
+ ## Related Skills
65
+
66
+ - **contentrain-init** — Re-initialize if project structure is broken
67
+ - **contentrain-validate-fix** — Fix content/model validation errors
68
+ - **contentrain-generate** — Regenerate SDK if client is stale
69
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -181,3 +181,10 @@ Report to the user:
181
181
  - TypeScript types: available via `index.d.ts`.
182
182
  - Next steps: import `query` from `#contentrain` and start querying content.
183
183
  - Reminder: re-run `contentrain generate` after model or content changes.
184
+
185
+ ## Related Skills
186
+
187
+ - **contentrain** — Core architecture and MCP tool catalog
188
+ - **contentrain-normalize** — Normalize workflow requires SDK regen after Phase 2
189
+ - **contentrain-content** — Content changes require SDK regen for type updates
190
+ - **contentrain-sdk** — @contentrain/query usage after generation
@@ -110,11 +110,13 @@ import { query, singleton, dictionary, document } from '#contentrain'
110
110
  ```ts
111
111
  const posts = query('blog-post')
112
112
  .locale('en') // set locale
113
- .where('status', 'published') // exact match filter
113
+ .where('status', 'published') // equality filter (shorthand)
114
+ .where('views', 'gt', 100) // operator filter: eq|ne|gt|gte|lt|lte|in|contains
114
115
  .sort('date', 'desc') // sort by field
115
116
  .limit(10) // limit results
116
117
  .offset(5) // skip results
117
118
  .include('author', 'tags') // resolve relation fields (1 level deep)
119
+ .count() // --> number (count of matches)
118
120
  .all() // --> T[] (returns array)
119
121
  .first() // --> T | undefined (first match)
120
122
  ```
@@ -143,22 +145,22 @@ Parameterized templates use `{placeholder}` syntax in dictionary values. The `ge
143
145
  ```ts
144
146
  const article = document('blog-article')
145
147
  .locale('en')
146
- .where('category', 'tech')
148
+ .where('category', 'tech') // equality shorthand
149
+ .where('title', 'contains', 'Guide') // operator syntax
147
150
  .include('author') // resolve relations in frontmatter
148
151
  .bySlug('getting-started') // --> T | undefined (find by slug)
149
152
 
150
- const docs = document('doc-page').locale('en').all() // --> T[]
151
- const first = document('doc-page').locale('en').first() // --> T | undefined
153
+ const docs = document('doc-page').locale('en').all() // --> T[]
154
+ const first = document('doc-page').locale('en').first() // --> T | undefined
155
+ const total = document('doc-page').locale('en').count() // --> number
152
156
  ```
153
157
 
154
158
  ### DOES NOT EXIST -- never use these
155
159
 
156
- - `.filter()` -- use `.where(field, value)` instead
160
+ - `.filter()` -- use `.where(field, value)` or `.where(field, op, value)` instead
157
161
  - `.byId()` -- use `.where('id', value).first()` instead
158
- - `.count()` -- use `.all().length` instead
159
162
  - `dictionary().all()` -- use `.get()` instead
160
163
  - Queries are SYNC -- do not use `await` with `query()`, `singleton()`, `dictionary()`, or `document()`
161
- - `.where('field', 'eq', value)` -- just `.where('field', value)`
162
164
  - `.get()` on QueryBuilder -- use `.all()` or `.first()`
163
165
 
164
166
  ---
@@ -96,4 +96,21 @@ Report to the user:
96
96
  - What was created in `.contentrain/`.
97
97
  - Which models were set up.
98
98
  - How to import content in their code (show the `#contentrain` import).
99
- - Next steps: create content, run `npx contentrain generate`, start the dev server.
99
+ - **Next step: Run `npx contentrain generate` to create the typed SDK client.** Without this, `#contentrain` imports won't work. See: **contentrain-generate** skill.
100
+ - Start the dev server and verify imports work.
101
+
102
+ ### Post-Init: Start Review UI
103
+
104
+ After initialization, start the local review UI to explore the project:
105
+
106
+ ```bash
107
+ contentrain serve
108
+ ```
109
+
110
+ This opens http://localhost:3333 where you can browse models, content, and validation results.
111
+
112
+ ## Related Skills
113
+
114
+ - **contentrain-serve** — Local review UI
115
+ - **contentrain-generate** — SDK client generation
116
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -139,3 +139,10 @@ Report:
139
139
  - field count
140
140
  - any relation targets
141
141
  - whether content migration is needed next
142
+
143
+ ## Related Skills
144
+
145
+ - **contentrain-content** — Create content for this model after defining it
146
+ - **contentrain-validate-fix** — Validate model and content after changes
147
+ - **contentrain-generate** — Regenerate SDK after model changes
148
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -17,6 +17,42 @@ Phase 1 alone is valuable: content becomes manageable in Studio, translatable, a
17
17
 
18
18
  ---
19
19
 
20
+ ## MUST Rules
21
+
22
+ - MUST scan before extract (`contentrain_scan` → `contentrain_apply`)
23
+ - MUST `dry_run: true` before `dry_run: false` for every `contentrain_apply` call
24
+ - MUST merge Phase 1 branch before starting Phase 2
25
+ - MUST run `npx contentrain generate` after Phase 2 completes
26
+ - MUST NOT reuse without scoped model or domain (whole-project patching is blocked)
27
+ - MUST NOT patch `.contentrain/` files via reuse (content files are read-only for reuse)
28
+ - MUST NOT exceed 100 patches per `contentrain_apply` call
29
+
30
+ ## Transport Requirements
31
+
32
+ Normalize (`contentrain_scan` and `contentrain_apply`) requires **local
33
+ disk access** — AST scanners walk the source tree and patch files in
34
+ place. It runs only on a `LocalProvider` (stdio transport, or an HTTP
35
+ transport configured with a `LocalProvider`).
36
+
37
+ Remote providers (`GitHubProvider`, `GitLabProvider`, future
38
+ `BitbucketProvider`) expose `astScan: false`, `sourceRead: false`, and
39
+ `sourceWrite: false`. Calling these tools over a remote provider
40
+ returns a uniform capability error:
41
+
42
+ ```json
43
+ {
44
+ "error": "contentrain_scan requires local filesystem access.",
45
+ "capability_required": "astScan",
46
+ "hint": "This tool is unavailable when MCP is driven by a remote provider. Use a LocalProvider or the stdio transport."
47
+ }
48
+ ```
49
+
50
+ If the agent is driving a remote-only MCP session, normalize must run
51
+ in a separate local-checkout session before the extracted content
52
+ branch is pushed.
53
+
54
+ ---
55
+
20
56
  ## Two-Phase Architecture
21
57
 
22
58
  | Aspect | Phase 1: Extraction | Phase 2: Reuse |
@@ -24,7 +60,7 @@ Phase 1 alone is valuable: content becomes manageable in Studio, translatable, a
24
60
  | Purpose | Pull content from source to `.contentrain/` | Patch source files with content references |
25
61
  | Scope | Full project scan | Per model or per domain |
26
62
  | Source files modified | No | Yes |
27
- | Branch pattern | `contentrain/normalize/extract/{domain}/{timestamp}` | `contentrain/normalize/reuse/{model}/{locale}/{timestamp}` |
63
+ | Branch pattern | `cr/normalize/extract/{domain}/{timestamp}` | `cr/normalize/reuse/{model}/{locale}/{timestamp}` |
28
64
  | Prerequisite | Initialized `.contentrain/` | Completed extraction (content exists in `.contentrain/`) |
29
65
  | Workflow mode | Always `review` | Always `review` |
30
66
  | Standalone value | Yes -- content is manageable in Studio immediately | Depends on Phase 1 |
@@ -97,7 +133,7 @@ Call `contentrain_apply(mode: "extract", dry_run: true)` to generate a preview.
97
133
 
98
134
  ### 6. Execute Extraction
99
135
 
100
- After user approval, call `contentrain_apply(mode: "extract", dry_run: false)`. This creates model definitions and content files in `.contentrain/` on a `contentrain/normalize/extract/{timestamp}` branch. Source files are NOT modified.
136
+ After user approval, call `contentrain_apply(mode: "extract", dry_run: false)`. This creates model definitions and content files in `.contentrain/` on a `cr/normalize/extract/{timestamp}` branch. Source files are NOT modified.
101
137
 
102
138
  ### 7. Validate and Submit
103
139
 
@@ -105,6 +141,52 @@ Call `contentrain_validate` to check schema compliance, i18n completeness, and d
105
141
 
106
142
  Tell the user: "Phase 1 complete. Content is now in Contentrain and can be managed, translated, and published from Studio. When ready, proceed with Phase 2 to update source files."
107
143
 
144
+ ### Step 5: User Review
145
+
146
+ Two paths — agent chooses based on context:
147
+
148
+ **Path A — Browser Review (recommended for visual diff):**
149
+ 1. Ensure `contentrain serve` is running (or ask user to start it)
150
+ 2. Summarize the dry_run output to the user
151
+ 3. Direct user to http://localhost:3333/normalize
152
+ 4. Explain: "On this page you can review the extraction plan and Approve or Reject it."
153
+ 5. Wait for user decision
154
+
155
+ **Path B — Terminal Review:**
156
+ 1. Show dry_run output to user
157
+ 2. Ask for explicit approval
158
+ 3. If approved: `contentrain_apply(mode: 'extract', dry_run: false)` → execute
159
+ 4. `contentrain_validate` → `contentrain_submit`
160
+ 5. `contentrain_merge(branch: 'cr/normalize/extract/...', confirm: true)` to merge locally
161
+
162
+ ### Step 6: Merge Phase 1 Branch
163
+
164
+ Phase 2 CANNOT start until Phase 1 branch is merged. Three options:
165
+ - **Browser:** localhost:3333/branches → click Merge
166
+ - **MCP Tool:** `contentrain_merge(branch: 'cr/normalize/extract/...', confirm: true)`
167
+ - **Git platform:** Create PR → review → merge
168
+
169
+ Verify with `contentrain_status` — check that extract branch is no longer in unmerged list.
170
+
171
+ ### Step 7: Phase 2 Prerequisite Check
172
+
173
+ Before starting reuse:
174
+ 1. Call `contentrain_status` and verify extract branch is merged
175
+ 2. If not merged → inform user and wait
176
+ 3. If merged → proceed to Phase 2 reuse
177
+
178
+ ### Step 8: SDK Regeneration (after Phase 2)
179
+
180
+ After all reuse operations are complete, source files now use `#contentrain` imports.
181
+ The SDK client MUST be regenerated:
182
+
183
+ ```bash
184
+ npx contentrain generate
185
+ ```
186
+
187
+ Without this, `#contentrain` imports will fail at build time.
188
+ See: **contentrain-generate** skill for details.
189
+
108
190
  ---
109
191
 
110
192
  ## Phase 2: Reuse (Step-by-Step)
@@ -125,7 +207,7 @@ Call `contentrain_apply(mode: "reuse", scope: { model: "<model-id>" }, patches:
125
207
 
126
208
  ### 4. Execute Reuse
127
209
 
128
- After user confirmation, call `contentrain_apply(mode: "reuse", scope: { model: "<model-id>" }, patches: [...], dry_run: false)`. This patches source files and creates a `contentrain/normalize/reuse/{model}/{timestamp}` branch.
210
+ After user confirmation, call `contentrain_apply(mode: "reuse", scope: { model: "<model-id>" }, patches: [...], dry_run: false)`. This patches source files and creates a `cr/normalize/reuse/{model}/{timestamp}` branch.
129
211
 
130
212
  ### 5. Validate and Submit
131
213
 
@@ -183,3 +265,10 @@ Ask the user which model or domain to process next. Repeat steps 1-5 for each re
183
265
  - [Extraction Details](references/extraction.md) -- Phase 1 extraction rules, parameters, and examples
184
266
  - [Reuse Details](references/reuse.md) -- Phase 2 replacement expressions by stack and patching rules
185
267
  - [What Is Content](references/what-is-content.md) -- Heuristics for identifying content vs code strings
268
+
269
+ ## Related Skills
270
+
271
+ - **contentrain-serve** — Browser-based review UI for extraction approval
272
+ - **contentrain-generate** — SDK client regeneration (required after reuse)
273
+ - **contentrain-sdk** — @contentrain/query usage in source code
274
+ - **contentrain** — Core architecture and full MCP tool catalog
@@ -113,7 +113,7 @@ Returns a preview of what will be created in `.contentrain/` without making chan
113
113
  contentrain_apply(mode: "extract", dry_run: false)
114
114
  ```
115
115
 
116
- Creates model definitions and content files in `.contentrain/` on a `contentrain/normalize/extract/{timestamp}` branch. `dry_run` defaults to `true`, so you MUST explicitly set `dry_run: false` to execute.
116
+ Creates model definitions and content files in `.contentrain/` on a `cr/normalize/extract/{timestamp}` branch. `dry_run` defaults to `true`, so you MUST explicitly set `dry_run: false` to execute.
117
117
 
118
118
  ### 7. Validate and Submit
119
119
 
@@ -42,7 +42,7 @@ Review the dry-run output:
42
42
  contentrain_apply(mode: "reuse", scope: { model: "<model-id>" }, patches: [...], dry_run: false)
43
43
  ```
44
44
 
45
- `dry_run` defaults to `true`, so you MUST explicitly set `dry_run: false` to execute. This patches source files and creates a `contentrain/normalize/reuse/{model}/{timestamp}` branch.
45
+ `dry_run` defaults to `true`, so you MUST explicitly set `dry_run: false` to execute. This patches source files and creates a `cr/normalize/reuse/{model}/{timestamp}` branch.
46
46
 
47
47
  ### 5. Validate and Submit
48
48
 
@@ -178,3 +178,10 @@ Noun or noun phrase, sentence case, no trailing colons. Helper text: one sentenc
178
178
  - [SEO Rules](references/seo.md) -- SEO optimization rules for content fields, meta tags, and structured data
179
179
  - [Accessibility](references/accessibility.md) -- Accessibility rules for content: alt text, ARIA, color contrast, reading level
180
180
  - [Media Rules](references/media.md) -- Media asset rules: image optimization, video handling, file naming conventions
181
+
182
+ ## Related Skills
183
+
184
+ - **contentrain-review** — Apply quality checks during content review
185
+ - **contentrain-content** — Content creation following quality rules
186
+ - **contentrain-translate** — Translation quality and i18n rules
187
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -74,6 +74,8 @@ If the agent cannot produce real content, it must leave the entry in `draft` sta
74
74
  - Descriptions/excerpts must be unique across all entries in the same collection.
75
75
  - If content is shared across entries, extract it to a referenced entry and use a `relation` field.
76
76
  - Before writing, query existing entries to confirm no duplication.
77
+ - **Dictionary values:** Different keys must not map to identical values. If "Cancel" exists under `dialog.cancel`, do not create `form.cancel` with the same value — reuse the existing key. MCP warns automatically via `advisories` in the save response.
78
+ - **Cross-model deduplication:** If the same text appears across multiple dictionary models, consider moving it to a shared dictionary or using vocabulary terms for consistency.
77
79
 
78
80
  ---
79
81
 
@@ -168,3 +168,9 @@ Only make changes after user approval.
168
168
  If fixes were applied, call `contentrain_validate` again to confirm all issues are resolved.
169
169
 
170
170
  Report the final status: "All checks passed" or list remaining issues that require manual attention.
171
+
172
+ ## Related Skills
173
+
174
+ - **contentrain-serve** — Visual review at http://localhost:3333/content
175
+ - **contentrain-quality** — Quality checklist reference
176
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -43,7 +43,9 @@ const doc = document('blog-post').bySlug('getting-started')
43
43
  |--------|-------------|
44
44
  | `.all()` | Get all entries |
45
45
  | `.first()` | Get first entry |
46
- | `.where(field, op, value)` | Filter (`eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `contains`) |
46
+ | `.count()` | Return count of matching entries |
47
+ | `.where(field, value)` | Equality filter (shorthand for `eq`) |
48
+ | `.where(field, op, value)` | Operator filter: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `contains` |
47
49
  | `.sort(field, direction?)` | Sort (`asc`/`desc`, default `asc`) |
48
50
  | `.limit(n)` | Limit results |
49
51
  | `.offset(n)` | Skip results |
@@ -71,7 +73,9 @@ const doc = document('blog-post').bySlug('getting-started')
71
73
  | `.all()` | Get all documents |
72
74
  | `.bySlug(slug)` | Get document by slug |
73
75
  | `.first()` | Get first document |
74
- | `.where(field, op, value)` | Filter by frontmatter field |
76
+ | `.count()` | Return count of matching documents |
77
+ | `.where(field, value)` | Equality filter (shorthand) |
78
+ | `.where(field, op, value)` | Operator filter (same ops as QueryBuilder) |
75
79
  | `.include(relation)` | Resolve relation fields |
76
80
 
77
81
  ## CDN Mode (Remote Data)
@@ -107,6 +111,28 @@ const doc = await client.document('docs').locale('en').bySlug('intro')
107
111
  | `in` | `.where('category', 'in', ['a','b'])` | In array |
108
112
  | `contains` | `.where('tags', 'contains', 'vue')` | String/array contains |
109
113
 
114
+ ### CDN Entry Metadata, Media & Forms
115
+
116
+ ```typescript
117
+ // Entry metadata (status, publish_at, expire_at)
118
+ const posts = await client.collection('blog').locale('en').withMeta().all()
119
+
120
+ // Media manifest & variant URLs
121
+ const media = client.media()
122
+ const asset = await media.asset('hero.jpg')
123
+ const url = media.url(asset, 'thumb')
124
+
125
+ // Forms (config fetch + submit)
126
+ const form = client.form()
127
+ const config = await form.config('contact')
128
+ const result = await form.submit('contact', { name: 'Alice' })
129
+
130
+ // Conversation API (external AI content operations)
131
+ const conv = client.conversation()
132
+ const response = await conv.send('Create a blog post about Vue 4')
133
+ const history = await conv.history(response.conversationId)
134
+ ```
135
+
110
136
  ### CDN vs Local
111
137
 
112
138
  | Aspect | Local (`#contentrain`) | CDN (`createContentrain()`) |
@@ -143,3 +169,9 @@ const doc = await client.document('docs').locale('en').bySlug('intro')
143
169
  | Reference | Description |
144
170
  |-----------|-------------|
145
171
  | [Bundler Configuration](references/bundler-config.md) | Vite, Next.js, Nuxt, SvelteKit, Metro alias setup |
172
+
173
+ ## Related Skills
174
+
175
+ - **contentrain-generate** — Generate the SDK client before using it
176
+ - **contentrain-quality** — Content quality rules for entries you query
177
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -94,3 +94,10 @@ The serve UI is a **monitoring + approval surface**, not an action trigger:
94
94
  - **Prompts**: every page shows copyable agent prompts that developers paste into their AI agent
95
95
 
96
96
  All mutations (create, edit, delete, scan, fix, normalize) are **agent-driven via MCP tools**. The UI never triggers these directly.
97
+
98
+ ## Related Skills
99
+
100
+ - **contentrain-normalize** — Normalize workflow uses serve for extraction/reuse review and approval
101
+ - **contentrain-diff** — Terminal-based branch review alternative to serve /branches page
102
+ - **contentrain-review** — Content review workflow uses serve for visual inspection
103
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -135,6 +135,14 @@ After all translations are saved, re-generate the SDK client so the application
135
135
  npx contentrain generate
136
136
  ```
137
137
 
138
+ ### After Translation: SDK Regeneration
139
+
140
+ New locale data requires SDK client regeneration:
141
+
142
+ ```bash
143
+ npx contentrain generate
144
+ ```
145
+
138
146
  ### 8. Save Translations
139
147
 
140
148
  After approval, call `contentrain_content_save` for each model and target locale:
@@ -162,7 +170,7 @@ If validation fails, fix issues and re-save.
162
170
 
163
171
  Call `contentrain_submit` to commit the translations:
164
172
 
165
- - Branch: `contentrain/content/{model}/{targetLocale}/{timestamp}`.
173
+ - Branch: `cr/content/{model}/{targetLocale}/{timestamp}`.
166
174
  - Each locale can be submitted independently.
167
175
 
168
176
  ### 11. Final Summary
@@ -178,3 +186,10 @@ Report to the user:
178
186
  - Submission status.
179
187
  - Reminder to review translations for nuance that automated checks cannot catch.
180
188
  - Suggestion: run `/contentrain-review` to verify overall i18n coverage.
189
+
190
+ ## Related Skills
191
+
192
+ - **contentrain-serve** — Review translated content in browser
193
+ - **contentrain-generate** — SDK regeneration for new locale data
194
+ - **contentrain-quality** — Translation quality rules
195
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -90,3 +90,9 @@ If validation still fails:
90
90
 
91
91
  - summarize remaining blockers precisely
92
92
  - tell the user which model/entry needs manual attention
93
+
94
+ ## Related Skills
95
+
96
+ - **contentrain-review** — Full content review workflow
97
+ - **contentrain-content** — Fix content entries after validation errors
98
+ - **contentrain** — Core architecture and MCP tool catalog
@@ -134,7 +134,7 @@ Do NOT proceed to apply unless the user approves (either via UI or explicit conf
134
134
 
135
135
  4. **Detect the user's decision.** After directing the user to the UI, check the plan file to determine the outcome:
136
136
  - **Plan file exists** (`status: "pending"`) → user has not decided yet — wait
137
- - **Plan file deleted + new `contentrain/normalize/extract/*` branch exists** → user approved, extraction applied
137
+ - **Plan file deleted + new `cr/normalize/extract/*` branch exists** → user approved, extraction applied
138
138
  - **Plan file deleted + no new branch** → user rejected the plan
139
139
 
140
140
  If rejected, ask the user what to change and iterate from Step 4 (re-evaluate candidates).
@@ -161,7 +161,7 @@ After user approval (via UI or chat), call `contentrain_apply(mode: "extract", d
161
161
 
162
162
  Note: `dry_run` defaults to `true`, so you MUST explicitly set `dry_run: false` to execute.
163
163
 
164
- This creates model definitions and content files in `.contentrain/` on a `contentrain/normalize/extract/{timestamp}` branch. Source files are NOT modified.
164
+ This creates model definitions and content files in `.contentrain/` on a `cr/normalize/extract/{timestamp}-{suffix}` branch. Source files are NOT modified.
165
165
 
166
166
  If approved via UI, the UI calls this automatically — no additional agent action needed.
167
167
 
@@ -230,7 +230,7 @@ After user confirmation, call `contentrain_apply(mode: "reuse", scope: { model:
230
230
 
231
231
  Note: `dry_run` defaults to `true`, so you MUST explicitly set `dry_run: false` to execute.
232
232
 
233
- This patches source files and creates a `contentrain/normalize/reuse/{model}/{timestamp}` branch.
233
+ This patches source files and creates a `cr/normalize/reuse/{model}/{timestamp}-{suffix}` branch.
234
234
 
235
235
  ### Step 5. Validate and Submit
236
236
 
@@ -154,7 +154,7 @@ If validation fails, fix issues and re-save.
154
154
 
155
155
  Call `contentrain_submit` to commit the translations:
156
156
 
157
- - Branch: `contentrain/content/{model}/{targetLocale}/{timestamp}`.
157
+ - Branch: `cr/content/{model}/{targetLocale}/{timestamp}-{suffix}`.
158
158
  - Each locale can be submitted independently.
159
159
 
160
160
  ### 11. Final Summary