Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The v0.1 product is deliberately small:

- validate a local skill directory
- validate an embedded bundled skill directory tree
- resolve a public GitHub skill bundle directory tree
- detect local agent hosts
- resolve safe CLI install selection before writes
- run the safe CLI install workflow for bundled skills
Expand All @@ -19,7 +20,7 @@ The v0.1 product is deliberately small:
- return structured reports
- enforce parity through shared golden cases

Do not turn kitup into a marketplace, registry client, package manager, MCP server, GUI, agent runtime integration layer, or arbitrary skill installer. Remote installs, GitHub source installs, marketplace search, plugin systems, `AGENTS.md` mutation, script execution, and symlink-first workflows are outside v0.1 unless this boundary and golden cases are changed first.
Do not turn kitup into a marketplace, registry client, package manager, MCP server, GUI, agent runtime integration layer, or arbitrary skill installer. Only first-party public GitHub bundle resolution is inside v0.1 behavior. Other remote installs, private GitHub auth, marketplace search, plugin systems, `AGENTS.md` mutation, script execution, and symlink-first workflows are outside v0.1 unless this boundary and golden cases are changed first.

## Product Promise

Expand Down Expand Up @@ -55,17 +56,18 @@ When docs and executable checks disagree, fix the source of truth or surface the

Before non-trivial work, classify the request as one of:

- v0.1 bundled-skill source, selection, and installer behavior
- v0.1 bundled-skill bundle, selection, and installer behavior
- public GitHub bundle behavior
- host adapter data correction
- fixture or parity improvement
- documentation of existing behavior
- post-v0.1 scope

Only the first four are normal work. For post-v0.1 scope, do not implement product surface until the boundary is explicitly changed in docs and golden cases.

Every new source, selection, or installer behavior needs a golden case. A behavior that cannot be expressed in `testdata/cases` is not ready to become SDK behavior.
Every new bundle input, selection, or installer behavior needs a golden case. A behavior that cannot be expressed in `testdata/cases` is not ready to become SDK behavior.

Do not add speculative abstractions for future registries, package managers, remote sources, marketplace metadata, auth, or dependency resolution. Build the shallowest implementation that satisfies the existing case matrix.
Do not add speculative abstractions for future registries, package managers, custom providers, marketplace metadata, auth, or dependency resolution. Build the shallowest implementation that satisfies the existing case matrix.

## Host Adapter Rules

Expand Down Expand Up @@ -101,7 +103,7 @@ Content hashes must be deterministic across TypeScript, Go, and Rust. Hash bundl

Reports are API contracts. Return structured `installed`, `updated`, `skipped`, `conflicts`, and `errors` data instead of relying on logs.

Bundled skill sources are directory trees. `SKILL.md` must live at the bundle root, but references, scripts, assets, and other regular files are part of the same source and must be validated, hashed, and copied as a tree.
Skill bundles are directory trees. `SKILL.md` must live at the bundle root, but references, scripts, assets, and other regular files are part of the same bundle and must be validated, hashed, and copied as a tree.

## Multi-Language Parity

Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Keep changes inside the v0.1 boundary:

- validate local skill directories
- validate embedded skill directory trees
- resolve public GitHub skill bundle directory trees
- detect agent hosts
- resolve safe CLI install selection
- run the safe CLI install workflow
Expand All @@ -15,7 +16,7 @@ Keep changes inside the v0.1 boundary:
- return structured reports
- keep TypeScript, Go, and Rust behavior aligned through golden cases

Do not add marketplace, registry, remote install, script execution, MCP server, GUI, or agent runtime behavior unless the product boundary changes first.
Do not add marketplace, registry, private remote install, custom provider, script execution, MCP server, GUI, or agent runtime behavior unless the product boundary changes first.

## Setup

Expand Down Expand Up @@ -73,7 +74,7 @@ Host support is data-first.

## SDK Behavior Changes

Every source, selection, or installer behavior needs a golden case in `testdata/cases`.
Every bundle input, selection, or installer behavior needs a golden case in `testdata/cases`.

Before opening a pull request:

Expand Down
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# kitup

Shared installer SDK for bundled Agent Skills.
Shared installer SDK for bundled and public GitHub Agent Skills.

CLI authors ship a skill with their tool. `kitup` models that bundled skill as a directory tree, resolves safe agent targets, validates `SKILL.md`, copies the full tree into the right host directories, and writes ownership metadata so updates stay safe.
CLI authors ship or point to a skill. `kitup` models that skill as a directory tree, resolves safe agent targets, validates `SKILL.md`, copies the full tree into the right host directories, and writes ownership metadata so updates stay safe.

```text
mycli skill install
Expand All @@ -17,7 +17,7 @@ mycli skill install
- resolve user and project skill directories
- resolve safe CLI install selection before writing
- validate bundled skills
- install from a local directory or embedded bundle tree
- install from a local directory, embedded bundle tree, or public GitHub bundle directory
- copy, update, and uninstall kitup-owned installs
- refuse unsafe overwrite conflicts
- return structured install reports
Expand All @@ -26,6 +26,7 @@ mycli skill install

- not a skill marketplace
- not a remote registry
- not a private GitHub auth client
- not a replacement for user-facing skill discovery tools

## Usage
Expand Down Expand Up @@ -97,6 +98,26 @@ await runBundledSkillInstall({
});
```

For public GitHub directories, configure the GitHub bundle in the embedding CLI. The user-facing install command stays the same:

```ts
import { githubBundle, runBundledSkillInstall } from "@kitup/sdk";

await runBundledSkillInstall({
appId: "mycli",
skillBundle: githubBundle({
owner: "acme",
repo: "mycli-skills",
path: "skills/mycli",
ref: "v1.2.3",
}),
scope: "user",
agents: ["codex"],
});
```

