@outsidestudio/agent-kit 0.2.1 → 0.2.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/README.md CHANGED
@@ -3,16 +3,16 @@
3
3
  One command to set up a developer's AI coding tools: skills, MCP servers and our self-hosted model provider, for **OpenCode** and **OMP (oh-my-pi)**.
4
4
 
5
5
  ```bash
6
- bunx @outsidestudio/agent-kit product-backend
6
+ bunx @outsidestudio/agent-kit add product-backend
7
7
  ```
8
8
 
9
9
  Need more than one profile (e.g. full-stack)? Pass them together; their items are merged:
10
10
 
11
11
  ```bash
12
- bunx @outsidestudio/agent-kit product-backend web-frontend
12
+ bunx @outsidestudio/agent-kit add product-backend web-frontend
13
13
  ```
14
14
 
15
- Run them in one command. Running them separately does not stack: each install replaces what the previous one set up.
15
+ Installs **stack**: every run is additive, so installing one profile never removes another profile's entries — run them in any order, as often as you like. `agent-kit remove <target>` takes something out again.
16
16
 
17
17
  That command:
18
18
 
@@ -20,15 +20,16 @@ That command:
20
20
  2. Asks once for any secrets the profile needs (API keys, model endpoint) and stores them in `~/.config/outside-agent-kit/env` (chmod 600), loaded from `~/.zshrc` / `~/.bashrc`.
21
21
  3. Fetches the **latest** version of every skill and plugin. Nothing is pinned.
22
22
  4. Writes each tool's config, keeping anything the developer added themselves.
23
- 5. Installing **only registry items** (no profile) is additive: it adds/replaces those items and keeps the rest of your install. Installing a profile reconciles the full set.
23
+ 5. **Installs are additive**: `agent-kit <target>` writes the named profiles/items and never removes anything else you already have — so `agent-kit product-backend` after `agent-kit product-backend web-frontend` just refreshes backend and leaves the web skills in place. To drop something, use `agent-kit remove <target>`; to rebuild configs to exactly your saved set, use `agent-kit update`.
24
24
 
25
25
  ## Commands
26
26
 
27
27
  | Command | What it does |
28
28
  |---|---|
29
- | `agent-kit <profile...>` | Install one or more profiles |
30
- | `agent-kit outside/llm` | Add/refresh a single registry item without touching the rest of the install (see `agent-kit list`) |
31
- | `agent-kit update` | Re-install the current targets with the latest of everything |
29
+ | `agent-kit add <profile...>` | Add/refresh one or more profiles (additive — keeps the rest). Bare `agent-kit <profile...>` and `install` are shorthands |
30
+ | `agent-kit add outside/llm` | Add/refresh a single registry item on top of what you have (see `agent-kit list`) |
31
+ | `agent-kit remove <target...>` | Remove installed profiles/items; everything else is reconciled to stay |
32
+ | `agent-kit update` | Re-fetch your saved targets and reconcile configs to exactly them (prunes leftovers) |
32
33
  | `agent-kit doctor` | Check tools, secrets, model endpoint, MCP servers, skills |
33
34
  | `agent-kit secrets` | Enter missing secrets |
34
35
  | `agent-kit list` | Show profiles and registry items |
