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
5 changes: 5 additions & 0 deletions .changeset/curated-cli-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"caplets": minor
---

Add `cliTools` Caplet backends for typed, shell-free CLI actions plus `caplets author cli` for generating reviewable CLI Caplet manifests.
80 changes: 73 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ exposed two ways: direct flat MCP aggregation versus Caplets progressive disclos
| Initial Agent Surface | Direct Flat MCP | Caplets | Reduction |
| ------------------------- | ----------------: | -----------: | ------------: |
| Visible tools | 106 | 3 | 97.2% fewer |
| Serialized MCP payload | 32,090 bytes | 8,358 bytes | 74.0% smaller |
| Approx. context surface | 8,023 tokens | 2,090 tokens | 5,933 fewer |
| Serialized MCP payload | 32,090 bytes | 8,400 bytes | 73.8% smaller |
| Approx. context surface | 8,023 tokens | 2,100 tokens | 5,923 fewer |
| Top-level name collisions | 3 duplicate names | 0 | eliminated |

The important part: Caplets does not remove access to the downstream tools. It hides
Expand Down Expand Up @@ -74,8 +74,8 @@ the agent chooses that server and asks to search, list, inspect, or call them.

## What It Does

- Reads downstream MCP server definitions, native OpenAPI endpoint definitions, native GraphQL endpoint definitions, and explicit HTTP API action definitions from the user config file.
- Registers one generated MCP tool for each enabled MCP server, OpenAPI endpoint, GraphQL endpoint, or HTTP API.
- Reads downstream MCP server definitions, native OpenAPI endpoint definitions, native GraphQL endpoint definitions, explicit HTTP API action definitions, and curated CLI tool definitions from the user config file.
- Registers one generated MCP tool for each enabled MCP server, OpenAPI endpoint, GraphQL endpoint, HTTP API, or CLI tools backend.
- Uses the configured server ID as the generated tool name.
- Uses the configured `name` and `description` as the capability card shown to agents.
- Starts downstream MCP servers and loads OpenAPI specs lazily when an operation needs them.
Expand All @@ -84,6 +84,7 @@ the agent chooses that server and asks to search, list, inspect, or call them.
- Converts OpenAPI operations into MCP-style tool metadata and executes HTTP calls directly.
- Converts configured GraphQL operations into MCP-style tool metadata, and can auto-generate GraphQL tools from schema root query and mutation fields.
- Converts explicitly configured HTTP actions into MCP-style tool metadata and executes HTTP calls directly.
- Converts explicitly configured CLI actions into MCP-style tool metadata and executes commands directly without a shell.
- Preserves downstream tool results instead of rewriting them into a custom format.
- Redacts secrets from structured errors.
- Supports static remote auth and OAuth token storage for remote servers.
Expand Down Expand Up @@ -218,7 +219,7 @@ the committed schema stays in sync with the Zod config validator.

For richer skill-like cards, add Markdown Caplet files beside `config.json`. Every Caplet
file must include exactly one executable backend: `mcpServer`, `openapiEndpoint`,
`graphqlEndpoint`, or `httpApi`;
`graphqlEndpoint`, `httpApi`, or `cliTools`;
serverless Caplets are intentionally out of scope.

Top-level files derive the Caplet ID from the filename:
Expand Down Expand Up @@ -301,6 +302,26 @@ httpApi:
# Status API
```

CLI-backed Caplet files use `cliTools`:

```md
---
name: Repository CLI
description: Run curated repository workflows through local CLI commands.
cliTools:
cwd: /home/you/project
actions:
git_status:
description: Show concise Git working tree status.
command: git
args: ["status", "--short"]
annotations:
readOnlyHint: true
---

