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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "kit"
version = "0.1.119"
version = "0.1.120"
edition = "2024"
rust-version = "1.94.0"
publish = false
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ LABEL org.opencontainers.image.title="Kit" \
org.opencontainers.image.revision="${REVISION}"

RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& apt-get install -y --no-install-recommends ca-certificates git \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd --gid 1000 kit \
&& useradd --uid 1000 --gid 1000 --create-home --no-log-init --shell /bin/sh kit \
Expand Down Expand Up @@ -99,7 +99,7 @@ LABEL org.opencontainers.image.title="Kit" \
org.opencontainers.image.revision="${REVISION}"

RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& apt-get install -y --no-install-recommends ca-certificates git \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd --gid 1000 kit \
&& useradd --uid 1000 --gid 1000 --create-home --no-log-init --shell /bin/sh kit \
Expand Down Expand Up @@ -131,7 +131,7 @@ LABEL org.opencontainers.image.title="Kit" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${REVISION}"

RUN apk add --no-cache ca-certificates \
RUN apk add --no-cache ca-certificates git \
&& addgroup -S -g 1000 kit \
&& adduser -S -D -u 1000 -G kit -h /home/kit -s /bin/sh kit \
&& mkdir -p /workspace \
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ See [MCP](docs/user/mcp.md).

### Agent Plugins and Agent Skills

Kit loads validated [Agent Plugin](docs/user/agent-plugins.md) packages from a local directory or a SHA-256-pinned archive. Kit supports ZIP, tar.gz, tar, and GitHub tag archives.
Kit loads validated [Agent Plugin](docs/user/agent-plugins.md) packages from a local directory, a SHA-256-pinned archive, or an HTTPS Git repository pinned to a full commit or validated tag. Kit supports ZIP, tar.gz, tar, and GitHub tag archives.

Plugin skills become available in the `skill` catalog. Kit starts plugin `stdio` and `streamable-http` MCP servers without an `mcp.json` file.

Expand All @@ -208,6 +208,12 @@ source = "archive"
url = "https://github.com/speakeasy-api/gram-plugin/archive/refs/tags/v1.2.0.tar.gz"
sha256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
subdir = "plugin"

[plugins.git-review]
source = "git"
url = "https://plugins.example.com/review.git"
rev = "main"
subdir = "agent-plugin"
```

<!-- PLACEHOLDER: record docs/media/plugins.gif — with a plugin configured in ~/.kit/config.toml, start `kit tui` and ask "Which skills and MCP servers do you have from plugins? Load the review skill." Capture the skill catalog + plugin MCP server in tool_search's `mcp` status listing. -->
Expand Down
24 changes: 21 additions & 3 deletions docs/user/agent-plugins.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Agent Plugins

Kit can load Agent Plugin packages from a local directory or a checksum-pinned online archive. Source resolution happens at startup. Kit uses `agentkit-plugins` to validate the resolved package, exposes its valid Agent Skills through the existing `skill` tool, and registers its supported MCP servers. A plugin-only configuration works without `--mcp-config` or `mcp_config`.
Kit can load Agent Plugin packages from a local directory, a checksum-pinned online archive, or a Git repository. Source resolution happens at startup. Kit uses `agentkit-plugins` to validate the resolved package, exposes its valid Agent Skills through the existing `skill` tool, and registers its supported MCP servers. A plugin-only configuration works without `--mcp-config` or `mcp_config`.

## Configure a source

Expand All @@ -16,16 +16,26 @@ source = "archive"
url = "https://github.com/owner/repo/archive/refs/tags/v1.2.0.tar.gz"
sha256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
subdir = "optional/plugin/path"

[plugins.git-plugin]
source = "git"
url = "https://plugins.example.com/marketplace/opaque-id.git"
rev = "main"
subdir = "agent-plugins/example"
```

Aliases must contain 1–64 lowercase ASCII letters, digits, or single hyphens, with an alphanumeric first and last character. Duplicate plugin manifest names are an error.

A relative `path` is resolved against Kit's working directory, not the configuration directory. An absolute path is used directly. Local packages are validated on every startup and remain mutable local content.