@@ -44,6 +45,7 @@ Options: `--tool opencode,omp`, `-y/--yes` (no prompts), `--no-shell` (don't edi
44
45
  profiles/ one file per department; "extends" + "include" registry ids
45
46
  registry/ one file per item; id = path under registry/ without .json
46
47
  outside/ our own items (registry/outside/llm.json → id "outside/llm")
48
+ anthropic/ Anthropic's skills (registry/anthropic/document-skills.json)
47
49
  skills/<group>/ our custom skills (SKILL.md folders)
48
50
  src/adapters/ one adapter per tool (opencode.ts, omp.ts)
49
51
  ```
@@ -54,21 +56,25 @@ src/adapters/ one adapter per tool (opencode.ts, omp.ts)
54
56
  {
55
57
  "description": "Product backend developers",
56
58
  "extends": ["shared"],
57
- "include": ["context-mode", "outside/backend-skills"]
59
+ "include": ["context-mode", "outside/product-backend-skills"]
58
60
  }
59
61
  ```
60
62
 
61
- `shared` is the base every department extends: the LLM provider, company skills, Superpowers and Context7.
63
+ `shared` is the base every department extends: the LLM provider, company skills, Superpowers, Context7 and Anthropic's document skills (docx, pdf, pptx, xlsx).
62
64
 
63
65
  ### Registry item kinds
64
66
 
65
- **`skills`**: a folder of skills, from this repo or any git repo (default branch, latest commit).
67
+ **`skills`**: a folder of skills, from this repo or any git repo (default branch, latest commit). `only` picks specific skill folders from the source; `requires` lists executables the skills expect on PATH (doctor warns when one is missing).
66
68
 
67
69
  ```json
68
- { "kind": "skills", "source": { "type": "local", "path": "skills/backend" } }
70
+ { "kind": "skills", "source": { "type": "local", "path": "skills/product-backend" } }
69
71
  { "kind": "skills", "source": { "type": "git", "repo": "https://github.com/org/repo.git", "path": "skills" }, "only": ["skill-a"] }
72
+ { "kind": "skills", "source": { "type": "git", "repo": "https://github.com/anthropics/skills.git", "path": "skills" },
73
+ "only": ["docx", "pdf", "pptx", "xlsx"], "requires": ["python3"] }
70
74
  ```
71
75
 
76
+ `anthropic/document-skills` uses the last shape: each run clones Anthropic's public skills repo and copies only the four document skills into the tools' skills dirs. Nothing from that repo is bundled in the npm package — worth knowing because those four carry Anthropic's source-available license (the repo's other skills are Apache 2.0).
77
+
72
78
  **`mcp`**: a local (stdio) or remote (HTTP) MCP server. Write secrets as `${VAR}`; each adapter converts them to the tool's syntax (`{env:VAR}` for OpenCode, `${VAR}` for OMP).
73
79
 