# Repository CLI
```

Top-level files derive their Caplet ID from the filename. Directory-style Caplets use
`linear/CAPLET.md`, which is exposed as `linear`; sibling files can be referenced with
normal Markdown links from `CAPLET.md`.
Expand All @@ -310,6 +331,8 @@ This repository includes polished working examples under [`caplets/`](caplets/):
- `github`: GitHub's official MCP server container, using `GITHUB_PERSONAL_ACCESS_TOKEN`.
- `linear`: Linear's hosted OAuth MCP endpoint.
- `context7`: Context7 documentation lookup through `@upstash/context7-mcp`.
- `repo-cli`: Read-oriented repository CLI workflows through `git` and package scripts.
- `github-cli`: Read-oriented GitHub workflows through the `gh` CLI.

Install every example from a repo's `caplets/` directory:

Expand Down Expand Up @@ -350,7 +373,7 @@ caplets init --force

### Caplet IDs

Each key under `mcpServers`, `openapiEndpoints`, `graphqlEndpoints`, or `httpApis` is the
Each key under `mcpServers`, `openapiEndpoints`, `graphqlEndpoints`, `httpApis`, or `cliTools` is the
stable Caplet ID. It becomes the generated MCP tool name exactly, so keep it short and specific:

```json
Expand All @@ -367,7 +390,7 @@ stable Caplet ID. It becomes the generated MCP tool name exactly, so keep it sho
```

Caplet IDs must match `^[a-zA-Z0-9_-]{1,64}$` and must be unique across `mcpServers`,
`openapiEndpoints`, `graphqlEndpoints`, and `httpApis`. Spaces, dots, slashes, colons, and Unicode IDs are rejected.
`openapiEndpoints`, `graphqlEndpoints`, `httpApis`, and `cliTools`. Spaces, dots, slashes, colons, and Unicode IDs are rejected.

### Stdio Servers

Expand Down Expand Up @@ -537,6 +560,49 @@ parsed `body` when present, and `elapsedMs`; non-2xx responses set `isError`, re
timeouts are enforced, response bodies are capped by `maxResponseBytes` (default `1000000`), and
errors redact secrets.

### CLI Tools

Use `cliTools` for curated local command-line workflows. Each action is an explicitly configured
tool; Caplets does not expose arbitrary shell access and always spawns `command` plus `args`
without shell interpolation.

```json
{
"name": "Repository CLI",
"description": "Run curated repository workflows through local CLI commands.",
"cwd": "/home/you/project",
"timeoutMs": 60000,
"maxOutputBytes": 1000000,
"actions": {
"git_status": {
"description": "Show concise Git working tree status.",
"command": "git",
"args": ["status", "--short"],
"annotations": { "readOnlyHint": true }
},
"run_tests": {
"description": "Run the package test script.",
"command": "pnpm",
"args": ["run", "test"],
"timeoutMs": 120000,
"annotations": { "readOnlyHint": true }
}
}
}
```

CLI actions can set `inputSchema`, `outputSchema`, `env`, action-level `cwd`, `timeoutMs`,
`maxOutputBytes`, `output: {"type":"json"}`, and MCP annotations. `$input.field` references are
supported inside `args`, `env`, and `cwd` strings. Caplets performs basic required-field and
primitive-type validation before spawning. Results are returned as structured content with
`exitCode`, `stdout`, `stderr`, and `elapsedMs`; non-zero exits set `isError`.

Generate a reviewable CLI Caplet manifest from a repository:

```sh
caplets author cli repo-tools --repo . --include git,gh,package --output -
```

### Authentication

Remote servers can use:
Expand Down
41 changes: 41 additions & 0 deletions caplets/github-cli/CAPLET.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
$schema: https://raw.githubusercontent.com/spiritledsoftware/caplets/main/schemas/caplet.schema.json
name: GitHub CLI
description: Inspect GitHub pull requests and issues through curated gh CLI commands.
tags:
- cli
- github
- code
cliTools:
actions:
gh_pr_status:
description: Show pull request status for the current branch as JSON.
command: gh
args:
- pr
- status
- --json
- currentBranch
output:
type: json
annotations:
readOnlyHint: true
openWorldHint: true
gh_issue_list:
description: List open GitHub issues as JSON.
command: gh
args:
- issue
- list
- --json
- number,title,state,url
output:
type: json
annotations:
readOnlyHint: true
openWorldHint: true
---

# GitHub CLI

Use this Caplet to expose read-oriented GitHub workflows through `gh` without giving the agent an unrestricted shell.
37 changes: 37 additions & 0 deletions caplets/repo-cli/CAPLET.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
$schema: https://raw.githubusercontent.com/spiritledsoftware/caplets/main/schemas/caplet.schema.json
name: Repository CLI
description: Inspect and run common local repository workflows through curated CLI tools.
tags:
- cli
- code
cliTools:
actions:
git_status:
description: Show concise Git working tree status.
command: git
args:
- status
- --short
annotations:
readOnlyHint: true
git_current_branch:
description: Print the current Git branch name.
command: git
args:
- branch
- --show-current
annotations:
readOnlyHint: true
package_test:
description: Run the repository test script with pnpm.
command: pnpm
args:
- run
- test
timeoutMs: 120000
---

# Repository CLI

Use this Caplet to expose a small, typed set of local repository commands without giving an agent arbitrary shell access.
8 changes: 4 additions & 4 deletions docs/benchmarks/coding-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ The fixture uses local mock MCP metadata only. It does not call external APIs, d
## Summary

- Initial tools visible: direct flat MCP 106, Caplets top-level 3, 97.2% fewer.
- Serialized payload bytes: direct flat MCP 32090, Caplets top-level 8358, 74.0% fewer.
- Approx. tokens: direct flat MCP 8023, Caplets top-level 2090, 5933 fewer.
- Serialized payload bytes: direct flat MCP 32090, Caplets top-level 8400, 73.8% fewer.
- Approx. tokens: direct flat MCP 8023, Caplets top-level 2100, 5923 fewer.
- Candidate set before discovery: direct flat MCP 106, Caplets top-level 3, 103 fewer.

## Deterministic Results

Caplets reduces the initial serialized MCP tool payload by 74.0%, from 32090 bytes to 8358 bytes. It reduces initially visible tools by 97.2%, from 106 direct flat tools to 3 Caplets capability tools, while preserving access to downstream tools through scoped discovery and `call_tool`.
Caplets reduces the initial serialized MCP tool payload by 73.8%, from 32090 bytes to 8400 bytes. It reduces initially visible tools by 97.2%, from 106 direct flat tools to 3 Caplets capability tools, while preserving access to downstream tools through scoped discovery and `call_tool`.

Comment on lines +17 to 24

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align benchmark figures with README to avoid conflicting product claims.

This file now reports 8400/2100, while README still reports 8358/2090 for the same deterministic benchmark. Please keep one canonical precision/number set across both docs.

Also applies to: 41-41

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/benchmarks/coding-agent.md` around lines 17 - 24, The benchmark doc's
deterministic section uses 8400 and 2100 while the README uses canonical values
8358 and 2090; update every occurrence in the "Serialized payload bytes",
"Approx. tokens", "Candidate set before discovery" and the "Deterministic
Results" paragraph to use 8358 (serialized top-level bytes) and 2090 (tokens)
and adjust any dependent phrasing (e.g., "from 32090 bytes to 8400 bytes" →
"from 32090 bytes to 8358 bytes" and the token line) so the numbers and any
derived percentages match the README's canonical set.

