@outsidestudio/agent-kit 0.2.2 → 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
 
@@ -45,6 +45,7 @@ Options: `--tool opencode,omp`, `-y/--yes` (no prompts), `--no-shell` (don't edi
45
45
  profiles/ one file per department; "extends" + "include" registry ids
46
46
  registry/ one file per item; id = path under registry/ without .json
47
47
  outside/ our own items (registry/outside/llm.json → id "outside/llm")
48
+ anthropic/ Anthropic's skills (registry/anthropic/document-skills.json)
48
49
  skills/<group>/ our custom skills (SKILL.md folders)
49
50
  src/adapters/ one adapter per tool (opencode.ts, omp.ts)
50
51
  ```
@@ -55,21 +56,25 @@ src/adapters/ one adapter per tool (opencode.ts, omp.ts)
55
56
  {
56
57
  "description": "Product backend developers",
57
58
  "extends": ["shared"],
58
- "include": ["context-mode", "outside/backend-skills"]
59
+ "include": ["context-mode", "outside/product-backend-skills"]
59
60
  }
60
61
  ```
61
62
 
62
- `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).
63
64
 
64
65
  ### Registry item kinds
65
66
 
66
- **`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).
67
68
 
68
69
  ```json
69
- { "kind": "skills", "source": { "type": "local", "path": "skills/backend" } }
70
+ { "kind": "skills", "source": { "type": "local", "path": "skills/product-backend" } }
70
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"] }
71
74
  ```
72
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
+
73
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).
74
79
 
75
80
  ```json
@@ -112,13 +117,13 @@ Model metadata is endpoint-specific — the same model id behind a different gat
112
117
 
113
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`.
114
119
 
115
- **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.
116
121
 
117
122
  **JSONC.** If `opencode.json` has comments, they are removed when the kit rewrites it (the backup keeps them).
118
123
 
119
124
  ## Adding things
120
125
 
121
- - **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`.
122
127
  - **New department**: add `profiles/<dept>.json` and `skills/<dept>/` (`new skill <dept>/<name>` creates the registry entry for you).
123
128
  - **Third-party item**: add a `registry/<id>.json` (put your own under `registry/outside/`), then add the id to profiles.
124
129
  - **New tool** (Codex, Cursor…): write `src/adapters/<tool>.ts` implementing `Adapter` and list it in `src/adapters/index.ts`.
@@ -127,15 +132,16 @@ Model metadata is endpoint-specific — the same model id behind a different gat
127
132
 
128
133
  Pick one:
129
134
 
130
- - **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`.
131
136
  - **Straight from GitHub**, no registry: `bunx github:madebyoutside/agent-kit <profile>`.
132
137
 
133
- 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.
134
139
 
135
140
  ## Things to verify for your setup
136
141
 
137
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.
138
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.
139
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.
140
146
  - **OpenCode plugin cache.** OpenCode caches git plugins. If an update doesn't show up, clear OpenCode's plugin cache and restart it.
141
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.2",
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,9 +1,11 @@
1
1
  #!/usr/bin/env bun
2
+ import { join } from "node:path";
2
3
  import { doctor } from "./commands/doctor";
3
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
 
@@ -24,9 +26,9 @@ ${color.bold("Options")}
24
26
  --no-shell Don't add the secrets loader to ~/.zshrc / ~/.bashrc
25
27
 
26
28
  ${color.bold("Examples")}
27
- bunx @outsidestudio/agent-kit add product-backend # bare form works too: bunx @outsidestudio/agent-kit product-backend
28
- bunx @outsidestudio/agent-kit product-backend web-frontend
29
- bunx @outsidestudio/agent-kit outside/llm # just the model provider, on top of what's installed (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)
30
32
  bunx @outsidestudio/agent-kit remove web-frontend # drop web skills, keep backend + shared
31
33
  bunx @outsidestudio/agent-kit update
32
34
  `;
@@ -47,8 +49,42 @@ function parse(argv: string[]) {
47
49
  return { args, flags };
48
50
  }
49
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
+
50
84
  async function main() {
51
- 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);
52
88
  const [cmd, ...rest] = args;
53
89
  const opts = {
54
90
  tools: typeof flags.tool === "string" ? flags.tool.split(",").map((s) => s.trim()).filter(Boolean) : undefined,
@@ -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");
@@ -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 {
@@ -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
- }