ide-agents 0.2.0 → 0.3.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
@@ -121,13 +121,7 @@ npm run docs:install
121
121
  npm run docs:start # http://localhost:3000
122
122
  ```
123
123
 
124
- Fixture repo for manual testing:
125
-
126
- ```bash
127
- cd fixtures/sample-repo && git init && git add . && git commit -m "init"
128
- ```
129
-
130
- Then add `file://$(pwd)` in the UI.
124
+ For local testing, add a `file://` URL to any git repo with skills/agents (see [docs](https://ide-agents.vercel.app/docs/source-repos#local-testing)).
131
125
 
132
126
  ## Data layout
133
127
 
package/dist/git.d.ts CHANGED
@@ -3,4 +3,5 @@ export declare function cloneRepo(url: string, slug: string, ref: string): Promi
3
3
  export declare function fetchRepo(slug: string): Promise<void>;
4
4
  export declare function pullRepo(slug: string): Promise<void>;
5
5
  export declare function getGitStatus(slug: string, ref: string): Promise<GitStatus>;
6
+ export declare function commitAndPushRepo(cwd: string, ref: string): Promise<void>;
6
7
  export declare function getGitStatusWithoutFetch(slug: string, ref: string): Promise<GitStatus>;
package/dist/git.js CHANGED
@@ -130,6 +130,30 @@ export async function getGitStatus(slug, ref) {
130
130
  };
131
131
  }
132
132
  }
133
+ export async function commitAndPushRepo(cwd, ref) {
134
+ if (!(await isGitRepo(cwd))) {
135
+ throw new Error(`Not a git repository: ${cwd}`);
136
+ }
137
+ const status = await runGit(cwd, ["status", "--porcelain"]);
138
+ if (!status.stdout.trim()) {
139
+ return;
140
+ }
141
+ await runGit(cwd, ["add", "-A"]);
142
+ await runGit(cwd, [
143
+ "commit",
144
+ "-m",
145
+ "chore: bootstrap skills catalog from ide-agents template",
146
+ ]);
147
+ try {
148
+ await runGit(cwd, ["push", "origin", ref]);
149
+ }
150
+ catch (err) {
151
+ const message = err instanceof Error ? err.message : String(err);
152
+ throw new Error(`Commit succeeded but push failed: ${message}`, {
153
+ cause: err,
154
+ });
155
+ }
156
+ }
133
157
  export async function getGitStatusWithoutFetch(slug, ref) {
134
158
  const cwd = getRepoPath(slug);
135
159
  if (!(await isGitRepo(cwd))) {
package/dist/server.js CHANGED
@@ -3,6 +3,7 @@ import fastifyStatic from "@fastify/static";
3
3
  import { v4 as uuidv4 } from "uuid";
4
4
  import { addRecentProject, readConfig, writeConfig, } from "./config.js";
5
5
  import { cloneRepo, fetchRepo, getGitStatusWithoutFetch, pullRepo, } from "./git.js";
6
+ import { bootstrapEmptyRepo } from "./template.js";
6
7
  import { applyInstallations } from "./apply.js";
7
8
  import { scanRepoArtifacts } from "./scan.js";
8
9
  import { getArtifactTargets } from "./targets.js";
@@ -99,14 +100,16 @@ export async function createServer(options) {
99
100
  if (config.repos.some((r) => r.id === repoId)) {
100
101
  return reply.status(409).send({ error: `Repository id already exists: ${repoId}` });
101
102
  }
103
+ let repoPath;
102
104
  try {
103
- await cloneRepo(url.trim(), slug, ref);
105
+ repoPath = await cloneRepo(url.trim(), slug, ref);
104
106
  }
105
107
  catch (err) {
106
108
  return reply.status(400).send({
107
109
  error: err instanceof Error ? err.message : String(err),
108
110
  });
109
111
  }
112
+ const bootstrap = await bootstrapEmptyRepo(repoPath, ref);
110
113
  const repo = { id: repoId, url: url.trim(), ref, slug };
111
114
  config.repos.push(repo);
112
115
  await writeConfig(config);
@@ -116,7 +119,10 @@ export async function createServer(options) {
116
119
  ...repo,
117
120
  localPath: getRepoPath(slug),
118
121
  git,
122
+ skillCount: bootstrap.skillCount,
123
+ agentCount: bootstrap.agentCount,
119
124
  },
125
+ bootstrap,
120
126
  };
121
127
  });