For an `archive`, provide the final archive URL. Kit does not clone Git repositories, translate forge URLs, select branches or tags, or automatically update plugins. `sha256` is mandatory and identifies the exact downloaded bytes. HTTPS is required, except that explicit loopback HTTP URLs are accepted for local testing. Redirects from HTTPS must remain HTTPS. URL credentials and fragments are rejected.
For an `archive`, provide the final archive URL. Kit does not translate forge URLs or automatically update archive sources. `sha256` is mandatory and identifies the exact downloaded bytes. HTTPS is required, except that explicit loopback HTTP URLs are accepted for local testing. Redirects from HTTPS must remain HTTPS. URL credentials and fragments are rejected.

Kit recognizes ZIP, gzip-compressed tar, and plain tar by content. Archives may contain `plugin.json` at the extraction root or one top-level directory, as forge-generated archives commonly do. `subdir`, when present, is applied below that selected base. Archive paths must be contained relative paths; links, special files, duplicate normalized paths, and extraction-limit violations are rejected. Executable mode bits are not preserved in this release.

For `git`, `url` is required, while `rev` and `subdir` are optional. When `rev` is omitted, Kit fetches the remote's `HEAD`, which selects its default branch. `rev` can be an exact 40-hex SHA-1 commit ID or a safe Git ref name such as `main`, `v1.2.0`, `refs/heads/main`, or `refs/tags/v1.2.0`. Git options, refspecs, revision expressions, control characters, and malformed ref names are rejected. Kit fetches the selected name into a private Kit-controlled ref, resolves it to a full commit ID, and uses that immutable ID for archive validation and the cache. A full commit is the reproducible choice; omitted or named revisions are fetched again on every startup and can select a new commit when the remote ref moves. The URL must be an absolute HTTPS URL without user information, a query, or a fragment. Local, SCP-like, SSH, `git`, file, and external-helper transports are rejected.

Kit invokes the installed `git` executable without a shell. It preserves normal system and user Git configuration so configured noninteractive HTTPS credential helpers can authenticate private repositories, but it disables Git terminal and configured askpass prompts, sets standard GUI credential-helper controls to noninteractive, and rejects credentials in the configured URL. Before network access, Kit verifies that `url.*.insteadOf` configuration did not rewrite the validated origin. System and uncommitted attribute files are disabled with controlled empty files; committed `.gitattributes` remains effective. Git diagnostics and configured URLs are not included in errors or written to temporary files. The selected portable `subdir` is archived with literal path semantics. Kit does not check out a worktree or run repository hooks, filters, Git LFS, or submodules; symlinks and submodules in the selected tree are rejected.

## Plugin MCP servers

Kit supports the Agent Plugin `stdio` and `streamable-http` transports. The deprecated `sse` transport is not supported: Kit skips each SSE server and writes a diagnostic containing the plugin alias and server name to stderr. Other valid servers in that plugin remain available.
Expand Down Expand Up @@ -54,7 +64,15 @@ Archive content is downloaded, checked against `sha256`, validated, and extracte
~/.kit/plugin-cache/<lowercase-sha256>
```

The cache is local state protected by the permissions of `~/.kit`; it is not a sandbox or a publisher-identity check. Remove a damaged cache entry to force a verified download. The configured checksum proves archive-byte integrity, not who published those bytes.
Git packages are fetched into an isolated bare staging repository, validated, and atomically published under:

```text
~/.kit/plugin-cache/git-v1/<sha256-url>/<resolved-commit>-<sha256-subdir>/repo
```

A validated full-commit cache entry can be reused without network access. Tags are still resolved remotely on every startup before a matching resolved-commit cache entry is reused. Concurrent publishers can duplicate fetch work, but publication remains atomic: losers validate the completed winner and attempt to remove their own staging directories. Kit also removes only exactly named staging directories under the relevant cache key when they are at least 24 hours old; it does not age out published cache entries. Git commands have a 120-second timeout, hard-bounded pipe output, backoff-based live object-store checks, and a final 256 MiB object-store validation. Git archives stream directly into bounded hardened tar extraction.

The cache is local state protected by the permissions of `~/.kit`; it is not a sandbox or a publisher-identity check. Remove a damaged cache entry to force a verified download. The configured archive checksum proves archive-byte integrity, while a Git commit identifies repository content; neither proves who published it.

Resolution or package-validation failures stop startup. Non-fatal package diagnostics are written to stderr with the plugin alias. Supported validated MCP declarations are registered and begin connecting in the background at startup; unsupported SSE declarations produce the skip diagnostic described above.

Expand Down
8 changes: 7 additions & 1 deletion docs/user/getting-started-and-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ path = "./plugins/local-plugin"
source = "archive"
url = "https://example.com/plugin.tar.gz"
sha256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"

[plugins.git-plugin]
source = "git"
url = "https://plugins.example.com/repository.git"
rev = "main"
subdir = "agent-plugins/example"
```

