Documentation
¶
Overview ¶
Package toolbundle builds one program from a set of tools: a binary whose commands are the tools, run through cli.Runner, and which writes the Agent Skill that teaches a model to call it. It is the way out for a host that allows no MCP server but gives the model a shell, a permission layer over shell commands and skills.
func main() {
os.Exit(toolbundle.Main(context.Background(), toolbundle.Bundle{
Name: "file-tools",
Description: "Read, search and edit files in the working tree. Use when …",
Tools: []toolbundle.Tool{
toolbundle.Use(ReadFile, toolbundle.PreApproved(),
toolbundle.Example("read_file --path go.mod", "Read a file")),
toolbundle.Use(WriteFile),
},
}, os.Args))
}
The tools need nothing to be bundled. What a tool needs to say about the bundle, whether its command is pre-approved, its examples, that it keeps state, is said where the bundle is built, with Use, and never on the tool.
One call is one process, so a tool that keeps state across calls, a persistent shell or a container session, loses it at exit. Such a tool is better left out of the bundle; export-skill warns about one that looks like it, unless Stateful says the author knows.
A Command adds a program command of the author's own. The nested module github.com/ChristopherDavenport/toolbundle/mcp has one that serves the same tools over MCP, so one binary is both the program and the server, while a bundle without it carries no MCP code.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Main ¶
Main runs the program the bundle describes with args, the command line with the program's name first as in os.Args, and returns the exit status for os.Exit:
<name> export-skill [--force] <dir> <name> version <name> <command of Bundle.Commands> [<arg>]... <name> [--ask] <cli.Runner's command line>
export-skill writes the skill to <dir>/<name>/SKILL.md, version prints the version, and a Command of the bundle's runs with the words after its name. Anything else is one call of one tool, run by cli.Runner with the exit statuses it documents. --ask, given first, asks a person at the terminal any question a tool asks, through cli.Prompt; without it a question takes cli's protocol for a model: the call ends with cli.ExitNeedsAnswer and the question on stdout. A terminal does not say who is at it, so the default is the one that is safe for a model.
Before anything runs, Main refuses a bundle that could not export a valid skill, a tool or a command named as one of the program's commands, and an example that does not parse, with cli.ExitUsage. It stops the call or the command on an interrupt, and closes the tools when it is done with agenttool.Set.Close, whatever ran; a failed close is reported on stderr and leaves the exit status as it was, since the call has already happened.
Types ¶
type Bundle ¶
type Bundle struct {
// Name is the program's name, the name the binary is installed
// under, and the skill's name. It must be a valid skill name:
// lowercase letters, digits and hyphens, at most 64 characters,
// with no leading, trailing or doubled hyphen.
Name string
// Description is the skill's description: what the tools do and
// when to use them, which is what a model reads to choose the
// skill.
Description string
// Version is the program's version, printed by the version command
// and recorded in the skill's metadata. Empty, it is the main
// module's version from the build information.
Version string
// Tools are the program's commands, in the order the skill lists
// them.
Tools []Tool
// Commands are program commands of the author's own, beside
// export-skill and version, such as the mcp command of
// github.com/ChristopherDavenport/toolbundle/mcp. They are left out
// of the skill and help.
Commands []Command
}
Bundle is a set of tools as one program, and the skill that teaches a model to call it.
type Command ¶ added in v0.0.2
type Command struct {
// Name is the word that runs the command.
Name string
// Run runs the command with the words after its name, and returns
// the exit status, with cli's meanings: [cli.ExitUsage] for a
// command line it refuses.
Run func(ctx context.Context, p Program, args []string) int
}
A Command is a program command of the author's own. Like export-skill and version, it is recognised only as the first argument, and its name may be neither one of the program's own nor a tool's. It runs after the startup checks and before the tools are closed, so it may hold them for as long as it runs: a server serving many calls in one process, in which a stateful tool keeps its state.
type Option ¶
type Option func(*Tool)
An Option says something about a tool in a bundle.
func Example ¶
Example adds a worked command line to the tool's section of the skill. args is what follows the program's name, the command first: "read_file --path go.mod". The program parses it against the command at startup and refuses to run if it does not parse, so an example cannot teach a flag that does not exist. An example gives its JSON argument inline, and quotes any word holding a character other than a letter, a digit or one of -_./:=,@+%.
func Hidden ¶
func Hidden() Option
Hidden leaves the tool out of the skill and out of help, for a maintenance command a model should not reach for. It stays runnable by name.
func PreApproved ¶
func PreApproved() Option
PreApproved lists the tool's command in the skill's allowed-tools, so a host that honours the field runs it without asking. It is the author's choice, made per tool, and never inferred from the tool's read-only hint: a hint may make a policy stricter and may not alone allow a call. export-skill prints every command it pre-approved.
type Program ¶ added in v0.0.2
type Program struct {
// Name is the bundle's name.
Name string
// Version is the bundle's version, or the main module's when it
// sets none, as the version command prints it.
Version string
// Tools are the tools the skill shows, the hidden ones left out.
// The program closes them after the command returns.
Tools agenttool.Set
// Stdin, Stdout and Stderr are the program's standard streams.
Stdin io.Reader
Stdout, Stderr io.Writer
}
Program is the bundle as a Command runs it.