create-restforge-skills 0.3.0 → 1.0.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
@@ -7,58 +7,41 @@ CLI, and OpenAI Codex** — not only Claude Code.
7
7
 
8
8
  ## What this package is (and is not)
9
9
 
10
- This package is the **portable** distribution of RESTForge agent knowledge.
10
+ This package is the **only** distribution of RESTForge agent knowledge.
11
11
 
12
12
  - It contains pure Agent Skills: a `skills/restforge/SKILL.md` plus `references/`.
13
13
  - It has **no** client-specific packaging — no Claude Code `plugin.json`,
14
- `marketplace.json`, or `.mcp.json`.
14
+ `marketplace.json`, or `.mcp.json`. The installer (`create-restforge-skills`)
15
+ copies the skill into each client and registers the MCP server there.
15
16
 
16
- It is a **complement to**, not a replacement for, [`restforge-plugins`](../packages/restforge-plugins).
17
-
18
- | | `restforge-plugins` | `restforge-skills` (this package) |
19
- |---|---|---|
20
- | Target | Claude Code only | Claude Code, Cursor, Gemini CLI, Codex |
21
- | Distribution | Claude Code plugin + marketplace | Copy/symlink the skill folder into each client's skills directory |
22
- | MCP registration | Bundled (`.mcp.json`) | Done per client by the user (see below) |
23
- | Knowledge source | `skills/restforge-skills/` | Same knowledge, portable form |
24
-
25
- Both packages wrap the **same** workflow knowledge and depend on the **same**
26
- execution engine: the `@restforgejs/mcp-server` MCP server. A skill describes
27
- *how* to drive RESTForge; the MCP server is *what* actually executes the
28
- operations. The skill is useless without the MCP server registered in the client.
17
+ The skill depends on one execution engine: the `@restforgejs/mcp-server` MCP
18
+ server. A skill describes *how* to drive RESTForge; the MCP server is *what*
19
+ actually executes the operations. The skill is useless without the MCP server
20
+ registered in the client.
29
21
 
30
22
  ## Directory layout
31
23
 
32
24
  ```
33
25
  restforge-skills/
34
- ├── README.md ← this file
26
+ ├── README.md ← this file (end-user guide, published to npm)
35
27
  ├── package.json ← npm package: create-restforge-skills
36
- ├── bump-and-publish.bat ← version bump + npm publish
37
- ├── sync-to-plugin.bat ← mirror the skill into the Claude Code plugin
28
+ ├── *.bat ← maintainer scripts (see docs/DEVELOPMENT.md)
38
29
  ├── cli/
39
30
  │ ├── index.js ← installer that copies the skill into each client
40
- │ └── mcp.js ← merges the MCP server into each client config
41
- ├── docs/ ← internal docs, NOT published (excluded from npm files)
31
+ │ ├── mcp.js ← merges JSON MCP config for Claude Code / Cursor
32
+ │ └── codex.js ← safely appends Codex TOML MCP configuration
33
+ ├── docs/
34
+ │ └── DEVELOPMENT.md ← maintainer guide, NOT published (excluded from npm files)
42
35
  └── skills/
43
36
  └── restforge/
44
- ├── SKILL.md ← the portable skill (name + description + workflow)
37
+ ├── SKILL.md ← the portable skill (name + description + workflow)
38
+ ├── agents/openai.yaml ← Codex display metadata and example prompt
45
39
  └── references/ ← progressive-disclosure reference material
46
40
  ```
47
41
 
48
- ## Single source of truth
49
-
50
- `skills/restforge/` here is the **one** authoritative copy of the skill. Two
51
- distribution channels consume it — do not edit the skill anywhere else:
52
-
53
- - **This package** (`create-restforge-skills`) — published to npm; cross-client.
54
- - **The Claude Code plugin** (`../packages/restforge-plugins`) — its
55
- `skills/restforge-skills/` folder is a **generated mirror**. After editing the
56
- canonical skill, run `sync-to-plugin.bat` to propagate, then commit the plugin
57
- repo. Hand-edits to the plugin's skill copy are overwritten on the next sync.
58
-
59
42
  ## Install
60
43
 
61
- One command. It detects your installed clients (Claude Code, Cursor), copies the
44
+ One command. It detects your installed clients (Claude Code, Cursor, Codex), copies the
62
45
  skill into each, and registers the RESTForge MCP server — because the skill is