`root`, `provider`, `model`, and credential settings apply to all four runtime commands. Subagent model aliases and explicit-override allowlists are scoped by fully qualified harness under `[subagent.harnesses."acp.name"]`. Omitting `allow_model_overrides` permits all explicit model selections accepted by that harness; an empty list disables explicit model overrides. This policy does not restrict the harness's inherited or default model.
Expand Down Expand Up @@ -251,7 +257,7 @@ If startup reports `could not load AGENTS.md context`, inspect the `AGENTS.md` f

## Agent Skills

Kit discovers [Agent Skills](https://agentskills.io/) recursively from `<root>/.agents/skills` and `~/.agents/skills`. Validated [Agent Plugins](agent-plugins.md) can add exact skill directories and supported MCP servers from local packages or checksum-pinned archives. Collision precedence for skills is project skills, user skills, then plugins in lexical alias order. Project skills therefore override user and plugin skills with the same name. Each skill lives in a directory containing `SKILL.md`; its frontmatter must include a `name` using lowercase letters, digits, and hyphens that matches the directory name and a non-empty `description`.
Kit discovers [Agent Skills](https://agentskills.io/) recursively from `<root>/.agents/skills` and `~/.agents/skills`. Validated [Agent Plugins](agent-plugins.md) can add exact skill directories and supported MCP servers from local packages, checksum-pinned archives, or HTTPS Git sources pinned to a full commit or validated tag. Collision precedence for skills is project skills, user skills, then plugins in lexical alias order. Project skills therefore override user and plugin skills with the same name. Each skill lives in a directory containing `SKILL.md`; its frontmatter must include a `name` using lowercase letters, digits, and hyphens that matches the directory name and a non-empty `description`.

```markdown
---
Expand Down
8 changes: 6 additions & 2 deletions docs/user/security-limits-and-troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Persisted session transcripts are append-only JSONL records under `~/.kit/sessio

Kit can expose credentials through the authority of its process even when it does not print them. Shell commands and ACP harnesses normally inherit the process environment. Local MCP servers, including plugin stdio servers, are executable code. Plugin stdio servers receive absolute `PLUGIN_ROOT` and `PLUGIN_DATA` paths and can read or modify anything allowed by the Kit process. Remote MCP tools receive invoked arguments, and explicit MCP configuration may contain a plain `bearerToken`. Keep config files and environment variables private, use narrowly scoped accounts, and do not ask the model to echo tokens for diagnosis.

Git plugin sources use the installed system Git and its normal credential-helper configuration for private HTTPS repositories. Inline URL credentials, URL queries, and URL fragments are rejected. Kit disables Git terminal and configured askpass prompts, sets standard GUI credential-helper controls to noninteractive, and disables inherited `GIT_*` shaping and trace settings, hooks, templates, redirects, non-HTTPS transports, uncommitted or system attribute files, submodules, and maintenance for source resolution. It rejects configured URL rewrites before network access and does not expose Git stderr or the configured URL in errors or temporary files. Committed `.gitattributes` remains effective. Credential helpers still run with Kit's process authority and custom helpers can ignore noninteractive conventions, so configure only trusted helpers and narrowly scoped credentials. Git package validation does not sandbox code that the validated plugin later declares as an MCP server.

OpenAI and MCP use one credential backend selected with `--credential-store` or `credential_store`. The default is `memory`. `kit auth login openai` uses PKCE, state, and nonce on fixed loopback callback ports 1455 and 1457 and verifies RS256 tokens against OpenAI's pinned JWKS endpoint. Standalone OpenAI login rejects `memory`; select persistent `keychain` or `file` storage and use the same selection for runtime commands. Token values are redacted from diagnostics and zeroized where practical. The synchronization lock file contains no credentials. `kit auth logout openai` revokes before deletion and retains the credential when revocation fails; `--local-only` deliberately skips revocation and should be used only when remote revocation cannot be completed.

The shared backend choices are:
Expand All @@ -85,7 +87,9 @@ Use `kit tui --help` for credential-store options. If nested Kit agents need the

The following are fixed runtime limits, not configurable policy controls:

- Shell timeout: 120 seconds by default; accepted values are 1 through 3600 seconds. Timeout reports `shell command timed out`. Shell stdout and stderr remain complete inside compose and fail if either stream exceeds the 64 MiB internal safety limit. Final compose results from 8 KiB through the 64 MiB result limit spill at the model-context boundary, which receives a bounded head-and-tail preview and artifact path.
- Shell timeout: 120 seconds by default; accepted values are 1 through 3600 seconds. Timeout reports `shell command timed out`. Shell stdout and stderr remain complete inside compose and fail if either stream exceeds the 64 MiB internal safety limit.
- Shell and Git timeout or output-limit cleanup targets the spawned process tree. On Unix, Kit starts the direct child in a separate process group and terminates that group; a descendant that deliberately creates a new session or process group can escape this cleanup. On Windows, Kit makes a best-effort `taskkill /PID <pid> /T /F` request, which is not a guarantee that every descendant stops. On other platforms, only direct-child termination is available. Always inspect for partial side effects after interruption or failure.
- Git plugin source commands have a fixed 120-second per-command timeout and hard-bounded stdout and stderr pipes. Fetches use backoff-based live object-store checks and a final 256 MiB validation. Archive output streams directly into extraction; selected content also uses the archive entry, per-file, and expanded-size limits. Final compose results from 8 KiB through the 64 MiB result limit spill at the model-context boundary, which receives a bounded head-and-tail preview and artifact path.
- Subagents: nesting depth is two and at most 120 live subagent sessions are retained per main session. Errors include `subagent depth limit (2) reached` and `live subagent session limit (120) reached`. Reuse completed sessions or release unneeded ones with `close` instead of creating unbounded children.
- ACP children: startup handshake and `session/fork` waits are 30 seconds. Cancellation allows 5 seconds to settle before Kit tears down the child. Captured ACP updates are limited to 64 updates and 64 KiB; the returned `updates.truncated` flag reports loss.
- MCP: background server initialization uses a 20-second connection timeout. Tool calls have a 60-second deadline by default; `timeout_seconds` can override it with a value from 1 through 3600 for a call expected to take longer. OAuth authorization expires after 10 minutes. `tool_search` returns at most 5 tools globally across all servers and caps the serialized response at 32 KiB; search with a configured server name, specific product term, or tool keywords. Use the exact query `mcp` (case-insensitive) for a compact configured-server status list; `total_servers`, `returned_servers`, and `truncated` report any tail entries omitted by the same cap.
Expand All @@ -98,7 +102,7 @@ Provider context windows, model token limits, child-agent turn limits, remote ra

### Kit does not start or the TUI exits before opening a session

1. Run `kit --version` and `kit <command> --help` to verify the installed binary and command syntax.
1. Run `kit --version` and `kit <command> --help` to verify the installed binary and command syntax. For a Git plugin error, confirm that `git` is installed, the HTTPS credential helper can authenticate noninteractively, and the configured commit or ref exists (or that the remote has a default branch when `rev` is omitted); Kit intentionally omits remote Git diagnostics because they can contain secrets.
2. If the diagnostic says `could not open working directory` or `working directory is not a directory`, verify that `--root` exists, is a directory, and is accessible to the Kit process.
3. If A2A binding fails or the port is taken, omit the fixed address to get an available loopback port, choose another loopback port, or use `kit acp` when HTTP is unnecessary.
4. If the failure mentions OpenAI subscription credentials, run status and login with the same persistent `--credential-store keychain` or `--credential-store file --credential-dir ...` used by the runtime; standalone login rejects `memory`. Ensure loopback port 1455 or 1457 is available. Retry without pasting secrets into the prompt.
Expand Down
2 changes: 1 addition & 1 deletion macos/Config/Version.xcconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Generated by scripts/generate-macos-project.sh from Cargo.toml.
KIT_VERSION = 0.1.119
KIT_VERSION = 0.1.120
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod docs;
pub mod events;
mod fatal;
pub mod plugins;
pub(crate) mod process_tree;
pub mod protocols;
pub mod provider;
pub mod runtime;
Expand Down
Loading
Loading