x402-engineer 0.1.1 → 0.1.3

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": "x402-engineer",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Claude Code skill pack for adding x402 micropayments to any API endpoint",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob]
9
9
 
10
10
  # /x402:init
11
11
 
12
- > Bootstrap x402 payment protection in your project. I'll detect your framework, install the right packages, and scaffold all config files.
12
+ > Bootstrap x402 payment protection in your project. Works with existing projects (brownfield) or creates a new project from scratch (greenfield). I'll detect your framework, install the right packages, and scaffold all config files.
13
13
 
14
14
  ## Important Rules
15
15
 
@@ -17,6 +17,64 @@ allowed-tools: [Read, Write, Edit, Bash, Grep, Glob]
17
17
  - Server-side `ExactStellarScheme` import path is always `@x402/stellar/exact/server` (NOT `@x402/stellar/exact/client`).
18
18
  - All templates are in this skill's `templates/` directory. Read the template file and use its content as the basis for generated code.
19
19
  - Adapt import paths if needed based on project structure (e.g., relative paths based on file placement).
20
+ - For Next.js greenfield projects, ALWAYS delegate to create-next-app. Do NOT scaffold Next.js manually.
21
+ - Greenfield templates are in this skill's `templates/greenfield/` directory.
22
+
23
+ ## Step 0 -- Detect Greenfield Project (Conditional)
24
+
25
+ Before anything else, determine if this is a greenfield (new/empty) project:
26
+
27
+ 1. **Check for package.json:** Use Read to check if `package.json` exists in the current working directory
28
+ 2. **If package.json exists:** Check if any supported framework (`next`, `express`, `fastify`, `hono`) appears in `dependencies`. If a framework IS found, this is a brownfield project -- skip to Step 1.
29
+ 3. **If no package.json OR no framework in dependencies:** This is a greenfield project. Continue below.
30
+
31
+ ### Greenfield: Verify Empty Directory
32
+
33
+ Before scaffolding, verify the directory is safe to scaffold into:
34
+
35
+ 1. Use Bash to list directory contents: `ls -A`
36
+ 2. **Allowed trivial files:** `.git`, `.gitignore`, `CLAUDE.md`, `.claude/`, `README.md`, `.planning/`
37
+ 3. If the directory contains files OTHER than the trivial list above, warn the user:
38
+ `"Directory is not empty. Found: {non-trivial files}. Greenfield scaffolding expects an empty directory. Continue anyway? (The existing files will be preserved, but conflicts may occur.)"`
39
+ Wait for user confirmation before proceeding. If the user says no, STOP.
40
+
41
+ ### Greenfield: Select Framework
42
+
43
+ 1. **If `$ARGUMENTS` provides a framework** (e.g., `/x402:init express`), use that framework directly. Valid values: `nextjs`, `next`, `express`, `fastify`, `hono`. Normalize `nextjs`/`next` to Next.js.
44
+ 2. **If no argument provided**, ask the user:
45
+ ```
46
+ No framework detected. Which framework would you like to use?
47
+
48
+ 1. Express (default -- simplest for API-only)
49
+ 2. Fastify
50
+ 3. Hono
51
+ 4. Next.js (full-stack with App Router)
52
+
53
+ Enter choice (1-4) or framework name:
54
+ ```
55
+ If the user just presses enter or says "default", use Express.
56
+
57
+ ### Greenfield: Scaffold Project
58
+
59
+ **For Next.js:**
60
+
61
+ 1. Output: `"Scaffolding Next.js project with create-next-app..."`
62
+ 2. Run via Bash: `npx create-next-app@latest . --typescript --app --yes`
63
+ 3. Wait for completion. If it fails (e.g., directory not empty), report the error and STOP.
64
+ 4. Output: `"Next.js project created. Continuing with x402 setup..."`
65
+ 5. Skip to Step 1 (the brownfield flow handles everything from here).
66
+
67
+ **For Express / Fastify / Hono:**
68
+
69
+ 1. Output: `"Scaffolding {Framework} project..."`
70
+ 2. Read `templates/greenfield/{framework}/package.json.md` -- extract JSON from code block, write to `./package.json`
71
+ 3. Read `templates/greenfield/{framework}/tsconfig.json.md` -- extract JSON from code block, write to `./tsconfig.json`
72
+ 4. Create `src/` directory via Bash: `mkdir -p src`
73
+ 5. Read `templates/greenfield/{framework}/server.ts.md` -- extract TypeScript from code block, write to `./src/server.ts`
74
+ 6. Run via Bash: `npm install`
75
+ 7. Output: `"Project scaffolded. Created 3 files: package.json, tsconfig.json, src/server.ts"`
76
+ 8. Output: `"Continuing with x402 setup..."`
77
+ 9. Continue to Step 1 (the existing brownfield flow picks up from here -- it will detect the framework from the newly created package.json).
20
78
 