63
46
  inert without it:
64
47
 
@@ -77,7 +60,8 @@ it takes **no positional folder argument** (`myapp` / `.`). The install location
77
60
  is chosen by `--scope`, not by where you stand or by a path you pass.
78
61
 
79
62
  - **Default (`--scope=user`) — run it from anywhere.** The current directory is
80
- ignored. The skill goes to your home (`~/.claude/skills/`, `~/.cursor/skills/`)
63
+ ignored. The skill goes to your home (`~/.claude/skills/`, `~/.cursor/skills/`,
64
+ or `~/.agents/skills/` for Codex)
81
65
  and is available across **all** your projects. This is the normal usage: a skill
82
66
  is editor/agent tooling, not part of any one app's source.
83
67
 
@@ -87,7 +71,9 @@ is chosen by `--scope`, not by where you stand or by a path you pass.
87
71
  `./.claude/skills/` or `./.cursor/skills/`; the MCP config goes to `./.mcp.json`
88
72
  for Claude Code (its project-scope convention, not a file under `.claude/`) and
89
73
  to `./.cursor/mcp.json` for Cursor. Use this to commit the skill with a specific
90
- repo so the team gets it on clone.
74
+ repo so the team gets it on clone.
75
+ For Codex, the corresponding paths are `./.agents/skills/` and
76
+ `./.codex/config.toml`; project MCP settings load only in trusted projects.
91
77
 
92
78
  ```bash
93
79
  # normal — anywhere, global for every project
@@ -104,8 +90,9 @@ Note: a bare path such as `npx create-restforge-skills .` is **not** recognized
104
90
  ### Options
105
91
 
106
92
  ```bash
107
- npx create-restforge-skills --client=cursor # one client only
108
- npx create-restforge-skills --scope=project # skill into ./.claude or ./.cursor, MCP into ./.mcp.json (commit for the team)
93
+ npx create-restforge-skills --client=cursor # one client only
94
+ npx create-restforge-skills --client=codex # Codex skill + MCP configuration
95
+ npx create-restforge-skills --scope=project # install into the current project
109
96
  npx create-restforge-skills --mcp-command=global # use the installed restforge-mcp binary instead of npx
110
97
  npx create-restforge-skills --no-mcp # skill only; you manage MCP yourself
111
98
  npx create-restforge-skills --dry-run # preview, write nothing
@@ -117,6 +104,19 @@ operations (Designer/frontend tools need no license). On Claude Code, if the
117
104
  skills directory was just created, restart the client so it watches the new
118
105
  directory.
119
106
 
107
+ ### Update
108
+
109
+ `npx` caches previously downloaded packages, so when updating always pin
110
+ `@latest` and pass `--force` to overwrite the installed skill folder:
111
+
112
+ ```bash
113
+ npx create-restforge-skills@latest --force
114
+ ```
115
+
116
+ If the machine already has the RESTForge MCP server registered the way you want
117
+ it (for example via a globally installed `restforge-mcp` binary), add `--no-mcp`
118
+ so the update touches only the skill and leaves the MCP config alone.
119
+
120
120
  ### Where it installs
121
121
 
122
122
  | Client | Scope | Skill | MCP config |
@@ -124,34 +124,71 @@ directory.
124
124
  | Claude Code | user (default) | `~/.claude/skills/restforge/` | `~/.claude.json` |
125
125
  | Claude Code | project | `./.claude/skills/restforge/` | `./.mcp.json` |
126
126
  | Cursor | user (default) | `~/.cursor/skills/restforge/` | `~/.cursor/mcp.json` |
127
- | Cursor | project | `./.cursor/skills/restforge/` | `./.cursor/mcp.json` |
127
+ | Cursor | project | `./.cursor/skills/restforge/` | `./.cursor/mcp.json` |
128
+ | Codex | user (default) | `~/.agents/skills/restforge/` | `$CODEX_HOME/config.toml` (default `~/.codex/config.toml`) |
129
+ | Codex | project | `./.agents/skills/restforge/` | `./.codex/config.toml` |
128
130
 
129
131
  Note the asymmetry on the project row: Claude Code reads a project-scope MCP
130
132
  server from `./.mcp.json` in the repo root, so that is where the installer writes
