Skip to content

Commit f4e213f

Browse files
committed
first try of skills and create package
1 parent 1b367be commit f4e213f

29 files changed

Lines changed: 1207 additions & 2 deletions

AGENTS.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## Skills
2+
A skill is a set of local instructions to follow that is stored in a `SKILL.md` file. Below is the list of skills that can be used. Each entry includes a name, description, and file path so you can open the source for full instructions when using a specific skill.
3+
4+
### Available skills
5+
- new-api-guide: Guide users through the APIOps Cycles method to design and scope a new API from business need to publishing and improvement. Use when the user needs help deciding the current station, checking whether entry or exit criteria are met, selecting the right next resource or canvas from the canonical method data, gathering answers for the selected canvas, or moving from method guidance into canvas JSON authoring and export without jumping too early into API design. (file: skills/new-api-guide/SKILL.md)
6+
- canvas-import-json-authoring: Create or review importable CanvasCreator JSON files using schema-first validation, template-specific section coverage, locale-aware section descriptions, and APIOps metadata defaults. Use when generating new filled canvas examples, converting raw notes into import JSON, or validating existing import files before import or export. (file: node_modules/canvascreator/.agents/skills/canvas-import-json-authoring/SKILL.md)
7+
- common-contributor-workflow: Follow the standard CanvasCreator contribution flow for scoping, implementation, validation, docs hygiene, and pull request preparation. Use when working on CanvasCreator package changes or package-bundled skill maintenance. (file: node_modules/canvascreator/.agents/skills/common-contributor-workflow/SKILL.md)
8+
- export-cli-usage-patterns: Create, review, or troubleshoot CanvasCreator export CLI usage for `scripts/export.js` and `canvascreator-export`, including argument patterns, output-file expectations, and format-specific behavior for `json`, `svg`, `pdf`, and `png` exports. (file: node_modules/canvascreator/.agents/skills/export-cli-usage-patterns/SKILL.md)
9+
10+
### How to use skills
11+
- Discovery: The list above is the skills available in this workspace (name + description + file path). Skill bodies live on disk at the listed paths.
12+
- Trigger rules: If the user names a skill with `$SkillName` or plain text, or the task clearly matches a skill's description shown above, use that skill for the turn.
13+
- Missing or blocked: If a named skill is not in the list or the path cannot be read, say so briefly and continue with the best fallback.
14+
- How to use a skill:
15+
1. Open its `SKILL.md`.
16+
2. Read only enough to follow the workflow.
17+
3. Resolve any relative paths from the skill directory first.
18+
4. Load only the specific reference files needed for the request.
19+
- Coordination and sequencing:
20+
1. Use `new-api-guide` to select the correct station and canvas.
21+
2. Use `canvas-import-json-authoring` to create or validate importable canvas JSON.
22+
3. Use `export-cli-usage-patterns` to export or troubleshoot exported artifacts.
23+
- Context hygiene: Keep context small and avoid loading unnecessary reference material.

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
"description": "APIOps Cycles Method data and canvases",
55
"license": "Apache-2.0",
66
"type": "module",
7-
"files": [
7+
"files": [
8+
".agents/skills",
9+
"AGENTS.md",
810
"src/data",
911
"src/snippets",
1012
"src/assets/",
11-
"schemas/"
13+
"schemas/",
14+
"packages/"
1215
],
1316
"exports": {
1417
"./canvasData.json": "./src/data/canvas/canvasData.json",

packages/README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# APIOps Project Scaffold
2+
3+
This package contains a draft scaffold for starting API design work with:
4+
5+
- `apiops-cycles-method-data`
6+
- `canvascreator`
7+
- the `new-api-guide` skill workflow
8+
9+
## What is included
10+
11+
- `create-apiops/`
12+
- a draft `npm create` style scaffolder
13+
- a project template with `docs/`, `specs/`, `src/`, `AGENTS.md`, and starter files
14+
- `package-examples/`
15+
- example `package.json` shapes for:
16+
- `apiops-cycles-method-data`
17+
- `canvascreator`
18+
- a user API project
19+
20+
## How to use this draft
21+
22+
### Option 1: Review the scaffold design
23+
24+
Read:
25+
26+
- `create-apiops/bin/create-apiops-project.js`
27+
- `create-apiops/template/package.json`
28+
- `create-apiops/template/README.md`
29+
- `create-apiops/template/AGENTS.md`
30+
31+
This is useful if you want to implement the scaffolder in a proper repo later.
32+
33+
### Option 2: Use the template manually
34+
35+
1. Copy the contents of `create-apiops/template/` into a new API project folder.
36+
2. Edit `package.json`, `README.md`, and `specs/openapi/api.yaml` to replace placeholders.
37+
3. Run `npm install`.
38+
4. Add your canvases under `specs/canvases/`.
39+
5. Add your OpenAPI files under `specs/openapi/`.
40+
6. Export reviewable SVGs into `docs/api/...`.
41+
42+
## Recommended project structure
43+
44+
- `specs/` = version-controlled source-of-truth artifacts
45+
- `docs/` = rendered review material
46+
- `src/` = implementation
47+
48+
Suggested layout:
49+
50+
- `specs/canvases/`
51+
- `specs/openapi/`
52+
- `specs/audit/`
53+
- `docs/api/strategy/`
54+
- `docs/api/architecture/`
55+
- `docs/api/design/`
56+
- `docs/api/delivery/`
57+
- `docs/api/audit/`
58+
- `docs/api/publishing/`
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/usr/bin/env node
2+
import fs from "node:fs";
3+
import path from "node:path";
4+
import { fileURLToPath } from "node:url";
5+
import readline from "node:readline";
6+
import { spawnSync } from "node:child_process";
7+
8+
const __filename = fileURLToPath(import.meta.url);
9+
const __dirname = path.dirname(__filename);
10+
const templateDir = path.resolve(__dirname, "..", "template");
11+
12+
function ask(rl, question, fallback = "") {
13+
return new Promise((resolve) => {
14+
rl.question(
15+
fallback ? `${question} (${fallback}): ` : `${question}: `,
16+
(answer) => resolve(answer.trim() || fallback),
17+
);
18+
});
19+
}
20+
21+
function copyDir(src, dest) {
22+
fs.mkdirSync(dest, { recursive: true });
23+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
24+
const srcPath = path.join(src, entry.name);
25+
const destPath = path.join(dest, entry.name);
26+
if (entry.isDirectory()) {
27+
copyDir(srcPath, destPath);
28+
} else {
29+
fs.copyFileSync(srcPath, destPath);
30+
}
31+
}
32+
}
33+
34+
function replaceInFile(filePath, replacements) {
35+
let content = fs.readFileSync(filePath, "utf8");
36+
for (const [from, to] of Object.entries(replacements)) {
37+
content = content.replaceAll(from, to);
38+
}
39+
fs.writeFileSync(filePath, content);
40+
}
41+
42+
function getScripts(locale, apiStyle) {
43+
const base = {
44+
"method:stations": `node ./node_modules/apiops-cycles-method-data/.agents/skills/new-api-guide/scripts/get-core-stations.cjs ${locale}`,
45+
"method:resource:audit": `node ./node_modules/apiops-cycles-method-data/.agents/skills/new-api-guide/scripts/get-resource-metadata.cjs api-audit-checklist ${locale}`
46+
};
47+
48+
if (apiStyle === "REST" || apiStyle === "Not sure yet") {
49+
base["method:canvas:rest"] =
50+
`node ./node_modules/apiops-cycles-method-data/.agents/skills/new-api-guide/scripts/get-canvas-metadata.cjs restCanvas ${locale}`;
51+
}
52+
if (apiStyle === "Event" || apiStyle === "Not sure yet") {
53+
base["method:canvas:event"] =
54+
`node ./node_modules/apiops-cycles-method-data/.agents/skills/new-api-guide/scripts/get-canvas-metadata.cjs eventCanvas ${locale}`;
55+
}
56+
if (apiStyle === "GraphQL" || apiStyle === "Not sure yet") {
57+
base["method:canvas:graphql"] =
58+
`node ./node_modules/apiops-cycles-method-data/.agents/skills/new-api-guide/scripts/get-canvas-metadata.cjs graphqlCanvas ${locale}`;
59+
}
60+
61+
return base;
62+
}
63+
64+
function createStarterCanvas(targetDir, locale = "en", canvasId = "domainCanvas") {
65+
const canvasDataPath = path.join(
66+
targetDir,
67+
"node_modules",
68+
"apiops-cycles-method-data",
69+
"canvasData.json"
70+
);
71+
72+
if (!fs.existsSync(canvasDataPath)) {
73+
return;
74+
}
75+
76+
const canvasData = JSON.parse(fs.readFileSync(canvasDataPath, "utf8"));
77+
const canvas = canvasData[canvasId];
78+
79+
if (!canvas) {
80+
return;
81+
}
82+
83+
const starter = {
84+
templateId: canvasId,
85+
locale,
86+
metadata: {
87+
source: "APIOps Cycles method",
88+
license: "CC-BY-SA 4.0",
89+
authors: ["Project team"],
90+
website: "www.apiopscycles.com",
91+
date: new Date().toISOString()
92+
},
93+
sections: canvas.sections.map((section) => ({
94+
sectionId: section.id,
95+
stickyNotes: [
96+
{
97+
content: "Placeholder",
98+
size: 80,
99+
color: "#FFF399"
100+
}
101+
]
102+
}))
103+
};
104+
105+
const outPath = path.join(targetDir, "specs", "canvases", "example.json");
106+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
107+
fs.writeFileSync(outPath, `${JSON.stringify(starter, null, 2)}\n`);
108+
}
109+
110+
async function main() {
111+
const rl = readline.createInterface({
112+
input: process.stdin,
113+
output: process.stdout
114+
});
115+
116+
const projectName = await ask(rl, "Project name", "my-api-project");
117+
const locale = await ask(rl, "Default locale", "en");
118+
const apiStyle = await ask(rl, "API style focus [REST/Event/GraphQL/Not sure yet]", "REST");
119+
const installNow = await ask(rl, "Install dependencies now? [yes/no]", "yes");
120+
rl.close();
121+
122+
const targetDir = path.resolve(process.cwd(), projectName);
123+
if (fs.existsSync(targetDir)) {
124+
console.error(`Target already exists: ${targetDir}`);
125+
process.exit(1);
126+
}
127+
128+
copyDir(templateDir, targetDir);
129+
130+
const replacements = {
131+
"__PROJECT_NAME__": projectName,
132+
"__LOCALE__": locale,
133+
"__API_TITLE__": projectName.replace(/[-_]/g, " ")
134+
};
135+
136+
replaceInFile(path.join(targetDir, "README.md"), replacements);
137+
replaceInFile(path.join(targetDir, "specs", "openapi", "api.yaml"), replacements);
138+
139+
const packageJsonPath = path.join(targetDir, "package.json");
140+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
141+
pkg.name = projectName;
142+
pkg.scripts = {
143+
...pkg.scripts,
144+
...getScripts(locale, apiStyle)
145+
};
146+
fs.writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`);
147+
148+
console.log(`Created ${projectName}`);
149+
150+
if (installNow.toLowerCase() === "yes") {
151+
const result = spawnSync("npm", ["install"], {
152+
cwd: targetDir,
153+
stdio: "inherit",
154+
shell: true
155+
});
156+
if (result.status !== 0) {
157+
console.error("npm install failed");
158+
process.exit(result.status || 1);
159+
}
160+
161+
createStarterCanvas(targetDir, locale, "domainCanvas");
162+
} else {
163+
console.log("\nStarter canvas was not generated yet.");
164+
console.log("Run `npm install` first, then regenerate it with the scaffolder or a helper command.");
165+
}
166+
167+
console.log("\nNext steps:");
168+
console.log(` cd ${projectName}`);
169+
console.log(" npm run method:stations");
170+
}
171+
172+
main().catch((err) => {
173+
console.error(err);
174+
process.exit(1);
175+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "create-apiops",
3+
"version": "0.1.0",
4+
"type": "module",
5+
"bin": {
6+
"create-apiops": "./bin/create-apiops-project.js"
7+
}
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
dist/
3+
coverage/
4+
*.log
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Skills
2+
A skill is a set of local instructions to follow that is stored in a `SKILL.md` file.
3+
4+
### Available skills
5+
- new-api-guide: Guide users through the APIOps Cycles method to design and scope a new API from business need to publishing and improvement. (file: node_modules/apiops-cycles-method-data/.agents/skills/new-api-guide/SKILL.md)
6+
- canvas-import-json-authoring: Create or review importable CanvasCreator JSON files. (file: node_modules/canvascreator/.agents/skills/canvas-import-json-authoring/SKILL.md)
7+
- export-cli-usage-patterns: Create, review, or troubleshoot CanvasCreator export CLI usage. (file: node_modules/canvascreator/.agents/skills/export-cli-usage-patterns/SKILL.md)
8+
9+
### How to use skills
10+
- Open the listed `SKILL.md`
11+
- Load only the needed references
12+
- Prefer package-provided scripts and snippets over custom reinvention
13+
- Keep project outputs in `specs/` and `docs/`
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# __API_TITLE__
2+
3+
This project uses APIOps Cycles method tooling to design, review, implement, audit, publish, and improve APIs.
4+
5+
## Structure
6+
7+
- `specs/canvases/` = source canvas JSON files
8+
- `specs/openapi/` = source OpenAPI contracts
9+
- `specs/audit/` = audit reviews and checklists
10+
- `docs/api/` = rendered SVGs and human-readable outputs
11+
- `src/` = implementation
12+
13+
## Install
14+
15+
```bash
16+
npm install
17+
```
18+
19+
## Useful commands
20+
21+
```bash
22+
npm run method:stations
23+
npm run method:criteria:design
24+
npm run method:resource:audit
25+
```
26+
27+
## Notes
28+
29+
- Keep source artifacts version controlled
30+
- Treat `specs/` as source of truth
31+
- Treat `docs/` as rendered review material
32+
- Default locale: `__LOCALE__`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)