Go, Rust, and Cobra use the same `skillBundle` shape; see [API](docs/API.md) for language-specific constructors.

### Go

Install:
Expand Down
65 changes: 62 additions & 3 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

The core flow is:

1. normalize a bundled skill directory tree
1. resolve a local directory tree, embedded files, or public GitHub bundle
2. resolve safe target agent selection for CLI workflows
3. validate `SKILL.md`
4. copy, update, skip, or report conflicts
Expand All @@ -20,6 +20,7 @@ import {
detectHosts,
directoryBundle,
filesBundle,
githubBundle,
installBundledSkill,
installFlagError,
installWorkflowError,
Expand All @@ -45,6 +46,21 @@ const report = await installBundledSkill({
});
```

Public GitHub bundle call:

```ts
const report = await installBundledSkill({
appId: "mycli",
skillBundle: githubBundle({
owner: "acme",
repo: "mycli-skills",
path: "skills/mycli",
ref: "v1.2.3",
}),
scope: "user",
});
```

Implemented functions:

- `loadHostSpec(hostsFile?)`
Expand All @@ -56,6 +72,7 @@ Implemented functions:
- `computeBundleContentHash(bundle, cwd?)`
- `directoryBundle(path)`
- `filesBundle(files)`
- `githubBundle(options)`
- `parseInstallFlags(flags)`
- `agentSelectorFromFlags(values)`
- `parseScopeFlag(value)`
Expand Down Expand Up @@ -87,6 +104,21 @@ report, err := kitup.InstallBundledSkill(kitup.InstallOptions{
})
```

Public GitHub bundle call:

```go
report, err := kitup.InstallBundledSkill(kitup.InstallOptions{
AppID: "mycli",
SkillBundle: kitup.GitHubBundle(kitup.GitHubBundleOptions{
Owner: "acme",
Repo: "mycli-skills",
Path: "skills/mycli",
Ref: "v1.2.3",
}),
Scope: kitup.UserScope,
})
```

Implemented functions:

- `LoadHostSpec(hostsFile string)`
Expand All @@ -99,6 +131,7 @@ Implemented functions:
- `DirectoryBundle(path)`
- `FSBundle(fsys, root)`
- `FilesBundle(files)`
- `GitHubBundle(opts)`
- `ParseInstallFlags(flags)`
- `AgentSelectorFromFlags(values)`
- `ParseScopeFlag(value)`
Expand Down Expand Up @@ -133,6 +166,23 @@ let report = kitup::install_bundled_skill(&kitup::InstallOptions {
})?;
```

Public GitHub bundle call:

```rust
let report = kitup::install_bundled_skill(&kitup::InstallOptions {
base: kitup::BaseOptions::default(),
app_id: "mycli".to_string(),
skill_bundle: kitup::github_bundle(kitup::GitHubBundleOptions {
owner: "acme".to_string(),
repo: "mycli-skills".to_string(),
path: "skills/mycli".to_string(),
ref_name: "v1.2.3".to_string(),
}),
scope: kitup::Scope::User,
agents: kitup::AgentSelector::Auto,
})?;
```

Implemented functions:

- `load_host_spec(hosts_file)`
Expand All @@ -144,6 +194,7 @@ Implemented functions:
- `compute_bundle_content_hash(bundle)`
- `directory_bundle(path)`
- `files_bundle(files)`
- `github_bundle(options)`
- `parse_install_flags(flags)`
- `agent_selector_from_flags(values, errors)`
- `parse_scope_flag(value, errors)`
Expand All @@ -163,12 +214,20 @@ Implemented functions:
Install options use the same concepts across languages:

- `appId` / `AppID` / `app_id`: owner id written to `.kitup.json`
- `skillBundle` / `SkillBundle` / `skill_bundle`: bundled skill directory tree source
- `skillBundle` / `SkillBundle` / `skill_bundle`: local directory, embedded files, or public GitHub bundle
- `scope`: `user` or `project`
- `agents`: `"auto"`, `"*"`, or explicit host ids
- `home`, `cwd`, `hostsFile`: optional test and embedding overrides

Bundle sources must use root-relative POSIX paths. SDKs reject empty paths, absolute paths, `..`, duplicate files, and backslash paths. SDKs exclude `.kitup.json`, `.git`, `.DS_Store`, swap files, and editor backups before validation, hashing, and copy.
Bundle file paths must use root-relative POSIX paths. SDKs reject empty paths, absolute paths, `..`, duplicate files, and backslash paths. SDKs exclude `.kitup.json`, `.git`, `.DS_Store`, swap files, and editor backups before validation, hashing, and copy.

The first non-local bundle constructor is GitHub only:

- TypeScript: `githubBundle({ owner, repo, path, ref })`
- Go: `GitHubBundle(GitHubBundleOptions{Owner, Repo, Path, Ref})`
- Rust: `github_bundle(GitHubBundleOptions { owner, repo, path, ref_name })`

GitHub bundle resolution downloads only files under the configured directory path, requires `SKILL.md` at that bundle root, records the requested ref and resolved commit, and writes GitHub provenance into `.kitup.json`. It does not search GitHub, install dependencies, execute scripts, handle private auth, or install whole repositories by default.

The embedding CLI owns command names and framework attachment. `kitup` owns standard install flag semantics, selector mapping, user-facing workflow text, summary rendering, confirmation, dry-run planning, workflow exit classification, and execution. For user-facing commands, call `runBundledSkillInstall` / `RunBundledSkillInstall` / `run_bundled_skill_install` with values from the shared flag parsing helpers.

Expand Down
Loading
Loading