21
79
  ## Step 1 -- Check for Existing x402 Setup (Idempotency)
22
80
 
@@ -50,7 +108,7 @@ Report which pieces are already present. Skip those. Only create the missing pie
50
108
 
51
109
  **Edge cases:**
52
110
  - If `@nestjs/core` is found in dependencies, warn: `"NestJS detected, using underlying Express/Fastify adapter"` and detect which underlying framework NestJS uses (check for `@nestjs/platform-express` or `@nestjs/platform-fastify`)
53
- - If no supported framework is detected, output: `"Could not detect framework from package.json. Supported: Next.js, Express, Fastify, Hono."` and STOP
111
+ - If no supported framework is detected AND Step 0 was skipped (package.json exists but has no framework): output `"Could not detect framework from package.json. Supported: Next.js, Express, Fastify, Hono."` and STOP
54
112
 
55
113
  ## Step 3 -- Detect Project Structure
56
114
 
@@ -90,7 +148,6 @@ Run the framework-specific install command via Bash:
90
148
  6. Check if `.env.example` already exists at the project root:
91
149
  - If it does NOT exist: create `.env.example` with the template content
92
150
  - If it DOES exist: check if it already contains `SERVER_STELLAR_ADDRESS`. If not, append the x402 section to the existing file
93
- 7. Output: `"Created .env.example with required variables. Copy to .env.local and fill in your values."`
94
151
 
95
152
  ## Step 6 -- Scaffold Server/Middleware Files
96
153
 
@@ -103,7 +160,94 @@ Run the framework-specific install command via Bash:
103
160
  5. Extract the TypeScript code from the template's fenced code block
104
161
  6. Write to `{base_dir}/x402/adapter.ts`
105
162
 
106
- ## Step 7 -- Summary
163
+ ## Step 7 -- Configure Environment (Interactive)
164
+
165
+ Guide the user through setting up `.env.local` with the required values. Check if `.env.local` already exists and has values before prompting.
166
+
167
+ ### 7a -- Check existing .env.local
168
+
169
+ 1. Use Read to check if `.env.local` exists
170
+ 2. If it exists and already contains `SERVER_STELLAR_ADDRESS` with a non-empty value, output:
171
+ `"Environment already configured in .env.local. Skipping setup."`
172
+ Skip to Step 8.
173
+
174
+ ### 7b -- SERVER_STELLAR_ADDRESS
175
+
176
+ Output the following explanation:
177
+
178
+ ```
179
+ To receive payments, you need a Stellar account address.
180
+ This is a public key that starts with "G" (56 characters).
181
+
182
+ How to get one:
183
+ 1. Go to https://laboratory.stellar.org/#account-creator?network=test
184
+ 2. Click "Generate Keypair"
185
+ 3. Save both keys -- you'll use the Public Key (G...) here
186
+ 4. Click "Fund account on testnet" to get test XLM
187
+
188
+ If you already have a Stellar address, paste it below.
189
+ ```
190
+
191
+ Ask the user for the value. Accept any input that:
192
+ - Starts with `G` and is 56 characters long
193
+ - OR is empty (user wants to skip for now)
194
+
195
+ If the user provides an invalid format, warn once: `"Stellar addresses start with G and are 56 characters. This doesn't look right, but I'll use it anyway."` and proceed.
196
+
197
+ If the user skips (empty), set `SERVER_STELLAR_ADDRESS=` (empty value).
198
+
199
+ ### 7c -- FACILITATOR_API_KEY
200
+
201
+ Output the following explanation:
202
+
203
+ ```
204
+ The facilitator is a service (by OpenZeppelin) that verifies and settles
205
+ x402 payments on your behalf. You need an API key to use it.
206
+
207
+ How to get one:
208
+ 1. Go to https://channels.openzeppelin.com/testnet/gen
209
+ 2. Generate a new API key
210
+ 3. Paste it below
211
+
212
+ This takes ~30 seconds. I'll wait.
213
+ ```
214
+
215
+ Ask the user for the value. Accept any non-empty string, or empty to skip.
216
+
217
+ If the user skips (empty), set `FACILITATOR_API_KEY=` (empty value).
218
+
219
+ ### 7d -- Write .env.local
220
+
221
+ Write `.env.local` with the collected values:
222
+
223
+ ```env
224
+ # x402 Payment Configuration
225
+
226
+ # Stellar public key (G...) that receives USDC payments
227
+ SERVER_STELLAR_ADDRESS={collected_value}
228
+
229
+ # OpenZeppelin facilitator endpoint
230
+ FACILITATOR_URL=https://channels.openzeppelin.com/x402/testnet
231
+
232
+ # API key from https://channels.openzeppelin.com/testnet/gen
233
+ FACILITATOR_API_KEY={collected_value}
234
+ ```
235
+
236
+ **Rules:**
237
+ - Always set `FACILITATOR_URL` to the testnet endpoint (no need to ask -- testnet is the right default for init)
238
+ - If `.env.local` already exists with OTHER variables (not x402-related), append the x402 section. Do not overwrite existing content.
239
+ - Add `.env.local` to `.gitignore` if not already present (check first for idempotency)
240
+
241
+ ### 7e -- Report status
242
+
243
+ If both values were provided:
244
+ `"Environment configured. .env.local is ready."`
245
+
246
+ If one or both were skipped:
247
+ `"Created .env.local with partial configuration. Fill in the missing values before testing:"`
248
+ Then list which variables are still empty.
249
+
250
+ ## Step 8 -- Summary
107
251
 