74
80
  ```json
@@ -111,13 +117,13 @@ Model metadata is endpoint-specific — the same model id behind a different gat
111
117
 
112
118
  `OPENCODE_CONFIG_DIR` and `OMP_PROFILE` are respected. The first time a file is changed, a backup is saved next to it as `*.agent-kit.bak`.
113
119
 
114
- **What the kit owns.** It records what it installed in `~/.config/outside-agent-kit/state.json`. On `update` or a profile switch it replaces only those entries. Your own MCP servers, plugins and skills are never touched; if one has the same name as a kit item, yours wins and the kit warns.
120
+ **What the kit owns.** It records what it installed in `~/.config/outside-agent-kit/state.json`. A plain install only ever adds; `remove` and `update` rebuild configs from the saved set, deleting only those recorded entries. Your own MCP servers, plugins and skills are never touched; if one has the same name as a kit item, yours wins and the kit warns.
115
121
 
116
122
  **JSONC.** If `opencode.json` has comments, they are removed when the kit rewrites it (the backup keeps them).
117
123
 
118
124
  ## Adding things
119
125
 
120
- - **Custom skill**: `agent-kit new skill backend/rate-limiting`, write the SKILL.md, open a PR. Everyone gets it on their next `update`.
126
+ - **Custom skill**: `agent-kit new skill product-backend/rate-limiting`, write the SKILL.md, open a PR. Everyone gets it on their next `update`.
121
127
  - **New department**: add `profiles/<dept>.json` and `skills/<dept>/` (`new skill <dept>/<name>` creates the registry entry for you).
122
128
  - **Third-party item**: add a `registry/<id>.json` (put your own under `registry/outside/`), then add the id to profiles.
123
129
  - **New tool** (Codex, Cursor…): write `src/adapters/<tool>.ts` implementing `Adapter` and list it in `src/adapters/index.ts`.
@@ -126,15 +132,16 @@ Model metadata is endpoint-specific — the same model id behind a different gat
126
132
 
127
133
  Pick one:
128
134
 
129
- - **Private npm registry** (GitHub Packages, Verdaccio): `npm publish`, then devs run `bunx @outsidestudio/agent-kit <profile>`. Point the `@outsidestudio` scope at your registry in `~/.npmrc` or `bunfig.toml`.
135
+ - **Private npm registry** (GitHub Packages, Verdaccio): `npm publish`, then devs run `bunx @outsidestudio/agent-kit add <profile>`. Point the `@outsidestudio` scope at your registry in `~/.npmrc` or `bunfig.toml`.
130
136
  - **Straight from GitHub**, no registry: `bunx github:madebyoutside/agent-kit <profile>`.
131
137
 
132
- With "always latest", `bunx` may reuse a cached copy of the kit itself. Use `bunx @outsidestudio/agent-kit@latest update` to be sure you have the newest registry.
138
+ **Auto-update.** bunx reuses its cached copy of the kit; from **0.2.3** a cached copy checks npm's `latest` on startup and transparently reruns the new version with your arguments — bare commands stay current, no `@latest` needed. Set `AGENT_KIT_NO_UPDATE_CHECK=1` to opt out. Copies older than 0.2.3 cannot self-update: if a new command errors (e.g. `Unknown target "add"`), run `bunx @outsidestudio/agent-kit@latest update` once; from then on the bare form updates itself.
133
139
 
134
140
  ## Things to verify for your setup
135
141
 
136
142
  - **Base URL.** Put a stable gateway (LiteLLM, Cloudflare Tunnel) in front of vast.ai so `OUTSIDE_LLM_BASE_URL` doesn't change when instances are recreated.
137
143
  - **Model list.** Replace `qwen3-coder` in `registry/outside/llm.json` with the model ids your server actually serves (`curl $OUTSIDE_LLM_BASE_URL/models`).
144
+ - **Document skills.** Anthropic's docx/pdf/pptx/xlsx skills shell out to `python3` (and LibreOffice/pandoc for some conversions). `agent-kit doctor` warns when `python3` is missing; install the rest only if you use those flows.
138
145
  - **OMP plugins.** Superpowers has no `omp` entry yet, so OMP gets its skills via the fallback. Add `"omp": { "plugin": "..." }` if `omp plugin install` supports it.
139
146
  - **OpenCode plugin cache.** OpenCode caches git plugins. If an update doesn't show up, clear OpenCode's plugin cache and restart it.
140
147
  - **Duplicates in OMP.** OMP also reads other tools' configs (`opencode.json`, `.claude`, …). Same-named MCP servers dedupe (OMP's own `mcp.json` wins), but a skill installed in several places may appear twice.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outsidestudio/agent-kit",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "One-command setup of skills, MCP servers and model providers for OpenCode and OMP",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +1 @@
1
- {"description":"Product backend developers","extends":["shared"],"include":["context-mode","outside/backend-skills"]}
1
+ {"description":"Product backend developers","extends":["shared"],"include":["context-mode","outside/product-backend-skills"]}
@@ -1 +1 @@
1
- {"description":"Base setup every profile extends","include":["outside/llm","outside/shared-skills","superpowers","context7"]}
1
+ {"description":"Base setup every profile extends","include":["outside/llm","outside/shared-skills","superpowers","context7","anthropic/document-skills"]}
@@ -1 +1 @@
1
- {"description":"Web / frontend developers","extends":["shared"],"include":["context-mode","outside/web-skills"]}
1
+ {"description":"Web / frontend developers","extends":["shared"],"include":["context-mode","outside/web-frontend-skills"]}
@@ -0,0 +1,7 @@
1
+ {
2
+ "kind": "skills",
3
+ "description": "Anthropic's document skills: docx, pdf, pptx, xlsx (cloned from Anthropic's repo at install time; source-available license, never bundled in the package)",
4
+ "source": { "type": "git", "repo": "https://github.com/anthropics/skills.git", "path": "skills" },
5
+ "only": ["docx", "pdf", "pptx", "xlsx"],
6
+ "requires": ["python3"]
7
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "kind": "skills",
3
+ "description": "Product backend team custom skills (lives in this repo)",
4
+ "source": { "type": "local", "path": "skills/product-backend" }
5
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "kind": "skills",
3
- "description": "Web team custom skills (lives in this repo)",
3
+ "description": "Web / frontend team custom skills (lives in this repo)",
4
4
  "source": { "type": "local", "path": "skills/web-frontend" }
5
5
  }
package/src/cli.ts CHANGED
@@ -1,15 +1,18 @@
1
1
  #!/usr/bin/env bun
2
+ import { join } from "node:path";
2
3
  import { doctor } from "./commands/doctor";
3
- import { install, secrets, update } from "./commands/install";
4
+ import { install, remove, secrets, update } from "./commands/install";
4
5
  import { list } from "./commands/list";
5
6
  import { newMcp, newSkill } from "./commands/new";
6
7
  import { color, log } from "./log";
8
+ import { KIT_ROOT } from "./paths";
7
9
 
8
10
  const HELP = `${color.bold("agent-kit")}: set up skills, MCP servers and models for OpenCode and OMP
