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 +60 -13
- package/cli/codex.js +42 -0
- package/cli/index.js +23 -8
- package/package.json +8 -3
- package/skills/restforge/SKILL.md +4 -2
- package/skills/restforge/agents/openai.yaml +4 -0
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
|
-
│
|
|
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 --
|
|
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
|
|
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
|
-
###
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
*
|
|
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
|
|
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 ~/.
|
|
197
|
-
console.error('Pass one explicitly, e.g. --client=
|
|
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
|
|
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
|
-
|
|
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
|
-
"description": "Install the RESTForge Agent Skill into Claude Code, Cursor, and
|
|
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?**
|
|
60
|
-
|
|
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.
|