108
252
  Count the files created during this run and output:
109
253
 
@@ -112,18 +256,20 @@ Count the files created during this run and output:
112
256
  List each file with its relative path from the project root, for example:
113
257
 
114
258
  ```
115
- x402 initialized. Created 3 files:
259
+ x402 initialized. Created 4 files:
116
260
  - lib/x402/config.ts
117
261
  - lib/x402/server.ts
118
262
  - .env.example
263
+ - .env.local
119
264
  ```
120
265
 
121
266
  For Fastify projects, the adapter file is also listed:
122
267
 
123
268
  ```
124
- x402 initialized. Created 4 files:
269
+ x402 initialized. Created 5 files:
125
270
  - lib/x402/config.ts
126
271
  - lib/x402/server.ts
127
272
  - lib/x402/adapter.ts
128
273
  - .env.example
274
+ - .env.local
129
275
  ```
@@ -0,0 +1,24 @@
1
+ # Express Greenfield package.json
2
+
3
+ Minimal package.json for a new Express + TypeScript project.
4
+
5
+ ```json
6
+ {
7
+ "name": "x402-server",
8
+ "version": "0.1.0",
9
+ "type": "module",
10
+ "scripts": {
11
+ "dev": "tsx watch src/server.ts",
12
+ "build": "tsc",
13
+ "start": "node dist/server.js"
14
+ },
15
+ "dependencies": {
16
+ "express": "latest"
17
+ },
18
+ "devDependencies": {
19
+ "@types/express": "latest",
20
+ "tsx": "latest",
21
+ "typescript": "latest"
22
+ }
23
+ }
24
+ ```
@@ -0,0 +1,18 @@
1
+ # Express Greenfield Server
2
+
3
+ Minimal Express server with a single `/api/hello` endpoint.
4
+
5
+ ```typescript
6
+ import express from "express";
7
+
8
+ const app = express();
9
+ const port = process.env.PORT || 3000;
10
+
11
+ app.get("/api/hello", (_req, res) => {
12
+ res.json({ message: "Hello from x402!" });
13
+ });
14
+
15
+ app.listen(port, () => {
16
+ console.log(`Server running on http://localhost:${port}`);
17
+ });
18
+ ```
@@ -0,0 +1,19 @@
1
+ # Express Greenfield tsconfig.json
2
+
3
+ Minimal TypeScript configuration for a new Express project.
4
+
5
+ ```json
6
+ {
7
+ "compilerOptions": {
8
+ "target": "ES2022",
9
+ "module": "Node16",
10
+ "moduleResolution": "Node16",
11
+ "outDir": "dist",
12
+ "rootDir": "src",
13
+ "strict": true,
14
+ "esModuleInterop": true,
15
+ "skipLibCheck": true
16
+ },
17
+ "include": ["src"]
18
+ }
19
+ ```
@@ -0,0 +1,23 @@
1
+ # Fastify Greenfield package.json
2
+
3
+ Minimal package.json for a new Fastify + TypeScript project.
4
+
5
+ ```json
6
+ {
7
+ "name": "x402-server",
8
+ "version": "0.1.0",
9
+ "type": "module",
10
+ "scripts": {
11
+ "dev": "tsx watch src/server.ts",
12
+ "build": "tsc",
13
+ "start": "node dist/server.js"
14
+ },
15
+ "dependencies": {
16
+ "fastify": "latest"
17
+ },
18
+ "devDependencies": {
19
+ "tsx": "latest",
20
+ "typescript": "latest"
21
+ }
22
+ }
23
+ ```
@@ -0,0 +1,22 @@
1
+ # Fastify Greenfield Server
2
+
3
+ Minimal Fastify server with a single `/api/hello` endpoint.
4
+
5
+ ```typescript
6
+ import Fastify from "fastify";
7
+
8
+ const fastify = Fastify();
9
+ const port = Number(process.env.PORT) || 3000;
10
+
11
+ fastify.get("/api/hello", async () => {
12
+ return { message: "Hello from x402!" };
13
+ });
14
+
15
+ fastify.listen({ port, host: "0.0.0.0" }, (err, address) => {
16
+ if (err) {
17
+ console.error(err);
18
+ process.exit(1);
19
+ }
20
+ console.log(`Server running on http://localhost:${port}`);
21
+ });
22
+ ```
@@ -0,0 +1,19 @@
1
+ # Fastify Greenfield tsconfig.json
2
+
3
+ Minimal TypeScript configuration for a new Fastify project.
4
+
5
+ ```json
6
+ {
7
+ "compilerOptions": {
8
+ "target": "ES2022",
9
+ "module": "Node16",
10
+ "moduleResolution": "Node16",
11
+ "outDir": "dist",
12
+ "rootDir": "src",
13
+ "strict": true,
14
+ "esModuleInterop": true,
15
+ "skipLibCheck": true
16
+ },
17
+ "include": ["src"]
18
+ }
19
+ ```
@@ -0,0 +1,24 @@
1
+ # Hono Greenfield package.json
2
+
3
+ Minimal package.json for a new Hono + TypeScript project.
4
+
5
+ ```json
6
+ {
7
+ "name": "x402-server",
8
+ "version": "0.1.0",
9
+ "type": "module",
10
+ "scripts": {
11
+ "dev": "tsx watch src/server.ts",
12
+ "build": "tsc",
13
+ "start": "node dist/server.js"
14
+ },
15
+ "dependencies": {
16
+ "@hono/node-server": "latest",
17
+ "hono": "latest"
18
+ },
19
+ "devDependencies": {
20
+ "tsx": "latest",
21
+ "typescript": "latest"
22
+ }
23
+ }
24
+ ```
@@ -0,0 +1,19 @@
1
+ # Hono Greenfield Server
2
+
3
+ Minimal Hono server with a single `/api/hello` endpoint.
4
+
5
+ ```typescript
6
+ import { Hono } from "hono";
7
+ import { serve } from "@hono/node-server";
8
+
9
+ const app = new Hono();
10
+ const port = Number(process.env.PORT) || 3000;
11
+
12
+ app.get("/api/hello", (c) => {
13
+ return c.json({ message: "Hello from x402!" });
14
+ });
15
+
16
+ serve({ fetch: app.fetch, port }, () => {
17
+ console.log(`Server running on http://localhost:${port}`);
18
+ });
19
+ ```
@@ -0,0 +1,19 @@
1
+ # Hono Greenfield tsconfig.json
2
+
3
+ Minimal TypeScript configuration for a new Hono project.
4
+
5
+ ```json
6
+ {
7
+ "compilerOptions": {
8
+ "target": "ES2022",
9
+ "module": "Node16",
10
+ "moduleResolution": "Node16",
11
+ "outDir": "dist",
12
+ "rootDir": "src",
13
+ "strict": true,
14
+ "esModuleInterop": true,
15
+ "skipLibCheck": true
16
+ },
17
+ "include": ["src"]
18
+ }
19
+ ```