9
11
 
10
12
  ${color.bold("Usage")}
11
- agent-kit <target...> Install profiles and/or single registry items (same as: agent-kit install <target...>)
12
- agent-kit update Re-install the current targets with the latest of everything
13
+ agent-kit add <target...> Add/refresh profiles and/or single registry items; leaves everything else installed untouched (shorthand: agent-kit <target...>, also: agent-kit install)
14
+ agent-kit remove <target...> Remove installed profiles/items; the rest is kept and reconciled
15
+ agent-kit update Re-fetch the saved targets and reconcile configs to exactly them
13
16
  agent-kit doctor Check tools, secrets, model endpoint and MCP servers
14
17
  agent-kit secrets Enter any missing secrets
15
18
  agent-kit list Show profiles and registry items
@@ -23,9 +26,10 @@ ${color.bold("Options")}
23
26
  --no-shell Don't add the secrets loader to ~/.zshrc / ~/.bashrc
24
27
 
25
28
  ${color.bold("Examples")}
26
- bunx @outsidestudio/agent-kit product-backend
27
- bunx @outsidestudio/agent-kit product-backend web-frontend
28
- bunx @outsidestudio/agent-kit outside/llm # just the model provider (see: agent-kit list)
29
+ bunx @outsidestudio/agent-kit add product-backend # also: install, or just the bare profile name
30
+ bunx @outsidestudio/agent-kit add product-backend web-frontend
31
+ bunx @outsidestudio/agent-kit add outside/llm # just the model provider, on top of what's installed (see: agent-kit list)
32
+ bunx @outsidestudio/agent-kit remove web-frontend # drop web skills, keep backend + shared
29
33
  bunx @outsidestudio/agent-kit update