131
133
  it — not into `./.claude/`.
132
134
 
133
- > For Claude Code, a turnkey alternative is the `restforge-plugins` package,
134
- > which bundles the skill **and** MCP registration in one `/plugin install`.
135
-
136
135
  ### Manual install (no CLI)
137
136
 
138
137
  The skill folder is self-contained — copy `skills/restforge/` (including
139
- `references/`) into the client's skills directory and add
138
+ `references/` and `agents/`) into the client's skills directory. For Claude Code
139
+ and Cursor, add
140
140
  `{ "mcpServers": { "restforge": { "command": "npx", "args": ["-y", "@restforgejs/mcp-server"] } } }`
141
141
  to the client's MCP config.
142
142
 
143
- ### Gemini CLI / OpenAI Codex
144
-
145
- Planned. Both consume the same `skills/restforge/` folder; only the skills
146
- directory path and MCP config file differ per client.
147
-
148
- ## Source of truth
149
-
150
- The knowledge in this skill mirrors the RESTForge handbook
151
- ([`restforge-handbook`](../restforge-handbook)) and the MCP tool surface
152
- ([`mcp-server`](../packages/mcp-server)). When RESTForge behavior changes, update the
153
- handbook first, then this skill — the skill is downstream documentation of real
154
- tool behavior, never an independent source.
143
+ ### OpenAI Codex
144
+
145
+ Install for Codex explicitly, or let auto-detection find `CODEX_HOME` (default
146
+ `~/.codex`). No Codex CLI binary is required by the installer:
147
+
148
+ ```bash
149
+ npx create-restforge-skills --client=codex
150
+ # Or install into the current project:
151
+ npx create-restforge-skills --client=codex --scope=project
152
+ ```
153
+
154
+ Restart Codex after installation and invoke `$restforge`, for example:
155
+ `Use $restforge to create a product API.` Check the MCP connection with `/mcp`
156
+ in Codex or `codex mcp list` in a terminal.
157
+
158
+ For manual setup, copy the entire skill folder to the Codex skill path in the
159
+ table above and add this to the corresponding `config.toml`:
160
+
161
+ ```toml
162
+ [mcp_servers.restforge]
163
+ command = "npx"
164
+ args = ["-y", "@restforgejs/mcp-server"]
165
+ ```
166
+
167
+ The installer preserves existing Codex RESTForge registrations, including custom
168
+ commands, URLs, environment variables and timeouts. `--mcp-command` chooses the
169
+ command for a **new** registration; edit `config.toml` to change an existing one.
170
+ `--force` only replaces the skill. Existing TOML comments and formatting are
171
+ preserved, and a changed config is backed up to `config.toml.bak`. If the TOML
172
+ cannot be parsed or extended safely (for example an inline `mcp_servers` table),
173
+ the installer leaves it untouched, reports an error, and exits with code 1;
174
+ the skill may already have been copied. Finish the MCP setup manually.
175
+
176
+ `CODEX_HOME` changes the user MCP config location and auto-detection marker;
177
+ user skills still go into `~/.agents/skills/`. See the official
178
+ [skill discovery documentation](https://developers.openai.com/codex/skills) and
179
+ [MCP configuration documentation](https://developers.openai.com/codex/mcp).
180
+
181
+ ### Gemini CLI
182
+
183
+ Installer support is planned. Use the same `skills/restforge/` folder with the
184
+ client's manual skill installation procedure.
185
+
186
+ ## Developing and releasing
187
+
188
+ Maintainer topics live in [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md): the
189
+ skill source, testing the skill from the working tree, the reference audit, the
190
+ release flow, and the extra care needed on machines that double as RESTForge
191
+ development machines. That guide is not published to npm.
155
192
 
156
193
  ## License
157
194
 
package/cli/codex.js ADDED
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const toml = require('@iarna/toml');
6
+
7
+ function formatCodexMcp(entry) {
8
+ return toml.stringify({ mcp_servers: { restforge: entry } });
9
+ }
10
+
11
+ // Append only, preserving comments, formatting, and any existing custom server.
12
+ // Parse both documents so inline tables, quoted keys and multiline strings are
13
+ // handled by a TOML parser rather than potentially destructive text matching.
14
+ function registerCodexMcp(file, entry, opts) {
15
+ try {
16
+ const existed = fs.existsSync(file);
17
+ const raw = existed ? fs.readFileSync(file, 'utf8') : '';
18
+ const config = toml.parse(raw);
19
+ if (config.mcp_servers && Object.hasOwn(config.mcp_servers, 'restforge')) {
20
+ const existing = config.mcp_servers.restforge;
21
+ const same = existing.command === entry.command &&
22
+ JSON.stringify(existing.args || []) === JSON.stringify(entry.args || []);
23
+ return { status: same ? 'already-registered' : 'preserved' };
24
+ }
25
+ const next = raw + (raw.endsWith('\n') || !raw ? '' : '\n') + '\n' + formatCodexMcp(entry);
26
+ toml.parse(next);
27
+ if (opts.dryRun) return { status: 'would-register' };
28
+ let backup;
29
+ if (existed) {
30
+ backup = file + '.bak';
31
+ fs.copyFileSync(file, backup);
32
+ }
33
+ fs.mkdirSync(path.dirname(file), { recursive: true });
34
+ fs.writeFileSync(file, next, 'utf8');
35
+ return { status: 'registered', backup };
36
+ } catch (err) {
37
+ // Parser diagnostics can contain config values (including credentials).
38
+ return { status: 'error', error: `Cannot safely register Codex MCP (${err.code || 'invalid or conflicting TOML'}); check config.toml manually.` };
39
+ }
40
+ }
41
+
42
+ module.exports = { formatCodexMcp, registerCodexMcp };
package/cli/index.js CHANGED
@@ -14,14 +14,15 @@
14
14
  *
15
15
  * It does NOT set a license; that secret stays a manual step.
16
16
  *
17
- * Zero runtime dependencies: Node built-ins only, for fast `npx` and broad
18
- * platform support (Windows included).
17
+ * Uses a TOML parser for Codex configuration; works on Windows, macOS and Linux.
19
18
  */
20
19
 
21
20
  const fs = require('fs');
22
21
  const path = require('path');
23
22
  const os = require('os');
24
23
  const { buildEntry, registerMcp } = require('./mcp');
24
+ const { registerCodexMcp, formatCodexMcp } = require('./codex');
25
+ const codexHome = () => process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
25
26
 
26
27
  const SKILL_NAME = 'restforge';
27
28
  // Bundled skill source: <package>/skills/restforge, resolved relative to this file.
@@ -33,6 +34,12 @@ const SOURCE_DIR = path.join(__dirname, '..', 'skills', SKILL_NAME);
33
34
  * touch the filesystem for a client the user did not select.
34
35
  */
35
36
  const CLIENTS = {
37
+ codex: {
38
+ label: 'Codex',
39
+ homeMarker: codexHome,
40
+ skillsDir: (scope, cwd) => path.join(scope === 'project' ? cwd : os.homedir(), '.agents', 'skills'),
41
+ mcpConfig: (scope, cwd) => path.join(scope === 'project' ? path.join(cwd, '.codex') : codexHome(), 'config.toml'),
42
+ },
36
43
  claude: {
37
44
  label: 'Claude Code',
38
45
  homeMarker: () => path.join(os.homedir(), '.claude'),
@@ -106,9 +113,9 @@ so it works out of the box. The MCP config is merged, not overwritten, and the
106
113
  existing file is backed up to <config>.bak first.
107
114
 
108
115
  Options:
109
- --client=<list> Comma-separated clients: claude,cursor. Default: auto-detect.
116
+ --client=<list> Comma-separated clients: claude,cursor,codex. Default: auto-detect.
110
117
  --scope=<scope> user (default) installs globally for you; project installs
111
- into ./.claude or ./.cursor in the current directory.
118
+ into ./.claude, ./.cursor or ./.agents (Codex).
112
119
  --no-mcp Skip MCP registration (only do this if you know why —
113
120
  the skill cannot call anything without the MCP server).
114
121
  --mcp-command=<c> npx (default, no global install needed) or
@@ -193,8 +200,8 @@ function main() {
193
200
 
194
201
  const clientKeys = resolveClients(opts);
195
202
  if (!clientKeys.length) {
196
- console.error('No target client detected (looked for ~/.claude and ~/.cursor).');
197
- console.error('Pass one explicitly, e.g. --client=claude,cursor');
203
+ console.error('No target client detected (looked for ~/.claude, ~/.cursor and CODEX_HOME or ~/.codex).');
204
+ console.error('Pass one explicitly, e.g. --client=codex');
198
205
  process.exit(1);
199
206
  }
200
207
 
@@ -212,13 +219,17 @@ function main() {
212
219
  console.log(` ${pad('')} → skill: ${skill.status}${skill.reason ? ` (${skill.reason})` : ''}`);
213
220
 
214
221
  if (opts.mcp) {
215
- const mcp = registerMcp(target.mcpConfig, mcpEntry, opts);
222
+ const register = target.key === 'codex' ? registerCodexMcp : registerMcp;
223
+ const mcp = register(target.mcpConfig, mcpEntry, opts);
216
224
  console.log(` ${pad('')} → mcp: ${mcp.status}${mcp.error ? ` — ${mcp.error}` : ''}`);
217
225
  console.log(` ${pad('')} ${target.mcpConfig}`);
218
226
  if (mcp.backup) console.log(` ${pad('')} backup: ${mcp.backup}`);
219
227
  if (mcp.status === 'error') {
220
- console.log(` ${pad('')} add manually: "mcpServers": { "restforge": ${JSON.stringify(mcpEntry)} }`);
228
+ process.exitCode = 1;
229
+ const manual = target.key === 'codex' ? formatCodexMcp(mcpEntry) : `"mcpServers": { "restforge": ${JSON.stringify(mcpEntry)} }`;
230
+ console.log(` ${pad('')} add manually: ${manual}`);
221
231
  }
232
+ if (mcp.status === 'preserved') console.log(' Existing Codex RESTForge settings kept; edit config.toml to change them.');
222
233
  }
223
234
  }
224
235
 
@@ -229,6 +240,10 @@ function main() {
229
240
  console.log(' Claude Code: if its skills dir was just created, restart the client so it');
230
241
  console.log(' watches the new directory.');
231
242
  }
243
+ if (clientKeys.includes('codex')) {
244
+ console.log(' Codex: restart the session, then invoke $restforge. Use /mcp to check the server.');
245
+ if (opts.scope === 'project') console.log(' Codex only loads project .codex/config.toml in trusted projects.');
246
+ }
232
247
  console.log('');
233
248
  }
234
249
 
package/package.json CHANGED
@@ -1,30 +1,38 @@
1
- {
2
- "name": "create-restforge-skills",
3
- "version": "0.3.0",
4
- "description": "Install the RESTForge Agent Skill into Claude Code, Cursor, and other skills-compatible clients.",
5
- "type": "commonjs",
6
- "bin": {
7
- "create-restforge-skills": "cli/index.js"
8
- },
9
- "files": [
10
- "cli",
11
- "skills",
12
- "README.md"
13
- ],
14
- "engines": {
15
- "node": ">=18"
16
- },
17
- "keywords": [
18
- "restforge",
19
- "agent-skills",
20
- "skill",
21
- "claude-code",
22
- "cursor",
23
- "mcp"
24
- ],
25
- "author": {
26
- "name": "RESTForge",
27
- "url": "https://restforge.dev"
28
- },
29
- "license": "MIT"
30
- }
1
+ {
2
+ "name": "create-restforge-skills",
3
+ "version": "1.0.0",
4
+ "description": "Install the RESTForge Agent Skill and MCP server configuration into Claude Code, Cursor, and OpenAI Codex.",
5
+ "type": "commonjs",
6
+ "bin": {
7
+ "create-restforge-skills": "cli/index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "node --test",
11
+ "audit-references": "node scripts/audit-references.js"
12
+ },
13
+ "files": [
14
+ "cli",
15
+ "skills",
16
+ "README.md"
17
+ ],
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "keywords": [
22
+ "restforge",
23
+ "agent-skills",
24
+ "skill",
25
+ "claude-code",
26
+ "cursor",
27
+ "codex",
28
+ "mcp"
29
+ ],
30
+ "author": {
31
+ "name": "RESTForge",
32
+ "url": "https://restforge.dev"
33
+ },
34
+ "license": "MIT",
35
+ "dependencies": {
36
+ "@iarna/toml": "2.2.5"
37
+ }
38
+ }