122
128
  app.delete("/api/repos/:id", async (request, reply) => {
@@ -130,6 +136,38 @@ export async function createServer(options) {
130
136
  await writeConfig(config);
131
137
  return { ok: true };
132
138
  });
139
+ app.post("/api/repos/:id/bootstrap", async (request, reply) => {
140
+ const config = await readConfig();
141
+ const repo = config.repos.find((r) => r.id === request.params.id);
142
+ if (!repo) {
143
+ return reply.status(404).send({ error: "Repository not found" });
144
+ }
145
+ const repoPath = getRepoPath(repo.slug);
146
+ try {
147
+ const bootstrap = await bootstrapEmptyRepo(repoPath, repo.ref);
148
+ if (!bootstrap.applied) {
149
+ return reply.status(409).send({
150
+ error: "Repository is not empty — bootstrap skipped",
151
+ });
152
+ }
153
+ const git = await getGitStatusWithoutFetch(repo.slug, repo.ref);
154
+ return {
155
+ repo: {
156
+ ...repo,
157
+ localPath: repoPath,
158
+ git,
159
+ skillCount: bootstrap.skillCount,
160
+ agentCount: bootstrap.agentCount,
161
+ },
162
+ bootstrap,
163
+ };
164
+ }
165
+ catch (err) {
166
+ return reply.status(400).send({
167
+ error: err instanceof Error ? err.message : String(err),
168
+ });
169
+ }
170
+ });
133
171
  app.post("/api/repos/:id/fetch", async (request, reply) => {
134
172
  const config = await readConfig();
135
173
  const repo = config.repos.find((r) => r.id === request.params.id);
@@ -0,0 +1,12 @@
1
+ export interface BootstrapResult {
2
+ applied: boolean;
3
+ pushed: boolean;
4
+ pushError?: string;
5
+ skillCount: number;
6
+ agentCount: number;
7
+ }
8
+ export declare function getTemplateDir(): string;
9
+ /** True when the clone has no installable artifacts and no custom content. */
10
+ export declare function isEmptySkillRepo(repoPath: string): Promise<boolean>;
11
+ export declare function applyTemplateToRepo(repoPath: string): Promise<void>;
12
+ export declare function bootstrapEmptyRepo(repoPath: string, ref: string): Promise<BootstrapResult>;
@@ -0,0 +1,86 @@
1
+ import { cp, readdir, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { commitAndPushRepo } from "./git.js";
5
+ import { scanRepoArtifacts } from "./scan.js";
6
+ const GITHUB_INIT_FILES = new Set([
7
+ "README.md",
8
+ "LICENSE",
9
+ "LICENSE.md",
10
+ "LICENSE.txt",
11
+ ".gitignore",
12
+ ]);
13
+ export function getTemplateDir() {
14
+ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
15
+ return path.resolve(moduleDir, "../template");
16
+ }
17
+ async function pathExists(filePath) {
18
+ try {
19
+ await stat(filePath);
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ /** True when the clone has no installable artifacts and no custom content. */
27
+ export async function isEmptySkillRepo(repoPath) {
28
+ const artifacts = await scanRepoArtifacts(repoPath);
29
+ if (artifacts.length > 0) {
30
+ return false;
31
+ }
32
+ const entries = await readdir(repoPath, { withFileTypes: true });
33
+ for (const entry of entries) {
34
+ if (entry.name === ".git") {
35
+ continue;
36
+ }
37
+ if (entry.isDirectory()) {
38
+ return false;
39
+ }
40
+ if (!GITHUB_INIT_FILES.has(entry.name)) {
41
+ return false;
42
+ }
43
+ }
44
+ return true;
45
+ }
46
+ export async function applyTemplateToRepo(repoPath) {
47
+ const templateDir = getTemplateDir();
48
+ if (!(await pathExists(templateDir))) {
49
+ throw new Error(`Template directory not found: ${templateDir}`);
50
+ }
51
+ const entries = await readdir(templateDir, { withFileTypes: true });
52
+ for (const entry of entries) {
53
+ const src = path.join(templateDir, entry.name);
54
+ const dest = path.join(repoPath, entry.name);
55
+ await cp(src, dest, { recursive: true, force: true });
56
+ }
57
+ }
58
+ export async function bootstrapEmptyRepo(repoPath, ref) {
59
+ if (!(await isEmptySkillRepo(repoPath))) {
60
+ const artifacts = await scanRepoArtifacts(repoPath);
61
+ return {
62
+ applied: false,
63
+ pushed: false,
64
+ skillCount: artifacts.filter((a) => a.kind === "skill").length,
65
+ agentCount: artifacts.filter((a) => a.kind === "agent").length,
66
+ };
67
+ }
68
+ await applyTemplateToRepo(repoPath);
69
+ let pushed = false;
70
+ let pushError;
71
+ try {
72
+ await commitAndPushRepo(repoPath, ref);
73
+ pushed = true;
74
+ }
75
+ catch (err) {
76
+ pushError = err instanceof Error ? err.message : String(err);
77
+ }
78
+ const artifacts = await scanRepoArtifacts(repoPath);
79
+ return {
80
+ applied: true,
81
+ pushed,
82
+ pushError,
83
+ skillCount: artifacts.filter((a) => a.kind === "skill").length,
84
+ agentCount: artifacts.filter((a) => a.kind === "agent").length,
85
+ };
86
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ide-agents",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Local admin for IDE agents and skills from git repos",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "dist",
11
+ "template",
11
12
  "web/dist",
12
13
  "LICENSE",
13
14
  "README.md"
@@ -23,7 +24,9 @@
23
24
  "start": "node dist/cli.js",
24
25
  "docs:install": "npm install --prefix docs",
25
26
  "docs:start": "npm --prefix docs start",
26
- "docs:build": "npm --prefix docs run build"
27
+ "docs:build": "npm --prefix docs run build",
28
+ "lint": "eslint .",
29
+ "lint:fix": "eslint . --fix"
27
30
  },
28
31
  "engines": {
29
32
  "node": ">=20"
@@ -56,6 +59,7 @@
56
59
  "uuid": "^11.1.0"
57
60
  },
58
61
  "devDependencies": {
62
+ "@eslint/js": "^10.0.1",
59
63
  "@mantine/core": "^9.2.2",
60
64
  "@mantine/hooks": "^9.2.2",
61
65
  "@tabler/icons-react": "^3.44.0",
@@ -64,6 +68,9 @@
64
68
  "@types/react-dom": "^19.2.3",
65
69
  "@vitejs/plugin-react": "^6.0.2",
66
70
  "concurrently": "^9.1.2",
71
+ "eslint": "^10.4.1",
72
+ "eslint-plugin-react-hooks": "^7.1.1",
73
+ "globals": "^16.5.0",
67
74
  "postcss": "^8.5.15",
68
75
  "postcss-preset-mantine": "^1.18.0",
69
76
  "postcss-simple-vars": "^7.0.1",
@@ -72,6 +79,7 @@
72
79
  "react-router-dom": "^7.3.0",
73
80
  "tsx": "^4.19.3",
74
81
  "typescript": "^5.8.2",
82
+ "typescript-eslint": "^8.60.0",
75
83
  "vite": "^8.0.14"
76
84
  }
77
85
  }
@@ -0,0 +1,51 @@
1
+ # Codex — repository guide
2
+
3
+ This repository holds **Agent Skills** and **agents** consumed by ide-agents.
4
+
5
+ ## Expected layout
6
+
7
+ ```
8
+ skills/<skill-id>/
9
+ ├── SKILL.md
10
+ ├── scripts/ # optional — *.mjs generators (stdlib, ESM)
11
+ └── assets/ # optional — JSON config for scripts
12
+ agents/<agent-id>.md
13
+ ```
14
+
15
+ ## SKILL.md
16
+
17
+ Required frontmatter:
18
+
19
+ ```yaml
20
+ ---
21
+ name: skill-id
22
+ description: Short summary for the UI.
23
+ scope: any
24
+ ---
25
+ ```
26
+
27
+ Project installs symlink into `<project>/.agents/skills/<name>`.
28
+
29
+ ## Agents
30
+
31
+ Markdown files in `agents/<agent-id>.md`. Required frontmatter:
32
+
33
+ ```yaml
34
+ ---
35
+ name: agent-id # must match filename stem
36
+ description: When the IDE should delegate to this subagent.
37
+ scope: any # optional — ide-agents install toggles
38
+ ---
39
+ ```
40
+
41
+ Project installs use `.agents/agents/<name>.md`.
42
+
43
+ Agents define **role and workflow** only. Repeatable generators (stack detection, audits, structured reports) go in `skills/<skill-id>/scripts/` — agents invoke `node <SKILL_DIR>/scripts/….mjs` instead of improvising the same logic in chat. Pattern: [repo-audit-skills](https://github.com/sergeychernov/repo-audit-skills).
44
+
45
+ ## Editing rules
46
+
47
+ - Do not flatten skills to repo root unless you intentionally use the flat layout (ide-agents detects nested `skills/` first).
48
+ - Preserve skill folder names — they become installation ids.
49
+ - Push to git after changes so remote catalogs stay in sync.
50
+
51
+ See `README.md` for usage with ide-agents.
@@ -0,0 +1,37 @@
1
+ # Claude Code — repository guide
2
+
3
+ This repo is a **skills and agents catalog** for ide-agents.
4
+
5
+ ## Layout
6
+
7
+ - `skills/<name>/SKILL.md` — skills with YAML frontmatter (`name`, `description`, `scope`)
8
+ - `skills/<name>/scripts/` — optional Node `.mjs` generators (stable scans, JSON reports)
9
+ - `skills/<name>/assets/` — optional JSON/markers scripts read
10
+ - `agents/<name>.md` — subagent orchestrators; frontmatter `name`, `description`, optional `scope`
11
+
12
+ ## Agents and scripts
13
+
14
+ Do **not** implement multi-step repo scanners or report generators inline in agent markdown. Put them in `skills/<skill-id>/scripts/` and have agents run:
15
+
16
+ ```bash
17
+ node <SKILL_DIR>/scripts/<script>.mjs
18
+ ```
19
+
20
+ Then read stdout (`--json`) or documented output files. See repo-audit-skills for reference (`detect-stack.mjs`, `run-audit.mjs`).
21
+
22
+ ## When editing
23
+
24
+ - Keep one skill per folder; the folder name is the skill id.
25
+ - Use `scope: any` unless the skill must be global-only or project-only.
26
+ - Write instructions in the skill body, not only in frontmatter.
27
+ - Commit meaningful changes; ide-agents symlinks from the cloned copy under `~/.ide-agents/repos/`.
28
+
29
+ ## Scope values
30
+
31
+ | Value | Meaning |
32
+ |-------|---------|
33
+ | `global` | Install only to user config (`~/.claude/`) |
34
+ | `project` | Install only to project `.claude/` |
35
+ | `any` | User chooses global or project in the UI |
36
+
37
+ See `README.md` for the full catalog overview.
@@ -0,0 +1,72 @@
1
+ ---
2
+ description: Agent authoring — orchestration, reports, and script-backed generators
3
+ globs: agents/**/*.md
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Agent authoring
8
+
9
+ Agents in `agents/*.md` are **orchestrators**: they define role, workflow, and output format. They are not a place for ad-hoc code generation.
10
+
11
+ ## Generators → `scripts/`
12
+
13
+ For anything that must be **stable, repeatable, and testable** (scanners, profile builders, report writers, stack detectors), put logic in bundled scripts under the **related skill folder**:
14
+
15
+ ```
16
+ skills/<skill-id>/
17
+ ├── SKILL.md
18
+ ├── scripts/ # node *.mjs — run these, do not re-implement in chat
19
+ └── assets/ # optional JSON/markers the scripts read
20
+ ```
21
+
22
+ Pattern from [repo-audit-skills](https://github.com/sergeychernov/repo-audit-skills):
23
+
24
+ - `skills/audit-init/scripts/detect-stack.mjs` — read-only scan, writes structured JSON
25
+ - `skills/audit-debt/scripts/run-audit.mjs` — reads profile, runs checks, writes report
26
+
27
+ ### Why agents call scripts
28
+
29
+ | In chat (avoid) | In `scripts/` (prefer) |
30
+ |-----------------|------------------------|
31
+ | Re-parsing repo layout each turn | Same repo state → same output |
32
+ | Drifting flags and file paths | Documented CLI in script header |
33
+ | Large inline bash one-liners | `#!/usr/bin/env node`, ESM `.mjs` |
34
+
35
+ Agent body should tell the model to **resolve `<SKILL_DIR>`**, run `node <SKILL_DIR>/scripts/<name>.mjs`, then **read the artifact** (stdout JSON or a known output path). See `scripts.mdc` for script conventions.
36
+
37
+ ## Agent file format
38
+
39
+ YAML frontmatter (filename stem must match `name`, e.g. `agents/oracle.md` → `name: oracle`):
40
+
41
+ ```yaml
42
+ ---
43
+ name: my-agent # required — lowercase id; Cursor subagent identity (/my-agent)
44
+ description: When to delegate to this subagent. Be specific — the IDE uses this for auto-delegation.
45
+ scope: any # optional — ide-agents only: global | project | any (default any)
46
+ ---
47
+ ```
48
+
49
+ | Field | Required | Used by |
50
+ |-------|----------|---------|
51
+ | `name` | yes | Cursor / Claude / Codex subagent id (defaults to filename if omitted — prefer explicit) |
52
+ | `description` | yes | IDE delegation — when the main agent should hand off to this subagent |
53
+ | `scope` | no | ide-agents UI — which install toggles are enabled |
54
+
55
+ Subagents are **not** skills: they live in `agents/*.md`, install to `~/.cursor/agents/`, and are invoked by name in Agent mode (e.g. `/oracle …` or “use the oracle subagent”), not via the `/` skill picker.
56
+
57
+ Body structure:
58
+
59
+ 1. **Role** — one paragraph
60
+ 2. **Inputs** — what the user or upstream skill must provide
61
+ 3. **Workflow** — numbered steps; step that runs a script must include the exact `node …mjs` command
62
+ 4. **Output contract** — fixed sections (e.g. summary, findings, gaps); use consistent severity markers if reporting issues
63
+
64
+ ## Do not
65
+
66
+ - Embed multi-step filesystem scans or JSON schema logic in the agent markdown
67
+ - Write into the target project except paths documented by the skill (e.g. `.audit/`)
68
+ - Duplicate script behavior in prose — link to `SKILL.md` quick start instead
69
+
70
+ ## Shared helpers
71
+
72
+ Cross-skill utilities may live in `skills/_shared/` (e.g. `generated-by.mjs`). Import from scripts via relative paths; agents reference the skill that owns the script.
@@ -0,0 +1,46 @@
1
+ ---
2
+ description: Skills and agents repository layout for ide-agents catalogs
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Repository structure
7
+
8
+ This repository is an **ide-agents skill catalog** — not an application codebase.
9
+
10
+ ## Directories
11
+
12
+ | Path | Purpose |
13
+ |------|---------|
14
+ | `skills/<id>/SKILL.md` | Installable skills (required `SKILL.md` per folder) |
15
+ | `skills/<id>/scripts/` | Optional bundled generators (`*.mjs`) — see `scripts.mdc` |
16
+ | `skills/<id>/assets/` | Optional JSON/markers read by scripts |
17
+ | `skills/_shared/` | Optional cross-skill helpers (imported by scripts) |
18
+ | `agents/<id>.md` | Subagent orchestrators — call scripts, do not re-implement generators |
19
+ | `.cursor/rules/` | Cursor project rules (this file) |
20
+
21
+ ## SKILL.md conventions
22
+
23
+ - YAML frontmatter: `name`, `description`, `scope` (`global`, `project`, or `any`).
24
+ - Body: instructions the IDE agent follows when the skill is invoked.
25
+ - One skill per directory under `skills/`.
26
+
27
+ ## Agents
28
+
29
+ - One markdown file per agent in `agents/` (e.g. `agents/oracle.md`).
30
+ - YAML frontmatter: `name`, `description`, optional `scope` (`global`, `project`, or `any`).
31
+ - `name` must match the filename stem; used by Cursor/Claude/Codex as the subagent id.
32
+ - Agents **orchestrate**; deterministic generators live in `skills/<id>/scripts/` (see `agents.mdc`).
33
+
34
+ ## Scripts (generators)
35
+
36
+ Stable scanners and report writers belong in `skills/<skill-id>/scripts/`, not inline in agent prompts. Follow `scripts.mdc` (ESM `.mjs`, stdlib only, `--json` / `--dry-run`, resolve paths via `import.meta.url`).
37
+
38
+ ## Do not
39
+
40
+ - Put application source code here unless it supports the catalog itself.
41
+ - Rename skill folders casually — `artifactId` in ide-agents matches the directory name.
42
+ - Remove `SKILL.md` from a skill folder (scan ignores directories without it).
43
+
44
+ ## Installing
45
+
46
+ Use [ide-agents](https://github.com/sergeychernov/ide-agents): add this repo, then toggle **Global** or **Project** on Skills / Agents pages.
@@ -0,0 +1,101 @@
1
+ ---
2
+ description: Conventions for skill scripts (generators, scanners, report writers)
3
+ globs: skills/**/scripts/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Skill scripts
8
+
9
+ Bundled under `skills/<skill-id>/scripts/`. Invoked by skills and agents — not installed separately by ide-agents.
10
+
11
+ Reference implementation: [repo-audit-skills](https://github.com/sergeychernov/repo-audit-skills) (`detect-stack.mjs`, `run-audit.mjs`, modular `checks/`).
12
+
13
+ ## Runtime
14
+
15
+ - ESM: `*.mjs`, `#!/usr/bin/env node`
16
+ - Node 18+, **zero npm dependencies** in scripts (stdlib only)
17
+ - Resolve skill assets via `import.meta.url` — never assume cwd for skill paths
18
+
19
+ ```javascript
20
+ import { dirname, join } from 'node:path';
21
+ import { fileURLToPath } from 'node:url';
22
+
23
+ const here = dirname(fileURLToPath(import.meta.url));
24
+ const assetsDir = join(here, '..', 'assets');
25
+ ```
26
+
27
+ ## Target repo discovery
28
+
29
+ Scripts run **from anywhere inside the user's project** (after skill symlink install). Discover the audited repo root explicitly:
30
+
31
+ ```javascript
32
+ import { execSync } from 'node:child_process';
33
+
34
+ const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
35
+ process.chdir(repoRoot);
36
+ ```
37
+
38
+ Exit `1` with a clear message if not a git repo.
39
+
40
+ ## File header (required)
41
+
42
+ Every entry script documents usage at the top:
43
+
44
+ ```javascript
45
+ #!/usr/bin/env node
46
+ // my-skill: one-line purpose
47
+ //
48
+ // Usage (from anywhere inside a git repo):
49
+ // node <SKILL_DIR>/scripts/my-script.mjs
50
+ // node <SKILL_DIR>/scripts/my-script.mjs --json
51
+ // node <SKILL_DIR>/scripts/my-script.mjs --dry-run
52
+ ```
53
+
54
+ `<SKILL_DIR>` is the installed skill folder path (global or project symlink).
55
+
56
+ ## CLI flags (standard)
57
+
58
+ | Flag | Effect |
59
+ |------|--------|
60
+ | `--json` | Machine-readable stdout |
61
+ | `--dry-run` | Run logic without writing output files |
62
+ | `--force` | Overwrite existing generated files (when applicable) |
63
+
64
+ Add skill-specific flags (`--offline`, `--verbose`, …) only when documented in the header.
65
+
66
+ ## Scan and write rules
67
+
68
+ - Prefer `git ls-files` over unbounded filesystem walks
69
+ - **Read-only** toward source files in the target repo by default
70
+ - Writable outputs only under paths the skill documents (e.g. `.audit/profile.json`, `.audit/reports/*.json`)
71
+ - Static config and schemas stay in `skills/<id>/assets/` — edit markers here, not in the target project
72
+ - No network calls in scan scripts unless the skill explicitly requires it
73
+
74
+ ## Output
75
+
76
+ - Human mode: short labeled summary for the terminal
77
+ - JSON mode: stable schema for agents to parse
78
+ - JSON files: 2-space indent, trailing newline
79
+ - Stamp artifacts with `generatedBy`, `version`, `generatedAt` when writing reports
80
+
81
+ ## Layout inside a skill
82
+
83
+ ```
84
+ skills/<name>/
85
+ ├── SKILL.md
86
+ ├── scripts/
87
+ │ ├── run-*.mjs # entry points
88
+ │ ├── load-*.mjs # shared loaders
89
+ │ └── checks/ # optional modular checks
90
+ └── assets/ # JSON registries, markers, schemas
91
+ ```
92
+
93
+ Split large generators into `scripts/checks/` modules (see `audit-debt/scripts/checks/`).
94
+
95
+ ## SKILL.md integration
96
+
97
+ Each skill with scripts must include in `SKILL.md`:
98
+
99
+ 1. Folder tree showing `scripts/` and `assets/`
100
+ 2. **Quick start** — copy-pasteable `node <SKILL_DIR>/scripts/….mjs`
101
+ 3. **Agent instructions** — resolve skill dir, run script, read output
@@ -0,0 +1,60 @@
1
+ # Skills & agents catalog
2
+
3
+ A git repository of **IDE skills** and **agents** for Cursor, Claude Code, and Codex.
4
+
5
+ Managed with [ide-agents](https://github.com/sergeychernov/ide-agents) — clone this repo in the UI, then install artifacts globally or per project.
6
+
7
+ ## Layout
8
+
9
+ ```
10
+ .
11
+ ├── skills/
12
+ │ └── <skill-id>/
13
+ │ ├── SKILL.md # required — frontmatter: name, description, scope
14
+ │ ├── scripts/ # optional — *.mjs generators (see .cursor/rules/scripts.mdc)
15
+ │ └── assets/ # optional — JSON/markers for scripts
16
+ ├── agents/
17
+ │ └── <agent-id>.md # orchestrators — call scripts, not inline generators
18
+ ├── .cursor/rules/ # Cursor project rules (repo structure)
19
+ ├── .claude/CLAUDE.md # Claude Code project instructions
20
+ └── .agents/AGENTS.md # Codex project instructions
21
+ ```
22
+
23
+ ## SKILL.md frontmatter
24
+
25
+ ```yaml
26
+ ---
27
+ name: my-skill
28
+ description: What this skill does.
29
+ scope: any # global | project | any
30
+ ---
31
+ ```
32
+
33
+ ## Agents
34
+
35
+ Agent files live in `agents/<agent-id>.md`. YAML frontmatter:
36
+
37
+ ```yaml
38
+ ---
39
+ name: my-agent
40
+ description: When the IDE should delegate to this subagent.
41
+ scope: any # global | project | any — ide-agents install toggles only
42
+ ---
43
+ ```
44
+
45
+ `name` must match the filename stem (`agents/oracle.md` → `name: oracle`). Subagents install to `~/.cursor/agents/<name>.md` (or project `.cursor/agents/`); invoke in Agent mode by name, not via the `/` skill menu.
46
+
47
+ ## Sample artifacts
48
+
49
+ This repo was bootstrapped with a demo skill and a starter agent. Extend or replace them as you build your catalog.
50
+
51
+ | Kind | ID | Purpose |
52
+ |------|-----|---------|
53
+ | skill | `hello` | Install smoke-test + `scripts/now.mjs` (system clock) |
54
+ | agent | `oracle` | Joke fortune-teller — always upbeat predictions |
55
+
56
+ ## Next steps
57
+
58
+ 1. Edit or add skills under `skills/` and agents under `agents/`.
59
+ 2. Commit and push to your remote.
60
+ 3. In ide-agents, open **Skills** / **Agents** and toggle **Global** or **Project** to symlink into your IDE.