30
34
  `;
31
35
 
@@ -45,8 +49,42 @@ function parse(argv: string[]) {
45
49
  return { args, flags };
46
50
  }
47
51
 
52
+
53
+ /**
54
+ * bunx can silently reuse its cached copy, so an installed copy may lag the
55
+ * published one. A cached copy (only: its path lives in bun's install cache)
56
+ * compares itself against the registry's `latest` and re-execs the new
57
+ * version with the same argv. Dev/repo/global copies never self-update.
58
+ */
59
+ async function selfUpdate(argv: string[]) {
60
+ if (process.env.AGENT_KIT_NO_UPDATE_CHECK) return;
61
+ if (!import.meta.dir.includes(".bun/install/cache")) return;
62
+ try {
63
+ const res = await fetch("https://registry.npmjs.org/@outsidestudio%2Fagent-kit", {
64
+ headers: { Accept: "application/vnd.npm.install-v1+json" },
65
+ signal: AbortSignal.timeout(2500),
66
+ });
67
+ if (!res.ok) return;
68
+ const latest = ((await res.json()) as { "dist-tags"?: { latest?: string } })["dist-tags"]?.latest;
69
+ const here = ((await Bun.file(join(KIT_ROOT, "package.json")).json()) as { version: string }).version;
70
+ if (!latest || latest === here) return;
71
+ log.info(`agent-kit ${here} is stale, rerunning with ${latest}…`);
72
+ const proc = Bun.spawn(["bunx", `@outsidestudio/agent-kit@${latest}`, ...argv], {
73
+ stdin: "inherit",
74
+ stdout: "inherit",
75
+ stderr: "inherit",
76
+ env: { ...process.env, AGENT_KIT_NO_UPDATE_CHECK: "1" },
77
+ });
78
+ process.exit(await proc.exited);
79
+ } catch {
80
+ // offline, slow registry, or no bunx on PATH: run the copy we have
81
+ }
82
+ }
83
+
48
84
  async function main() {
49
- const { args, flags } = parse(Bun.argv.slice(2));
85
+ const argv = Bun.argv.slice(2);
86
+ const { args, flags } = parse(argv);
87
+ await selfUpdate(argv);
50
88
  const [cmd, ...rest] = args;
51
89
  const opts = {
52
90
  tools: typeof flags.tool === "string" ? flags.tool.split(",").map((s) => s.trim()).filter(Boolean) : undefined,
@@ -57,9 +95,13 @@ async function main() {
57
95
  if (!cmd || flags.help) return console.log(HELP);
58
96
 
59
97
  switch (cmd) {
98
+ case "add":
60
99
  case "install":
61
100
  if (!rest.length) throw new Error("What to install? Run: agent-kit list");
62
101
  return install(rest, opts);
102
+ case "remove":
103
+ if (!rest.length) throw new Error("What to remove? Run: agent-kit list");
104
+ return remove(rest, opts);
63
105
  case "update":
64
106
  return update(opts);
65
107
  case "doctor":
@@ -6,7 +6,7 @@ import { paths } from "../paths";
6
6
  import { loadItem, resolveProfiles, secretsOf } from "../registry";
7
7
  import { readEnvFile } from "../secrets";
8
8
  import { readState } from "../state";
9
- import type { McpItem, ProviderItem } from "../types";
9
+ import type { McpItem, ProviderItem, SkillsItem } from "../types";
10
10
 
11
11
  const expand = (v: string) => v.replace(/\$\{([A-Z0-9_]+)\}/g, (_, k) => process.env[k] ?? "");
12
12
 
@@ -55,6 +55,16 @@ export async function doctor(): Promise<number> {
55
55
  const ids = [...new Set([...(await resolveProfiles(state.profiles)), ...(state.items ?? [])])];
56
56
  const items = await Promise.all(ids.map(loadItem));
57
57
 
58
+ const skillDeps = items.filter((i): i is SkillsItem & { id: string } => i.kind === "skills" && !!i.requires?.length);
59
+ if (skillDeps.length) {
60
+ log.head("Skill dependencies");
61
+ for (const item of skillDeps) {
62
+ const missing = item.requires!.filter((b) => !Bun.which(b));
63
+ if (missing.length) log.warn(`${item.id}: ${missing.join(", ")} not on PATH; these skills may not work fully`);
64
+ else log.ok(`${item.id}: needs ${item.requires!.join(", ")} — found`);
65
+ }
66
+ }
67
+
58
68
  log.head("Secrets");
59
69
  const names = [...new Set(items.flatMap(secretsOf))];
60
70
  if (!names.length) log.ok("none needed");
@@ -11,6 +11,8 @@ export interface InstallOptions {
11
11
  tools?: string[];
12
12
  yes?: boolean;
13
13
  shell?: boolean;
14
+ /** Rebuild configs from exactly these targets, purging managed leftovers. */
15
+ reconcile?: boolean;
14
16
  }
15
17
 
16
18
  function pickTools(requested?: string[]): string[] {
@@ -46,10 +48,14 @@ function mergeToolState(prev: ToolState | undefined, next: ToolState): ToolState
46
48
  export async function install(targets: string[], opts: InstallOptions = {}) {
47
49
  const tools = pickTools(opts.tools);
48
50
  const { profiles, items: direct } = await resolveTargets(targets);
49
- // Targeting only registry items adds/replaces those items; it never purges
50
- // the rest of the install. A profile target still reconciles the full set.
51
- const additive = profiles.length === 0 && direct.length > 0;
52
- log.head(`Setting up ${targets.map((t) => `"${t}"`).join(" + ")} for ${tools.join(" + ")}`);
51
+ // Installs are additive: they add/refresh the named targets and never touch
52
+ // what else is installed. Only --reconcile runs (update, remove) purge.
53
+ const additive = opts.reconcile !== true;
54
+ log.head(
55
+ targets.length
56
+ ? `Setting up ${targets.map((t) => `"${t}"`).join(" + ")} for ${tools.join(" + ")}`
57
+ : `Removing everything the kit manages for ${tools.join(" + ")}`,
58
+ );
53
59
 
54
60
  const ids = [...new Set([...(await resolveProfiles(profiles)), ...direct])];
55
61
  const items = await Promise.all(ids.map(loadItem));
@@ -101,7 +107,10 @@ export async function install(targets: string[], opts: InstallOptions = {}) {
101
107
  managed: { ...(prev?.managed ?? {}) },
102
108
  installed: additive ? { ...(prev?.installed ?? {}), ...plan.fetched } : plan.fetched,
103
109
  };
104
- if (additive && prev) log.step(`Additive: keeping ${prev.profiles.join(", ") || "existing items"}; replacing ${direct.join(", ")}`);
110
+ if (additive && prev)
111
+ log.step(
112
+ `Additive: keeping ${[...prev.profiles, ...prev.items].join(", ") || "nothing"}; refreshing ${targets.join(", ")}`,
113
+ );
105
114
  for (const t of tools) {
106
115
  const next = await adapters[t].apply(plan, prev?.managed[t]);
107
116
  state.managed[t] = additive ? mergeToolState(prev?.managed[t], next) : next;
@@ -124,7 +133,31 @@ export async function install(targets: string[], opts: InstallOptions = {}) {
124
133
  export async function update(opts: InstallOptions = {}) {
125
134
  const prev = await readState();
126
135
  if (!prev) throw new Error("Nothing installed yet. Run: agent-kit <profile>");
127
- await install([...prev.profiles, ...prev.items], { ...opts, tools: opts.tools ?? prev.tools });
136
+ // Reconcile: the saved targets are the whole truth, so leftovers from
137
+ // changed profile definitions get purged.
138
+ await install([...prev.profiles, ...prev.items], {
139
+ ...opts,
140
+ tools: opts.tools ?? prev.tools,
141
+ reconcile: true,
142
+ });
143
+ }
144
+
145
+ /** Drop targets from the saved install; everything else is reconciled to stay. */
146
+ export async function remove(targets: string[], opts: InstallOptions = {}) {
147
+ const prev = await readState();
148
+ if (!prev) throw new Error("Nothing installed yet. Run: agent-kit <profile>");
149
+ await resolveTargets(targets); // reject unknown names
150
+ const saved = [...prev.profiles, ...prev.items];
151
+ const gone = targets.filter((t) => saved.includes(t));
152
+ if (!gone.length)
153
+ throw new Error(
154
+ `None of ${targets.join(", ")} is installed. Installed: ${saved.join(", ") || "nothing"}. ` +
155
+ `Items pulled in by a profile can only be removed by removing that profile.`,
156
+ );
157
+ const rest = saved.filter((t) => !gone.includes(t));
158
+ log.head(`Removing ${gone.join(", ")}`);
159
+ if (rest.length) log.info(`Keeping: ${rest.join(", ")}`);
160
+ await install(rest, { ...opts, tools: opts.tools ?? prev.tools, reconcile: true });
128
161
  }
129
162
 
130
163
  /** Re-prompt for every secret the current install needs. */
@@ -17,7 +17,7 @@ export async function newSkill(spec: string) {
17
17
  const root = kitRepo();
18
18
  const [group, name] = spec.includes("/") ? spec.split("/") : ["shared", spec];
19
19
  if (!validName(group) || !validName(name)) {
20
- throw new Error("Use lowercase letters, digits and dashes: agent-kit new skill backend/my-skill");
20
+ throw new Error("Use lowercase letters, digits and dashes: agent-kit new skill product-backend/my-skill");
21
21
  }
22
22
  const dir = join(root, "skills", group, name);
23
23
  if (existsSync(dir)) throw new Error(`${dir} already exists`);
package/src/types.ts CHANGED
@@ -8,6 +8,8 @@ export interface SkillsItem {
8
8
  source: SkillSource;
9
9
  /** Optional allowlist of skill folder names from the source. */
10
10
  only?: string[];
11
+ /** Executables that should be on PATH for these skills to work fully (warned about by doctor). */
12
+ requires?: string[];
11
13
  }
12
14
 
13
15
  export interface McpItem {
@@ -95,8 +97,10 @@ export interface Plan {
95
97
  /** What was fetched, for the install log. */
96
98
  fetched: Record<string, string>;
97
99
  /**
98
- * Single registry-item install: replace only the items in this plan and
99
- * keep everything else the kit managed before (no purge of skills/MCP/etc).
100
+ * Additive run (the default for installs): write exactly what this plan
101
+ * names and keep every other entry the kit managed before — no purge of
102
+ * skills/MCP/plugins/providers. Reconcile runs (update, remove) leave this
103
+ * false and rebuild the config from only this plan.
100
104
  */
101
105
  additive?: boolean;
102
106
  }
@@ -1,5 +0,0 @@
1
- {
2
- "kind": "skills",
3
- "description": "Backend team custom skills (lives in this repo)",
4
- "source": { "type": "local", "path": "skills/backend" }
5
- }