@kuznai/inception-engine 0.10.1 → 0.11.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 +37 -3
- package/dist/core/init.d.ts +9 -0
- package/dist/core/init.js +99 -0
- package/dist/index.js +25 -0
- package/dist/types.d.ts +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# inception-engine
|
|
2
2
|
|
|
3
|
-
Plant skills directly into the minds of your installed AI coding agents — Claude Code, Codex, Gemini CLI, Antigravity,
|
|
3
|
+
Plant skills directly into the minds of your installed AI coding agents — Claude Code, Codex, Gemini CLI, Antigravity, and OpenCode. One command. They'll think they thought of it themselves.
|
|
4
4
|
|
|
5
5
|
Today, inception-engine works as a cross-agent deployer for skills on all listed agents, plus single-file writes and JSON config patches. It also supports MCP server registration and global rules-file deployment for the subset of agents whose config surfaces are implemented and validated today.
|
|
6
6
|
|
|
7
|
+
GitHub Copilot is no longer treated as a separate instruction or skill target in the product direction when it can consume Claude-native artifacts directly. If Copilot uses `CLAUDE.md` or Claude-style skill layouts without translation, inception-engine should rely on the Claude deployment path instead of maintaining duplicate Copilot-specific surfaces. Dedicated Copilot customization remains justified only where Copilot exposes a materially different interface, such as MCP-related configuration.
|
|
8
|
+
|
|
7
9
|
The broader portability layer is the roadmap direction, but this README focuses on what is working now.
|
|
8
10
|
|
|
11
|
+
`init` is available as a bootstrap command, but what works today is intentionally narrow: it scans for directories containing `SKILL.md` and generates starter `skills` entries plus empty `mcpServers` and `agentRules` arrays. It does not infer `files`, `configs`, MCP server definitions, or rules files from the repository yet.
|
|
12
|
+
|
|
9
13
|
## Quick Start
|
|
10
14
|
|
|
11
15
|
```bash
|
|
@@ -32,7 +36,6 @@ Managed skills overwrite their previous version. If a target exists but was not
|
|
|
32
36
|
| Gemini CLI | `gemini-cli` | `~/.gemini/skills/` | Yes | Yes | Yes |
|
|
33
37
|
| Antigravity | `antigravity` | `~/.gemini/antigravity/skills/` | Yes* | Yes* | Yes* |
|
|
34
38
|
| OpenCode | `opencode` | `~/.config/opencode/skills/` | Yes | Yes | Yes* |
|
|
35
|
-
| GitHub Copilot | `github-copilot` | `~/.copilot/skills/` | Yes | Yes | Yes |
|
|
36
39
|
|
|
37
40
|
\* Antigravity support is currently based on the implementation's registry path assumptions and local validation, not a strong official doc set equivalent to the other agents.
|
|
38
41
|
|
|
@@ -47,9 +50,12 @@ Managed skills overwrite their previous version. If a target exists but was not
|
|
|
47
50
|
| Config patch (JSON merge) | All agents via manifest and CLI | All agents |
|
|
48
51
|
| MCP Servers | claude-code, gemini-cli; other agents are warned and skipped | claude-code, gemini-cli |
|
|
49
52
|
| Global Rules Files | claude-code, codex, gemini-cli, opencode; other agents are warned and skipped | claude-code, codex, gemini-cli, opencode |
|
|
53
|
+
| `init` manifest generation | Scans `SKILL.md` directories and writes starter `skills` entries | N/A |
|
|
50
54
|
|
|
51
55
|
Features that depend on agent-specific config surfaces are intentionally conservative: if a target path or schema is not implemented with enough confidence, inception-engine warns and skips it rather than guessing.
|
|
52
56
|
|
|
57
|
+
For GitHub Copilot specifically, the portability rule is Claude-first: if Copilot accepts the same Claude-native instruction or skill artifact, inception-engine should not add a separate Copilot deployment feature for it.
|
|
58
|
+
|
|
53
59
|
## Manifest Format
|
|
54
60
|
|
|
55
61
|
Create an `inception.json` file at the root of your skills directory:
|
|
@@ -60,7 +66,7 @@ Create an `inception.json` file at the root of your skills directory:
|
|
|
60
66
|
{
|
|
61
67
|
"name": "my-skill",
|
|
62
68
|
"path": "skills/my-skill",
|
|
63
|
-
"agents": ["claude-code", "codex", "gemini-cli", "antigravity", "opencode"
|
|
69
|
+
"agents": ["claude-code", "codex", "gemini-cli", "antigravity", "opencode"]
|
|
64
70
|
}
|
|
65
71
|
],
|
|
66
72
|
"files": [
|
|
@@ -151,11 +157,30 @@ Instructions for the AI agent...
|
|
|
151
157
|
|
|
152
158
|
The `name` and `description` fields in the frontmatter are used by most agents. The description determines when the agent activates the skill. inception-engine does not currently validate the frontmatter — missing or malformed fields may cause the skill to be ignored or misbehave at the agent level.
|
|
153
159
|
|
|
160
|
+
## `init` Command
|
|
161
|
+
|
|
162
|
+
`init` is meant to bootstrap a repository that already has skill folders. It recursively scans the target directory, treats any directory containing `SKILL.md` as a skill, and writes a starter `inception.json`.
|
|
163
|
+
|
|
164
|
+
Current `init` behavior:
|
|
165
|
+
|
|
166
|
+
- Generates `skills` entries using the discovered relative paths
|
|
167
|
+
- Uses the directory name as the manifest skill name
|
|
168
|
+
- Applies either the `--agents` list or all currently known agent IDs
|
|
169
|
+
- Refuses to overwrite an existing `inception.json` unless `--force` is provided
|
|
170
|
+
- Supports `--dry-run` so you can inspect the generated manifest before writing it
|
|
171
|
+
|
|
172
|
+
Current `init` limitations:
|
|
173
|
+
|
|
174
|
+
- It does not read or validate YAML frontmatter inside `SKILL.md`
|
|
175
|
+
- It does not infer `files`, `configs`, `mcpServers`, or `agentRules`
|
|
176
|
+
- It does not reconcile generated output with the longer-term Claude-first portability direction
|
|
177
|
+
|
|
154
178
|
## CLI Reference
|
|
155
179
|
|
|
156
180
|
```
|
|
157
181
|
inception-engine <directory> [options]
|
|
158
182
|
inception-engine revert <directory> [options]
|
|
183
|
+
inception-engine init <directory> [options]
|
|
159
184
|
```
|
|
160
185
|
|
|
161
186
|
### Commands
|
|
@@ -164,6 +189,7 @@ inception-engine revert <directory> [options]
|
|
|
164
189
|
|---|---|
|
|
165
190
|
| `<directory>` | Deploy skills from the manifest in the given directory |
|
|
166
191
|
| `revert <directory>` | Remove previously deployed skills declared in the manifest |
|
|
192
|
+
| `init <directory>` | Scan a directory for skill folders and generate `inception.json` |
|
|
167
193
|
|
|
168
194
|
### Options
|
|
169
195
|
|
|
@@ -171,6 +197,7 @@ inception-engine revert <directory> [options]
|
|
|
171
197
|
|---|---|
|
|
172
198
|
| `--dry-run` | Show what would be done without making changes |
|
|
173
199
|
| `--agents <list>` | Comma-separated list of agent IDs to target (overrides deploy detection; restricts revert) |
|
|
200
|
+
| `--force` | `init` only; overwrite an existing `inception.json` |
|
|
174
201
|
| `--verbose` | Show detailed output including file paths |
|
|
175
202
|
| `--debug` | Show full error stack traces |
|
|
176
203
|
| `--help` | Show help message |
|
|
@@ -192,6 +219,12 @@ npx @kuznai/inception-engine revert ./my-skills-repo
|
|
|
192
219
|
|
|
193
220
|
# Preview what would be removed
|
|
194
221
|
npx @kuznai/inception-engine revert ./my-skills-repo --dry-run
|
|
222
|
+
|
|
223
|
+
# Generate a starter manifest from discovered skill folders
|
|
224
|
+
npx @kuznai/inception-engine init ./my-skills-repo
|
|
225
|
+
|
|
226
|
+
# Preview the generated manifest without writing it
|
|
227
|
+
npx @kuznai/inception-engine init ./my-skills-repo --dry-run
|
|
195
228
|
```
|
|
196
229
|
|
|
197
230
|
## Sample Skills
|
|
@@ -201,6 +234,7 @@ The `limbo/` directory contains exceptional sample skills for testing purposes o
|
|
|
201
234
|
Try them out:
|
|
202
235
|
|
|
203
236
|
```bash
|
|
237
|
+
npx @kuznai/inception-engine init limbo --dry-run
|
|
204
238
|
npx @kuznai/inception-engine limbo --dry-run
|
|
205
239
|
```
|
|
206
240
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AgentId } from "../schemas/manifest.ts";
|
|
2
|
+
export interface InitOptions {
|
|
3
|
+
directory: string;
|
|
4
|
+
agents: AgentId[] | null;
|
|
5
|
+
dryRun: boolean;
|
|
6
|
+
force: boolean;
|
|
7
|
+
verbose: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function runInit(options: InitOptions): Promise<number>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { access, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { dryRunPrefix, logger } from "../logger.js";
|
|
4
|
+
import { AGENT_IDS } from "../schemas/manifest.js";
|
|
5
|
+
const SAFE_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
6
|
+
async function findSkillDirs(baseDir, dir, found) {
|
|
7
|
+
let entries;
|
|
8
|
+
try {
|
|
9
|
+
entries = await readdir(dir, { withFileTypes: true, encoding: "utf-8" });
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const hasSkillMd = entries.some((e) => e.isFile() && e.name === "SKILL.md");
|
|
15
|
+
if (hasSkillMd) {
|
|
16
|
+
const relPath = path.relative(baseDir, dir).split(path.sep).join("/");
|
|
17
|
+
const name = path.basename(dir);
|
|
18
|
+
if (SAFE_NAME_RE.test(name)) {
|
|
19
|
+
found.push({ relPath, name });
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
logger.warn("init", `Skipping "${relPath}": directory name "${name}" is not a valid skill name`);
|
|
23
|
+
}
|
|
24
|
+
// Don't recurse into a skill directory
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
if (entry.isDirectory() && !entry.name.startsWith(".")) {
|
|
29
|
+
await findSkillDirs(baseDir, path.join(dir, entry.name), found);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function resolveSkillName(relPath, name, namesSeen) {
|
|
34
|
+
if (!namesSeen.has(name))
|
|
35
|
+
return name;
|
|
36
|
+
// Collision: derive unique name from path by replacing separators with hyphens
|
|
37
|
+
const derived = relPath.replace(/\//g, "-");
|
|
38
|
+
if (SAFE_NAME_RE.test(derived))
|
|
39
|
+
return derived;
|
|
40
|
+
logger.warn("init", `Skipping "${relPath}": could not generate a unique valid name (collision with "${name}")`);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
function buildSkills(found, agents) {
|
|
44
|
+
const namesSeen = new Set();
|
|
45
|
+
const skills = [];
|
|
46
|
+
for (const { relPath, name } of found) {
|
|
47
|
+
const skillName = resolveSkillName(relPath, name, namesSeen);
|
|
48
|
+
if (skillName === null)
|
|
49
|
+
continue;
|
|
50
|
+
namesSeen.add(skillName);
|
|
51
|
+
skills.push({ name: skillName, path: relPath, agents });
|
|
52
|
+
}
|
|
53
|
+
return skills;
|
|
54
|
+
}
|
|
55
|
+
async function manifestExists(manifestPath) {
|
|
56
|
+
try {
|
|
57
|
+
await access(manifestPath);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function runInit(options) {
|
|
65
|
+
const { directory, dryRun, force, verbose } = options;
|
|
66
|
+
const agents = options.agents ?? [...AGENT_IDS];
|
|
67
|
+
const manifestPath = path.join(directory, "inception.json");
|
|
68
|
+
if (!dryRun && (await manifestExists(manifestPath)) && !force) {
|
|
69
|
+
logger.error(`Error: ${manifestPath} already exists. Use --force to overwrite.`);
|
|
70
|
+
return 2;
|
|
71
|
+
}
|
|
72
|
+
const found = [];
|
|
73
|
+
await findSkillDirs(directory, directory, found);
|
|
74
|
+
if (found.length === 0) {
|
|
75
|
+
logger.info("No skill directories found (looking for directories containing SKILL.md).");
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
const skills = buildSkills(found, agents);
|
|
79
|
+
if (skills.length === 0) {
|
|
80
|
+
logger.info("No skills could be added to the manifest.");
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
const manifest = { skills, mcpServers: [], agentRules: [] };
|
|
84
|
+
const json = `${JSON.stringify(manifest, null, 2)}\n`;
|
|
85
|
+
if (dryRun) {
|
|
86
|
+
logger.info(`${dryRunPrefix(true)}Would write ${manifestPath} with ${skills.length} skill(s):`);
|
|
87
|
+
logger.info("");
|
|
88
|
+
logger.info(json);
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
await writeFile(manifestPath, json, "utf-8");
|
|
92
|
+
logger.info(`Generated ${manifestPath} with ${skills.length} skill(s).`);
|
|
93
|
+
if (verbose) {
|
|
94
|
+
for (const s of skills) {
|
|
95
|
+
logger.detail(`${s.name} → ${s.path}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { AGENT_REGISTRY } from "./config/agents.js";
|
|
|
5
5
|
import { loadManifest } from "./config/manifest.js";
|
|
6
6
|
import { executeDeploy, planDeploy } from "./core/deploy.js";
|
|
7
7
|
import { detectInstalledAgents } from "./core/detect.js";
|
|
8
|
+
import { runInit } from "./core/init.js";
|
|
8
9
|
import { runPreflight } from "./core/preflight.js";
|
|
9
10
|
import { resolveHome } from "./core/resolve.js";
|
|
10
11
|
import { executeRevert, planRevert, planRevertAll } from "./core/revert.js";
|
|
@@ -17,10 +18,17 @@ inception-engine - Deploy AI agent skills
|
|
|
17
18
|
Usage:
|
|
18
19
|
inception-engine <directory> [options]
|
|
19
20
|
inception-engine revert <directory> [options]
|
|
21
|
+
inception-engine init <directory> [options]
|
|
22
|
+
|
|
23
|
+
Commands:
|
|
24
|
+
<directory> Deploy skills from the manifest in the given directory
|
|
25
|
+
revert <directory> Remove previously deployed skills
|
|
26
|
+
init <directory> Scan a directory for skill folders and generate inception.json
|
|
20
27
|
|
|
21
28
|
Options:
|
|
22
29
|
--dry-run Show what would be done without doing it
|
|
23
30
|
--agents <list> Comma-separated list of agent IDs to target
|
|
31
|
+
--force (init only) Overwrite an existing inception.json
|
|
24
32
|
--verbose Show detailed output
|
|
25
33
|
--debug Show full error stack traces
|
|
26
34
|
--help Show this help message
|
|
@@ -38,6 +46,7 @@ function parseCLI(argv) {
|
|
|
38
46
|
agents: null,
|
|
39
47
|
verbose: false,
|
|
40
48
|
debug: false,
|
|
49
|
+
force: false,
|
|
41
50
|
};
|
|
42
51
|
}
|
|
43
52
|
let parsed;
|
|
@@ -50,6 +59,7 @@ function parseCLI(argv) {
|
|
|
50
59
|
verbose: { type: "boolean", default: false },
|
|
51
60
|
debug: { type: "boolean", default: false },
|
|
52
61
|
help: { type: "boolean", default: false },
|
|
62
|
+
force: { type: "boolean", default: false },
|
|
53
63
|
agents: { type: "string" },
|
|
54
64
|
},
|
|
55
65
|
});
|
|
@@ -66,6 +76,7 @@ function parseCLI(argv) {
|
|
|
66
76
|
agents: null,
|
|
67
77
|
verbose: false,
|
|
68
78
|
debug: false,
|
|
79
|
+
force: false,
|
|
69
80
|
};
|
|
70
81
|
}
|
|
71
82
|
let command = "deploy";
|
|
@@ -74,6 +85,10 @@ function parseCLI(argv) {
|
|
|
74
85
|
command = "revert";
|
|
75
86
|
pos = pos.slice(1);
|
|
76
87
|
}
|
|
88
|
+
else if (pos[0] === "init") {
|
|
89
|
+
command = "init";
|
|
90
|
+
pos = pos.slice(1);
|
|
91
|
+
}
|
|
77
92
|
if (pos.length > 1) {
|
|
78
93
|
throw new UserError("INVALID_ARGS", `Unexpected argument: ${pos[1]}`);
|
|
79
94
|
}
|
|
@@ -96,6 +111,7 @@ function parseCLI(argv) {
|
|
|
96
111
|
agents,
|
|
97
112
|
verbose: values.verbose,
|
|
98
113
|
debug: values.debug,
|
|
114
|
+
force: values.force,
|
|
99
115
|
};
|
|
100
116
|
}
|
|
101
117
|
async function main() {
|
|
@@ -104,6 +120,15 @@ async function main() {
|
|
|
104
120
|
console.log(USAGE);
|
|
105
121
|
return 0;
|
|
106
122
|
}
|
|
123
|
+
if (options.command === "init") {
|
|
124
|
+
return runInit({
|
|
125
|
+
directory: options.directory,
|
|
126
|
+
agents: options.agents,
|
|
127
|
+
dryRun: options.dryRun,
|
|
128
|
+
force: options.force,
|
|
129
|
+
verbose: options.verbose,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
107
132
|
const manifest = await loadManifest(options.directory);
|
|
108
133
|
const home = resolveHome();
|
|
109
134
|
if (options.command === "deploy") {
|
package/dist/types.d.ts
CHANGED
|
@@ -85,10 +85,11 @@ export interface PlannedChange {
|
|
|
85
85
|
confidence?: Confidence;
|
|
86
86
|
}
|
|
87
87
|
export interface CliOptions {
|
|
88
|
-
command: "deploy" | "revert" | "help";
|
|
88
|
+
command: "deploy" | "revert" | "init" | "help";
|
|
89
89
|
directory: string;
|
|
90
90
|
dryRun: boolean;
|
|
91
91
|
agents: AgentId[] | null;
|
|
92
92
|
verbose: boolean;
|
|
93
93
|
debug: boolean;
|
|
94
|
+
force: boolean;
|
|
94
95
|
}
|