create-restforge-skills 0.4.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
@@ -28,18 +28,20 @@ restforge-skills/
28
28
  ├── *.bat ← maintainer scripts (see docs/DEVELOPMENT.md)
29
29
  ├── cli/
30
30
  │ ├── index.js ← installer that copies the skill into each client
31
- │ └── mcp.js ← merges the MCP server into each client config
31
+ │ ├── mcp.js ← merges JSON MCP config for Claude Code / Cursor
32
+ │ └── codex.js ← safely appends Codex TOML MCP configuration
32
33
  ├── docs/
33
34
  │ └── DEVELOPMENT.md ← maintainer guide, NOT published (excluded from npm files)
34
35
  └── skills/
35
36
  └── restforge/
36
- ├── 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
37
39
  └── references/ ← progressive-disclosure reference material
38
40
  ```
39
41
 
40
42
  ## Install
41
43
 
42
- 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
43
45
  skill into each, and registers the RESTForge MCP server — because the skill is
44
46
  inert without it:
45
47
 
@@ -58,7 +60,8 @@ it takes **no positional folder argument** (`myapp` / `.`). The install location
58
60
  is chosen by `--scope`, not by where you stand or by a path you pass.
59
61
 
60
62
  - **Default (`--scope=user`) — run it from anywhere.** The current directory is
61
- 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)
62
65
  and is available across **all** your projects. This is the normal usage: a skill
63
66
  is editor/agent tooling, not part of any one app's source.
64
67
 
@@ -68,7 +71,9 @@ is chosen by `--scope`, not by where you stand or by a path you pass.
68
71
  `./.claude/skills/` or `./.cursor/skills/`; the MCP config goes to `./.mcp.json`
69
72
  for Claude Code (its project-scope convention, not a file under `.claude/`) and
70
73
  to `./.cursor/mcp.json` for Cursor. Use this to commit the skill with a specific
71
- 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.
72
77
 
73
78
  ```bash
74
79
  # normal — anywhere, global for every project
@@ -85,8 +90,9 @@ Note: a bare path such as `npx create-restforge-skills .` is **not** recognized
85
90
  ### Options
86
91
 
87
92
  ```bash
88
- npx create-restforge-skills --client=cursor # one client only
89
- 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
90
96
  npx create-restforge-skills --mcp-command=global # use the installed restforge-mcp binary instead of npx
91
97
  npx create-restforge-skills --no-mcp # skill only; you manage MCP yourself
92
98
  npx create-restforge-skills --dry-run # preview, write nothing
@@ -118,7 +124,9 @@ so the update touches only the skill and leaves the MCP config alone.
118
124
  | Claude Code | user (default) | `~/.claude/skills/restforge/` | `~/.claude.json` |
119
125
  | Claude Code | project | `./.claude/skills/restforge/` | `./.mcp.json` |
120
126
  | Cursor | user (default) | `~/.cursor/skills/restforge/` | `~/.cursor/mcp.json` |
121
- | 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` |
122
130
 
123
131
  Note the asymmetry on the project row: Claude Code reads a project-scope MCP
124
132
  server from `./.mcp.json` in the repo root, so that is where the installer writes
@@ -127,14 +135,53 @@ it — not into `./.claude/`.
127
135
  ### Manual install (no CLI)
128
136
 
129
137
  The skill folder is self-contained — copy `skills/restforge/` (including
130
- `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
131
140
  `{ "mcpServers": { "restforge": { "command": "npx", "args": ["-y", "@restforgejs/mcp-server"] } } }`
132
141
  to the client's MCP config.
133
142
 
134
- ### Gemini CLI / OpenAI Codex
135
-
136
- Planned. Both consume the same `skills/restforge/` folder; only the skills
137
- directory path and MCP config file differ per client.
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.
138
185
 
139
186
  ## Developing and releasing
140
187
 
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,12 +1,13 @@
1
1
  {
2
2
  "name": "create-restforge-skills",
3
- "version": "0.4.0",
4
- "description": "Install the RESTForge Agent Skill into Claude Code, Cursor, and other skills-compatible clients.",
3
+ "version": "1.0.0",
4
+ "description": "Install the RESTForge Agent Skill and MCP server configuration into Claude Code, Cursor, and OpenAI Codex.",
5
5
  "type": "commonjs",
6
6
  "bin": {
7
7
  "create-restforge-skills": "cli/index.js"
8
8
  },
9
9
  "scripts": {
10
+ "test": "node --test",
10
11
  "audit-references": "node scripts/audit-references.js"
11
12
  },
12
13
  "files": [
@@ -23,11 +24,15 @@
23
24
  "skill",
24
25
  "claude-code",
25
26
  "cursor",
27
+ "codex",
26
28
  "mcp"
27
29
  ],
28
30
  "author": {
29
31
  "name": "RESTForge",
30
32
  "url": "https://restforge.dev"
31
33
  },
32
- "license": "MIT"
34
+ "license": "MIT",
35
+ "dependencies": {
36
+ "@iarna/toml": "2.2.5"
37
+ }
33
38
  }
@@ -56,8 +56,10 @@ The platform exposes its capabilities as MCP tools grouped by domain: `health_*`
56
56
 
57
57
  Verify readiness before planning or producing anything:
58
58
 
59
- 1. **Are the RESTForge MCP tools present?** If `codegen_*` / `designer_*` are not
60
- in your available tools, the MCP server is **not active**. Stop and tell the
59
+ 1. **Are the RESTForge MCP tools present?** Look for `codegen_*` / `designer_*`,
60
+ including client-prefixed names such as `mcp__restforge__codegen_*`. If the
61
+ client supports deferred tool discovery, search for RESTForge tools first.
62
+ If they remain unavailable, the MCP server is **not active**. Stop and tell the
61
63
  user to register the RESTForge MCP server and restart the client. Do **not**
62
64
  finish the task by hand-reading the bundled `references/` — that bypasses the
63
65
  generator and yields slower, non-deterministic output.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "RESTForge"
3
+ short_description: "Build RESTForge APIs and frontends through MCP"
4
+ default_prompt: "Use $restforge to build or update my RESTForge application."