Loading Extensions
# Loading Extensions
## Auto-discovery
Kit automatically discovers and loads extensions from these paths, in order:
| Path | Scope |
|------|-------|
| `~/.config/kit/extensions/*.go` | Global single files |
| `~/.config/kit/extensions/*/main.go` | Global subdirectory extensions |
| `.kit/extensions/*.go` | Project-local single files |
| `.kit/extensions/*/main.go` | Project-local subdirectory extensions |
| `~/.local/share/kit/git/` | Global git-installed packages |
| `.kit/git/` | Project-local git-installed packages |
## Explicit loading
Load extensions by path using the `-e` flag:
```bash
kit -e path/to/extension.go
```
Load multiple extensions:
```bash
kit -e ext1.go -e ext2.go
```
## Disabling extensions
Disable all auto-discovered extensions:
```bash
kit --no-extensions
```
You can combine `--no-extensions` with `-e` to load only specific extensions:
```bash
kit --no-extensions -e my-extension.go
```
## Installing from git
Install extensions from git repositories using `kit install`:
```bash
# Install globally (to ~/.local/share/kit/git/)
kit install https://github.com/user/my-kit-extension.git
# Install project-locally (to .kit/git/)
kit install -l https://github.com/user/my-kit-extension.git
# Update an installed package
kit install -u https://github.com/user/my-kit-extension.git
# Remove
kit install --uninstall my-kit-extension
```
## Extension structure
### Single-file extensions
A single `.go` file with an `Init` function:
```go
//go:build ignore
package main
import "kit/ext"
func Init(api ext.API) {
// register handlers, tools, commands, etc.
}
```
The `//go:build ignore` directive prevents the Go toolchain from trying to compile the file as part of a normal build.
### Subdirectory extensions
For more complex extensions, create a directory with a `main.go` entry point:
```
.kit/extensions/my-extension/
├── main.go # Must contain Init(api ext.API)
├── helpers.go # Additional source files
└── config.go
```
### Package-level state
Yaegi supports package-level variables captured in closures. This is the standard way to maintain state across event callbacks:
```go
package main
import "kit/ext"
var callCount int
func Init(api ext.API) {
api.OnToolCall(func(_ ext.ToolCallEvent, ctx ext.Context) {
callCount++
ctx.SetFooter(ext.HeaderFooterConfig{
Content: ext.WidgetContent{
Text: fmt.Sprintf("Tools called: %d", callCount),
},
})
})
}
```