@contentrain/skills 0.4.0 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/skills",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "license": "MIT",
5
5
  "description": "AI agent skills for Contentrain — workflow procedures, framework integration guides",
6
6
  "type": "module",
@@ -61,7 +61,7 @@
61
61
  "tsdown": "^0.21.0",
62
62
  "typescript": "^5.7.0",
63
63
  "vitest": "^3.0.0",
64
- "@contentrain/mcp": "1.3.0"
64
+ "@contentrain/mcp": "1.5.0"
65
65
  },
66
66
  "scripts": {
67
67
  "build": "tsdown src/index.ts --format esm,cjs --dts",
@@ -16,7 +16,7 @@ Contentrain consists of 6 packages that work together:
16
16
 
17
17
  | Package | Role | How agent uses it |
18
18
  |---|---|---|
19
- | @contentrain/mcp | 17 MCP tools (scan, apply, validate, merge, doctor...) | MCP tool calls |
19
+ | @contentrain/mcp | 19 MCP tools (scan, apply, validate, merge, doctor...) | MCP tool calls |
20
20
  | contentrain (CLI) | init, serve, generate, doctor, diff, status | Shell commands |
21
21
  | @contentrain/types | Shared TypeScript contracts | Type safety |
22
22
  | @contentrain/query | Generated SDK client (Prisma-pattern) | `import from '#contentrain'` |
@@ -278,13 +278,42 @@ Push `cr/*` feature branches to remote.
278
278
 
279
279
  ### contentrain_merge
280
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.
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. The merged feature branch is pruned afterward.
282
+
283
+ Target the branch by exact name, or resolve it by model:
284
+
285
+ | Parameter | Type | Required | Description |
286
+ |-----------|------|----------|-------------|
287
+ | `branch` | string | No* | Exact feature branch name (must start with `cr/`) |
288
+ | `model` | string | No* | Resolve the branch by model id (e.g. `blog-post`) |
289
+ | `locale` | string | No | Narrow model resolution to a locale |
290
+ | `latest` | boolean | No | When multiple branches match the model, merge the most recently committed one |
291
+ | `confirm` | `true` | Yes | Must be `true` to confirm |
292
+
293
+ \* Provide either `branch` or `model`. Ambiguous model matches return the candidate branches so you can pick one (or pass `latest: true`).
294
+
295
+ Returns `{ branch, action, commit, sync }` — `sync.skipped[]` lists files the selective sync skipped because the developer has uncommitted changes. The CLI surfaces this as a warning.
296
+
297
+ ### contentrain_branch_list
298
+
299
+ List pending `cr/*` branches with their merge status against the `contentrain` branch. Use it to discover branch names for `contentrain_merge` / `contentrain_branch_delete` and to monitor branch-health pressure (warning at 50, blocked at 80 unmerged). Read-only. Local-filesystem only (`localWorktree`).
300
+
301
+ | Parameter | Type | Required | Description |
302
+ |-----------|------|----------|-------------|
303
+ | `unmerged_only` | boolean | No | Only list branches not yet merged into `contentrain`. Default `false` |
304
+
305
+ Returns `{ total, unmerged, branches: [{ name, sha, merged, lastCommit }], health }`.
306
+
307
+ ### contentrain_branch_delete
308
+
309
+ Delete a pending `cr/*` branch that will not be merged — e.g. one left by a failed operation, or a superseded draft. Only `cr/*` branches can be deleted; the `contentrain` branch is protected. Destructive: the branch and its unmerged commits are removed.
282
310
 
283
311
  | Parameter | Type | Required | Description |
284
312
  |-----------|------|----------|-------------|
285
- | `branch` | string | Yes | Feature branch name (must start with `cr/`) |
313
+ | `branch` | string | Yes | The `cr/*` branch to delete |
314
+ | `confirm` | `true` | Yes | Must be `true` to confirm deletion |
286
315
 
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.
316
+ Returns `{ status: 'deleted', branch, was_merged }`. Note: in normal operation Contentrain prunes feature branches automatically after auto-merge / `contentrain_merge`, so this tool is for cleanup of leftover branches only.
288
317
 
289
318
  ## Doctor Tools
290
319
 
@@ -54,6 +54,10 @@ Execute the generation command:
54
54
  npx contentrain generate
55
55
  ```
56
56
 
57
+ > **Two ways to invoke the generator:**
58
+ > - `contentrain generate` — via the `contentrain` CLI (recommended; requires the `contentrain` package installed). This is what all examples in this skill use.
59
+ > - `npx contentrain-query generate` — directly via the `@contentrain/query` package's own bin, for projects that depend only on `@contentrain/query` (programmatic / build-tool flows). Both run the same generator.
60
+
57
61
  If the project uses a non-standard root directory, specify it:
58
62
 
59
63
  ```bash
@@ -170,6 +174,25 @@ For convenience, suggest adding a script to `package.json`:
170
174
  }