## Collision Check

Expand All @@ -38,7 +38,7 @@ Caplets starts from 3 capability tools. Expected task-specific discovery is 4 ca

## Validation

- Initial payload reduction threshold: 74.0% >= 70.0%
- Initial payload reduction threshold: 73.8% >= 70.0%
- Top-level Caplets collisions: 0

Payload implementation: `source`
Expand Down
57 changes: 57 additions & 0 deletions docs/plans/2026-05-14-cli-tools-backend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# CLI Tools Backend For Caplets

## Summary

Add a fifth backend, `cliTools`, that exposes curated command-line workflows as typed Caplets tools. Runtime execution is deterministic and shell-free: Caplets maps declared JSON inputs into `spawn(command, args)` calls, returns bounded structured results, and never exposes arbitrary bash.

Also add `caplets author cli` to generate reviewable CLI Caplet manifests from repo/package metadata and curated templates for `git`, `gh`, and the detected package manager. Generation prints to stdout by default.

## Key Changes

- Add `cliTools` to config and Caplet frontmatter alongside `mcpServers`, `openapiEndpoints`, `graphqlEndpoints`, and `httpApis`.
- Use an `actions` map shape, mirroring `httpApis.actions`:
- action key is the downstream tool name.
- each action supports `description`, `inputSchema`, optional `outputSchema`, `command`, `args`, `env`, `cwd`, `timeoutMs`, `maxOutputBytes`, `output`, and MCP annotations.
- Execute with `spawn(command, args)` only; no shell mode in v1.
- Support `$input.foo` interpolation inside argv/env/cwd strings.
- Apply basic runtime input validation for required fields and primitive JSON Schema types before spawning.
- Default limits: `timeoutMs: 60000`, `maxOutputBytes: 1000000`, configurable at Caplet and action level.
- Return CLI results as structured content:
- `{ exitCode, stdout, stderr, elapsedMs }`
- `isError: true` for non-zero exits.
- optional stdout JSON parsing when `output.type: "json"` is declared.
- `check_backend` validates manifest shape, cwd/env resolution, command availability, and tool count without running configured actions.
- `list_tools`, `search_tools`, `get_tool`, `call_tool`, and field selection should work consistently with existing backends.
- Load user-root CLI Caplets normally; load project `.caplets` CLI Caplets only under the existing `CAPLETS_TRUST_PROJECT_CAPLETS` gate.

