@outsidestudio/agent-kit 0.2.2 → 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 +23 -30
- package/package.json +1 -1
- package/profiles/pm.json +9 -1
- package/profiles/product-backend.json +10 -1
- package/profiles/shared.json +11 -1
- package/profiles/web-frontend.json +9 -1
- package/registry/anthropic/document-skills.json +7 -0
- package/registry/outside/product-backend-skills.json +5 -0
- package/registry/outside/{web-skills.json → web-frontend-skills.json} +1 -1
- package/registry/security-audit.json +7 -0
- package/src/cli.ts +40 -4
- package/src/commands/doctor.ts +11 -1
- package/src/commands/new.ts +1 -1
- package/src/types.ts +2 -0
- package/registry/outside/backend-skills.json +0 -5
- /package/skills/{backend → product-backend}/outside-db-migrations/SKILL.md +0 -0
package/README.md
CHANGED
|
@@ -3,16 +3,18 @@
|
|
|
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
|
-
|
|
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
|
+
|
|
17
|
+
**Auto-update.** bunx caches its 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, so bare commands stay current (`AGENT_KIT_NO_UPDATE_CHECK=1` to opt out). Copies older than 0.2.3 cannot self-update: run `bunx @outsidestudio/agent-kit@latest update` once; the bare form updates itself from then on.
|
|
16
18
|
|
|
17
19
|
That command:
|
|
18
20
|
|
|
@@ -45,6 +47,7 @@ Options: `--tool opencode,omp`, `-y/--yes` (no prompts), `--no-shell` (don't edi
|
|
|
45
47
|
profiles/ one file per department; "extends" + "include" registry ids
|
|
46
48
|
registry/ one file per item; id = path under registry/ without .json
|
|
47
49
|
outside/ our own items (registry/outside/llm.json → id "outside/llm")
|
|
50
|
+
anthropic/ Anthropic's skills (registry/anthropic/document-skills.json)
|
|
48
51
|
skills/<group>/ our custom skills (SKILL.md folders)
|
|
49
52
|
src/adapters/ one adapter per tool (opencode.ts, omp.ts)
|
|
50
53
|
```
|
|
@@ -55,21 +58,25 @@ src/adapters/ one adapter per tool (opencode.ts, omp.ts)
|
|
|
55
58
|
{
|
|
56
59
|
"description": "Product backend developers",
|
|
57
60
|
"extends": ["shared"],
|
|
58
|
-
"include": ["
|
|
61
|
+
"include": ["outside/product-backend-skills", "security-audit"]
|
|
59
62
|
}
|
|
60
63
|
```
|
|
61
64
|
|
|
62
|
-
`shared` is the base every department extends: the LLM provider, company skills, Superpowers and
|
|
65
|
+
`shared` is the base every department extends: the LLM provider, company skills, Superpowers, Context7, context-mode and Anthropic's document skills (docx, pdf, pptx, xlsx).
|
|
63
66
|
|
|
64
67
|
### Registry item kinds
|
|
65
68
|
|
|
66
|
-
**`skills`**: a folder of skills, from this repo or any git repo (default branch, latest commit).
|
|
69
|
+
**`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
70
|
|
|
68
71
|
```json
|
|
69
|
-
{ "kind": "skills", "source": { "type": "local", "path": "skills/backend" } }
|
|
72
|
+
{ "kind": "skills", "source": { "type": "local", "path": "skills/product-backend" } }
|
|
70
73
|
{ "kind": "skills", "source": { "type": "git", "repo": "https://github.com/org/repo.git", "path": "skills" }, "only": ["skill-a"] }
|
|
74
|
+
{ "kind": "skills", "source": { "type": "git", "repo": "https://github.com/anthropics/skills.git", "path": "skills" },
|
|
75
|
+
"only": ["docx", "pdf", "pptx", "xlsx"], "requires": ["python3"] }
|
|
71
76
|
```
|
|
72
77
|
|
|
78
|
+
`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).
|
|
79
|
+
|
|
73
80
|
**`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
81
|
|
|
75
82
|
```json
|
|
@@ -87,16 +94,16 @@ src/adapters/ one adapter per tool (opencode.ts, omp.ts)
|
|
|
87
94
|
"fallback": { "type": "git", "repo": "https://github.com/obra/superpowers.git", "path": "skills" } }
|
|
88
95
|
```
|
|
89
96
|
|
|
90
|
-
**`provider`**: an OpenAI-compatible model endpoint (our vast.ai models). The provider id in each tool is the registry id with `/` replaced by `-`, so the model id `nvidia/
|
|
97
|
+
**`provider`**: an OpenAI-compatible model endpoint (our vast.ai models). The provider id in each tool is the registry id with `/` replaced by `-`, so the model id `nvidia/Qwen3.8-Flash-Next-NVFP4` in `outside/llm` appears as `outside-llm/nvidia/Qwen3.8-Flash-Next-NVFP4`.
|
|
91
98
|
|
|
92
99
|
```json
|
|
93
100
|
{ "kind": "provider", "name": "Outside LLM",
|
|
94
101
|
"baseURL": "${OUTSIDE_LLM_BASE_URL}", "apiKey": "${OUTSIDE_LLM_API_KEY}",
|
|
95
|
-
"models": { "nvidia/
|
|
96
|
-
"name": "
|
|
102
|
+
"models": { "nvidia/Qwen3.8-Flash-Next-NVFP4": {
|
|
103
|
+
"name": "Qwen3.8 Flash Next (NVFP4)", "contextWindow": 131072, "maxTokens": 32768,
|
|
97
104
|
"reasoning": true, "input": ["text", "image"],
|
|
98
105
|
"thinking": { "mode": "effort", "efforts": ["low", "medium", "high"], "defaultLevel": "medium" } } },
|
|
99
|
-
"defaultModel": "nvidia/
|
|
106
|
+
"defaultModel": "nvidia/Qwen3.8-Flash-Next-NVFP4" }
|
|
100
107
|
```
|
|
101
108
|
|
|
102
109
|
Model metadata is endpoint-specific — the same model id behind a different gateway has different limits — so each provider item carries the numbers for the server it points at. The kit maps `contextWindow`/`maxTokens` to OMP's `contextWindow`/`maxTokens` and OpenCode's `limit.context`/`limit.output`, `input` to OpenCode `modalities.input`, and passes `thinking` through to OMP.
|
|
@@ -112,30 +119,16 @@ Model metadata is endpoint-specific — the same model id behind a different gat
|
|
|
112
119
|
|
|
113
120
|
`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
121
|
|
|
115
|
-
**What the kit owns.** It records what it installed in `~/.config/outside-agent-kit/state.json`.
|
|
122
|
+
**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
123
|
|
|
117
124
|
**JSONC.** If `opencode.json` has comments, they are removed when the kit rewrites it (the backup keeps them).
|
|
118
125
|
|
|
126
|
+
**Caveats.** 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. OpenCode caches git plugins — if an update doesn't show up, clear OpenCode's plugin cache and restart it.
|
|
127
|
+
|
|
119
128
|
## Adding things
|
|
120
129
|
|
|
121
|
-
- **Custom skill**: `agent-kit new skill backend/rate-limiting`, write the SKILL.md, open a PR. Everyone gets it on their next `update`.
|
|
130
|
+
- **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
131
|
- **New department**: add `profiles/<dept>.json` and `skills/<dept>/` (`new skill <dept>/<name>` creates the registry entry for you).
|
|
123
132
|
- **Third-party item**: add a `registry/<id>.json` (put your own under `registry/outside/`), then add the id to profiles.
|
|
124
133
|
- **New tool** (Codex, Cursor…): write `src/adapters/<tool>.ts` implementing `Adapter` and list it in `src/adapters/index.ts`.
|
|
125
|
-
|
|
126
|
-
## Publishing
|
|
127
|
-
|
|
128
|
-
Pick one:
|
|
129
|
-
|
|
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`.
|
|
131
|
-
- **Straight from GitHub**, no registry: `bunx github:madebyoutside/agent-kit <profile>`.
|
|
132
|
-
|
|
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.
|
|
134
|
-
|
|
135
|
-
## Things to verify for your setup
|
|
136
|
-
|
|
137
|
-
- **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
|
-
- **Model list.** Replace `qwen3-coder` in `registry/outside/llm.json` with the model ids your server actually serves (`curl $OUTSIDE_LLM_BASE_URL/models`).
|
|
139
|
-
- **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
|
-
- **OpenCode plugin cache.** OpenCode caches git plugins. If an update doesn't show up, clear OpenCode's plugin cache and restart it.
|
|
141
|
-
- **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.
|
|
134
|
+
- **Release**: bump `version` in `package.json`, commit, `npm publish --access public`, push. `latest` propagates in ~1-2 min; machines on 0.2.3+ pick it up on their next bare `bunx` run.
|
package/package.json
CHANGED
package/profiles/pm.json
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"description": "Product backend developers",
|
|
3
|
+
"extends": [
|
|
4
|
+
"shared"
|
|
5
|
+
],
|
|
6
|
+
"include": [
|
|
7
|
+
"outside/product-backend-skills",
|
|
8
|
+
"security-audit"
|
|
9
|
+
]
|
|
10
|
+
}
|
package/profiles/shared.json
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"description": "Base setup every profile extends",
|
|
3
|
+
"include": [
|
|
4
|
+
"outside/llm",
|
|
5
|
+
"outside/shared-skills",
|
|
6
|
+
"superpowers",
|
|
7
|
+
"context7",
|
|
8
|
+
"context-mode",
|
|
9
|
+
"anthropic/document-skills"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -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,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "skills",
|
|
3
|
+
"description": "Cloudflare's security-audit skill: security guidance, focused reviews and full multi-agent codebase audits",
|
|
4
|
+
"source": { "type": "git", "repo": "https://github.com/cloudflare/security-audit-skill.git", "path": "skills" },
|
|
5
|
+
"only": ["security-audit"],
|
|
6
|
+
"requires": ["node"]
|
|
7
|
+
}
|
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 #
|
|
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
|
|
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,
|
package/src/commands/doctor.ts
CHANGED
|
@@ -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");
|
package/src/commands/new.ts
CHANGED
|
@@ -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 {
|
|
File without changes
|