171
175
  ```
172
176
 
177
+ ### 9b. Wire generate into build/CI (REQUIRED for fresh clones)
178
+
179
+ `.contentrain/client/` is git-ignored (it is generated output, like Prisma's client). That means a **fresh clone or CI checkout has no client**, so any `#contentrain` import fails at typecheck/build until `generate` runs.
180
+
181
+ Wire generation into the build lifecycle so it always runs before a build:
182
+
183
+ ```json
184
+ {
185
+ "scripts": {
186
+ "prebuild": "contentrain generate",
187
+ "predev": "contentrain generate"
188
+ }
189
+ }
190
+ ```
191
+
192
+ - `prebuild`/`predev` run automatically before `build`/`dev` (npm/pnpm lifecycle), so CI and teammates regenerate the client without a manual step.
193
+ - Alternatively use a `postinstall` hook, but `prebuild`/`predev` are preferred (they don't run on every dependency install and stay close to when the client is actually needed).
194
+ - If you only commit content occasionally, the watch script above covers local dev; the `prebuild` hook covers CI and fresh clones.
195
+
173
196
  ### 10. Final Summary
174
197
 
175
198
  Report to the user:
@@ -12,12 +12,12 @@ The `#contentrain` subpath import works natively in Node.js 22+ but **does NOT r
12
12
  ### Vite (Vue, React, Svelte, Astro)
13
13
 
14
14
  ```ts
15
- // vite.config.ts
16
- import { resolve } from 'node:path'
15
+ // vite.config.ts (ESM — __dirname is not defined; use import.meta.url)
16
+ import { fileURLToPath } from 'node:url'
17
17
  export default defineConfig({
18
18
  resolve: {
19
19
  alias: {
20
- '#contentrain': resolve(__dirname, '.contentrain/client/index.mjs'),
20
+ '#contentrain': fileURLToPath(new URL('.contentrain/client/index.mjs', import.meta.url)),
21
21
  },
22
22
  },
23
23
  })
@@ -60,9 +60,9 @@ Add the same `tsconfig.json` paths entry:
60
60
  }
61
61
  ```
62
62
 
63
- ### Nuxt 3
63
+ ### Nuxt 3 / Nuxt 4
64
64
 
65
- Nuxt provides a top-level `alias` option — no Vite config needed:
65
+ Nuxt provides a top-level `alias` option — no Vite config needed (the relative string avoids `__dirname` entirely):
66
66
 
67
67
  ```ts
68
68
  // nuxt.config.ts
@@ -20,14 +20,14 @@ The `#contentrain` import requires subpath imports configuration in `package.jso
20
20
  ## Vite (Vue, React, Svelte)
21
21
 
22
22
  ```typescript
23
- // vite.config.ts
24
- import { resolve } from 'node:path'
23
+ // vite.config.ts (ESM — __dirname is not defined here)
24
+ import { fileURLToPath } from 'node:url'
25
25
  import { defineConfig } from 'vite'
26
26
 
27
27
  export default defineConfig({
28
28
  resolve: {
29
29
  alias: {
30
- '#contentrain': resolve(__dirname, '.contentrain/client/index.mjs')
30
+ '#contentrain': fileURLToPath(new URL('.contentrain/client/index.mjs', import.meta.url))
31
31
  }
32
32
  }
33
33
  })
@@ -47,20 +47,22 @@ export default {
47
47
  }
48
48
  ```
49
49
 
50
- ## Nuxt 3
50
+ ## Nuxt 3 / Nuxt 4
51
51
 
52
52
  ```typescript
53
- // nuxt.config.ts
54
- import { resolve } from 'node:path'
53
+ // nuxt.config.ts (ESM — use import.meta.url, not __dirname)
54
+ import { fileURLToPath } from 'node:url'
55
55
 
56
56
  export default defineNuxtConfig({
57
57
  alias: {
58
- '#contentrain': resolve(__dirname, '.contentrain/client/index.mjs')
58
+ '#contentrain': fileURLToPath(new URL('.contentrain/client/index.mjs', import.meta.url))
59
59
  }
60
60
  })
61
61
  ```
62
62
 
63
- **Important:** Treat `#contentrain` as **server-only** in Nuxt. Use in server routes, server plugins, and `useAsyncData` callbacks only.
63
+ **Important:** Treat `#contentrain` as **server-only** in Nuxt. Use it in server routes (`server/`), server plugins, and `useAsyncData` callbacks only.
64
+
65
+ **Nuxt 4 note:** Nuxt 4 moves app code under `app/` and keeps server code under `server/`. The alias above is resolved relative to `nuxt.config.ts` (project root), so it is unchanged — but make sure your `#contentrain` calls live in `server/` (e.g. `server/api/*`), never in `app/` components that run on the client.
64
66
 
65
67
  ## SvelteKit
66
68
 
@@ -103,12 +103,12 @@ The `#contentrain` subpath import works natively in Node.js 22+ but **does NOT r
103
103
  #### Vite (Vue, React, Svelte, Astro)
104
104
 
105
105
  ```ts
106
- // vite.config.ts
107
- import { resolve } from 'node:path'
106
+ // vite.config.ts (ESM — __dirname is not defined; use import.meta.url)
107
+ import { fileURLToPath } from 'node:url'
108
108
  export default defineConfig({
109
109
  resolve: {
110
110
  alias: {
111
- '#contentrain': resolve(__dirname, '.contentrain/client/index.mjs'),
111
+ '#contentrain': fileURLToPath(new URL('.contentrain/client/index.mjs', import.meta.url)),
112
112
  },
113
113
  },
114
114
  })