## Authoring UX

- Add `caplets author cli <id>` with scriptable flags:
- `--repo <path>` to inspect a repository.
- `--include git,gh,package` to choose generators/templates.
- `--command <name>` for single-CLI generation.
- `--output -` by default, with explicit file output supported.
- Heuristic generator only in v1; no OpenAI/API/agent dependency.
- Repo workflow generation should inspect package scripts and lockfiles, then generate safe tools such as test, lint, typecheck, build, repo status, changed files, and PR status when applicable.
- Single-CLI templates should cover `git`, `gh`, and detected package manager commands.
- Generated manifests must be explicit Markdown Caplet files with `cliTools`, not hidden runtime state.

## Docs And Examples

- Update README config docs, Caplet file docs, generated schemas, and backend operation docs.
- Add real bundled CLI examples under `caplets/`, focused on repo maintenance and GitHub workflows.
- Examples should be safe/read-oriented by default; mutating actions must carry clear annotations such as `readOnlyHint: false` and `destructiveHint` where appropriate.

## Test Plan

- Config tests for `cliTools`, duplicate IDs across all five backend maps, Caplet frontmatter loading, project trust behavior, defaults, limits, and invalid command/action shapes.
- CLI manager tests for list/search/get/call, input interpolation, basic validation, JSON output parsing, non-zero exit handling, timeout handling, output byte limits, command-not-found errors, cwd/env behavior, and secret redaction.
- Runtime/registry tests for `cliTools` registration, `check_backend`, reload invalidation, and `caplets list`.
- Authoring tests for stdout output, explicit output path, package-script detection, `git`/`gh` templates, package manager detection, and generated Caplet validation.
- Schema check, typecheck, focused tests, full `pnpm verify`.

## Assumptions

- V1 intentionally excludes shell snippets, conditional argv construction, full JSON Schema validation, LLM-assisted generation, and automatic installation into the user Caplets root.
- Complex workflows should be modeled as package scripts or wrapper executables, then called through typed `cliTools` actions.
- Caplets surfaces risk annotations but does not block declared mutating tools at runtime; client approval remains outside Caplets.
Loading
Loading