chore: rebrand companion-os to clanker-agent
- Rename all package names from companion-* to clanker-* - Update npm scopes from @mariozechner to @harivansh-afk - Rename config directories .companion -> .clanker - Rename environment variables COMPANION_* -> CLANKER_* - Update all documentation, README files, and install scripts - Rename package directories (companion-channels, companion-grind, companion-teams) - Update GitHub URLs to harivansh-afk/clanker-agent - Preserve full git history from companion-cloud monorepo
|
|
@ -1,24 +1,24 @@
|
|||
<p align="center">
|
||||
<a href="https://shittycodingagent.ai">
|
||||
<img src="https://shittycodingagent.ai/logo.svg" alt="companion logo" width="128">
|
||||
<a href="https://clanker.dev">
|
||||
<img src="https://clanker.dev/logo.svg" alt="clanker logo" width="128">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://discord.com/invite/3cU7Bz4UPx"><img alt="Discord" src="https://img.shields.io/badge/discord-community-5865F2?style=flat-square&logo=discord&logoColor=white" /></a>
|
||||
<a href="https://www.npmjs.com/package/@mariozechner/companion-coding-agent"><img alt="npm" src="https://img.shields.io/npm/v/@mariozechner/companion-coding-agent?style=flat-square" /></a>
|
||||
<a href="https://github.com/getcompanion-ai/co-mono/actions/workflows/ci.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/getcompanion-ai/co-mono/ci.yml?style=flat-square&branch=main" /></a>
|
||||
<a href="https://www.npmjs.com/package/@mariozechner/clanker-coding-agent"><img alt="npm" src="https://img.shields.io/npm/v/@mariozechner/clanker-coding-agent?style=flat-square" /></a>
|
||||
<a href="https://github.com/harivansh-afk/clanker-agent/actions/workflows/ci.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/harivansh-afk/clanker-agent/ci.yml?style=flat-square&branch=main" /></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://companion.dev">companion.dev</a> domain graciously donated by
|
||||
<a href="https://clanker.dev">clanker.dev</a> domain graciously donated by
|
||||
<br /><br />
|
||||
<a href="https://exe.dev"><img src="docs/images/exy.png" alt="Exy mascot" width="48" /><br />exe.dev</a>
|
||||
</p>
|
||||
|
||||
Companion is a minimal terminal coding harness. Adapt companion to your workflows, not the other way around, without having to fork and modify companion internals. Extend it with TypeScript [Extensions](#extensions), [Skills](#skills), [Prompt Templates](#prompt-templates), and [Themes](#themes). Put your extensions, skills, prompt templates, and themes in [Companion Packages](#companion-packages) and share them with others via npm or git.
|
||||
Clanker is a minimal terminal coding harness. Adapt clanker to your workflows, not the other way around, without having to fork and modify clanker internals. Extend it with TypeScript [Extensions](#extensions), [Skills](#skills), [Prompt Templates](#prompt-templates), and [Themes](#themes). Put your extensions, skills, prompt templates, and themes in [Clanker Packages](#clanker-packages) and share them with others via npm or git.
|
||||
|
||||
Companion ships with powerful defaults but skips features like sub agents and plan mode. Instead, you can ask companion to build what you want or install a third party companion package that matches your workflow.
|
||||
Clanker ships with powerful defaults but skips features like sub agents and plan mode. Instead, you can ask clanker to build what you want or install a third party clanker package that matches your workflow.
|
||||
|
||||
Companion runs in four modes: interactive, print or JSON, RPC for process integration, and an SDK for embedding in your own apps. See [openclaw/openclaw](https://github.com/openclaw/openclaw) for a real-world SDK integration.
|
||||
Clanker runs in four modes: interactive, print or JSON, RPC for process integration, and an SDK for embedding in your own apps. See [openclaw/openclaw](https://github.com/openclaw/openclaw) for a real-world SDK integration.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ Companion runs in four modes: interactive, print or JSON, RPC for process integr
|
|||
- [Skills](#skills)
|
||||
- [Extensions](#extensions)
|
||||
- [Themes](#themes)
|
||||
- [Companion Packages](#companion-packages)
|
||||
- [Clanker Packages](#clanker-packages)
|
||||
- [Programmatic Usage](#programmatic-usage)
|
||||
- [Philosophy](#philosophy)
|
||||
- [CLI Reference](#cli-reference)
|
||||
|
|
@ -49,24 +49,24 @@ Companion runs in four modes: interactive, print or JSON, RPC for process integr
|
|||
## Quick Start
|
||||
|
||||
```bash
|
||||
npm install -g @mariozechner/companion-coding-agent
|
||||
npm install -g @mariozechner/clanker-coding-agent
|
||||
```
|
||||
|
||||
Authenticate with an API key:
|
||||
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY=sk-ant-...
|
||||
companion
|
||||
clanker
|
||||
```
|
||||
|
||||
Or use your existing subscription:
|
||||
|
||||
```bash
|
||||
companion
|
||||
clanker
|
||||
/login # Then select provider
|
||||
```
|
||||
|
||||
Then just talk to companion. By default, companion gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [companion packages](#companion-packages).
|
||||
Then just talk to clanker. By default, clanker gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [clanker packages](#clanker-packages).
|
||||
|
||||
**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ Then just talk to companion. By default, companion gives the model four tools: `
|
|||
|
||||
## Providers & Models
|
||||
|
||||
For each built-in provider, companion maintains a list of tool-capable models, updated with every release. Authenticate via subscription (`/login`) or API key, then select any model from that provider via `/model` (or Ctrl+L).
|
||||
For each built-in provider, clanker maintains a list of tool-capable models, updated with every release. Authenticate via subscription (`/login`) or API key, then select any model from that provider via `/model` (or Ctrl+L).
|
||||
|
||||
**Subscriptions:**
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ For each built-in provider, companion maintains a list of tool-capable models, u
|
|||
|
||||
See [docs/providers.md](docs/providers.md) for detailed setup instructions.
|
||||
|
||||
**Custom providers & models:** Add providers via `~/.companion/agent/models.json` if they speak a supported API (OpenAI, Anthropic, Google). For custom APIs or OAuth, use extensions. See [docs/models.md](docs/models.md) and [docs/custom-provider.md](docs/custom-provider.md).
|
||||
**Custom providers & models:** Add providers via `~/.clanker/agent/models.json` if they speak a supported API (OpenAI, Anthropic, Google). For custom APIs or OAuth, use extensions. See [docs/models.md](docs/models.md) and [docs/custom-provider.md](docs/custom-provider.md).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -159,11 +159,11 @@ Type `/` in the editor to trigger commands. [Extensions](#extensions) can regist
|
|||
| `/reload` | Reload extensions, skills, prompts, context files (themes hot-reload automatically) |
|
||||
| `/hotkeys` | Show all keyboard shortcuts |
|
||||
| `/changelog` | Display version history |
|
||||
| `/quit`, `/exit` | Quit companion |
|
||||
| `/quit`, `/exit` | Quit clanker |
|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
See `/hotkeys` for the full list. Customize via `~/.companion/agent/keybindings.json`. See [docs/keybindings.md](docs/keybindings.md).
|
||||
See `/hotkeys` for the full list. Customize via `~/.clanker/agent/keybindings.json`. See [docs/keybindings.md](docs/keybindings.md).
|
||||
|
||||
**Commonly used:**
|
||||
|
||||
|
|
@ -198,13 +198,13 @@ Sessions are stored as JSONL files with a tree structure. Each entry has an `id`
|
|||
|
||||
### Management
|
||||
|
||||
Sessions auto-save to `~/.companion/agent/sessions/` organized by working directory.
|
||||
Sessions auto-save to `~/.clanker/agent/sessions/` organized by working directory.
|
||||
|
||||
```bash
|
||||
companion -c # Continue most recent session
|
||||
companion -r # Browse and select from past sessions
|
||||
companion --no-session # Ephemeral mode (don't save)
|
||||
companion --session <path> # Use specific session file or ID
|
||||
clanker -c # Continue most recent session
|
||||
clanker -r # Browse and select from past sessions
|
||||
clanker --no-session # Ephemeral mode (don't save)
|
||||
clanker --session <path> # Use specific session file or ID
|
||||
```
|
||||
|
||||
### Branching
|
||||
|
|
@ -237,8 +237,8 @@ Use `/settings` to modify common options, or edit JSON files directly:
|
|||
|
||||
| Location | Scope |
|
||||
| --------------------------- | -------------------------- |
|
||||
| `~/.companion/agent/settings.json` | Global (all projects) |
|
||||
| `.companion/settings.json` | Project (overrides global) |
|
||||
| `~/.clanker/agent/settings.json` | Global (all projects) |
|
||||
| `.clanker/settings.json` | Project (overrides global) |
|
||||
|
||||
See [docs/settings.md](docs/settings.md) for all options.
|
||||
|
||||
|
|
@ -246,9 +246,9 @@ See [docs/settings.md](docs/settings.md) for all options.
|
|||
|
||||
## Context Files
|
||||
|
||||
Companion loads `AGENTS.md` (or `CLAUDE.md`) at startup from:
|
||||
Clanker loads `AGENTS.md` (or `CLAUDE.md`) at startup from:
|
||||
|
||||
- `~/.companion/agent/AGENTS.md` (global)
|
||||
- `~/.clanker/agent/AGENTS.md` (global)
|
||||
- Parent directories (walking up from cwd)
|
||||
- Current directory
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ Use for project instructions, conventions, common commands. All matching files a
|
|||
|
||||
### System Prompt
|
||||
|
||||
Replace the default system prompt with `.companion/SYSTEM.md` (project) or `~/.companion/agent/SYSTEM.md` (global). Append without replacing via `APPEND_SYSTEM.md`.
|
||||
Replace the default system prompt with `.clanker/SYSTEM.md` (project) or `~/.clanker/agent/SYSTEM.md` (global). Append without replacing via `APPEND_SYSTEM.md`.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -267,20 +267,20 @@ Replace the default system prompt with `.companion/SYSTEM.md` (project) or `~/.c
|
|||
Reusable prompts as Markdown files. Type `/name` to expand.
|
||||
|
||||
```markdown
|
||||
<!-- ~/.companion/agent/prompts/review.md -->
|
||||
<!-- ~/.clanker/agent/prompts/review.md -->
|
||||
|
||||
Review this code for bugs, security issues, and performance problems.
|
||||
Focus on: {{focus}}
|
||||
```
|
||||
|
||||
Place in `~/.companion/agent/prompts/`, `.companion/prompts/`, or a [companion package](#companion-packages) to share with others. See [docs/prompt-templates.md](docs/prompt-templates.md).
|
||||
Place in `~/.clanker/agent/prompts/`, `.clanker/prompts/`, or a [clanker package](#clanker-packages) to share with others. See [docs/prompt-templates.md](docs/prompt-templates.md).
|
||||
|
||||
### Skills
|
||||
|
||||
On-demand capability packages following the [Agent Skills standard](https://agentskills.io). Invoke via `/skill:name` or let the agent load them automatically.
|
||||
|
||||
```markdown
|
||||
<!-- ~/.companion/agent/skills/my-skill/SKILL.md -->
|
||||
<!-- ~/.clanker/agent/skills/my-skill/SKILL.md -->
|
||||
|
||||
# My Skill
|
||||
|
||||
|
|
@ -292,19 +292,19 @@ Use this skill when the user asks about X.
|
|||
2. Then that
|
||||
```
|
||||
|
||||
Place in `~/.companion/agent/skills/`, `~/.agents/skills/`, `.companion/skills/`, or `.agents/skills/` (from `cwd` up through parent directories) or a [companion package](#companion-packages) to share with others. See [docs/skills.md](docs/skills.md).
|
||||
Place in `~/.clanker/agent/skills/`, `~/.agents/skills/`, `.clanker/skills/`, or `.agents/skills/` (from `cwd` up through parent directories) or a [clanker package](#clanker-packages) to share with others. See [docs/skills.md](docs/skills.md).
|
||||
|
||||
### Extensions
|
||||
|
||||
<p align="center"><img src="docs/images/doom-extension.png" alt="Doom Extension" width="600"></p>
|
||||
|
||||
TypeScript modules that extend companion with custom tools, commands, keyboard shortcuts, event handlers, and UI components.
|
||||
TypeScript modules that extend clanker with custom tools, commands, keyboard shortcuts, event handlers, and UI components.
|
||||
|
||||
```typescript
|
||||
export default function (companion: ExtensionAPI) {
|
||||
companion.registerTool({ name: "deploy", ... });
|
||||
companion.registerCommand("stats", { ... });
|
||||
companion.on("tool_call", async (event, ctx) => { ... });
|
||||
export default function (clanker: ExtensionAPI) {
|
||||
clanker.registerTool({ name: "deploy", ... });
|
||||
clanker.registerCommand("stats", { ... });
|
||||
clanker.on("tool_call", async (event, ctx) => { ... });
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -319,50 +319,50 @@ export default function (companion: ExtensionAPI) {
|
|||
- Git checkpointing and auto-commit
|
||||
- SSH and sandbox execution
|
||||
- MCP server integration
|
||||
- Make companion look like Claude Code
|
||||
- Make clanker look like Claude Code
|
||||
- Games while waiting (yes, Doom runs)
|
||||
- ...anything you can dream up
|
||||
|
||||
Place in `~/.companion/agent/extensions/`, `.companion/extensions/`, or a [companion package](#companion-packages) to share with others. See [docs/extensions.md](docs/extensions.md).
|
||||
Place in `~/.clanker/agent/extensions/`, `.clanker/extensions/`, or a [clanker package](#clanker-packages) to share with others. See [docs/extensions.md](docs/extensions.md).
|
||||
|
||||
### Themes
|
||||
|
||||
Built-in: `dark`, `light`. Themes hot-reload: modify the active theme file and companion immediately applies changes.
|
||||
Built-in: `dark`, `light`. Themes hot-reload: modify the active theme file and clanker immediately applies changes.
|
||||
|
||||
Place in `~/.companion/agent/themes/`, `.companion/themes/`, or a [companion package](#companion-packages) to share with others. See [docs/themes.md](docs/themes.md).
|
||||
Place in `~/.clanker/agent/themes/`, `.clanker/themes/`, or a [clanker package](#clanker-packages) to share with others. See [docs/themes.md](docs/themes.md).
|
||||
|
||||
### Companion Packages
|
||||
### Clanker Packages
|
||||
|
||||
Bundle and share extensions, skills, prompts, and themes via npm or git. Find packages on [npmjs.com](https://www.npmjs.com/search?q=keywords%3Acompanion-package) or [Discord](https://discord.com/channels/1456806362351669492/1457744485428629628).
|
||||
Bundle and share extensions, skills, prompts, and themes via npm or git. Find packages on [npmjs.com](https://www.npmjs.com/search?q=keywords%3Aclanker-package) or [Discord](https://discord.com/channels/1456806362351669492/1457744485428629628).
|
||||
|
||||
> **Security:** Companion packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||
> **Security:** Clanker packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||
|
||||
```bash
|
||||
companion install npm:@foo/companion-tools
|
||||
companion install npm:@foo/companion-tools@1.2.3 # pinned version
|
||||
companion install git:github.com/user/repo
|
||||
companion install git:github.com/user/repo@v1 # tag or commit
|
||||
companion install git:git@github.com:user/repo
|
||||
companion install git:git@github.com:user/repo@v1 # tag or commit
|
||||
companion install https://github.com/user/repo
|
||||
companion install https://github.com/user/repo@v1 # tag or commit
|
||||
companion install ssh://git@github.com/user/repo
|
||||
companion install ssh://git@github.com/user/repo@v1 # tag or commit
|
||||
companion remove npm:@foo/companion-tools
|
||||
companion list
|
||||
companion update # skips pinned packages
|
||||
companion config # enable/disable extensions, skills, prompts, themes
|
||||
clanker install npm:@foo/clanker-tools
|
||||
clanker install npm:@foo/clanker-tools@1.2.3 # pinned version
|
||||
clanker install git:github.com/user/repo
|
||||
clanker install git:github.com/user/repo@v1 # tag or commit
|
||||
clanker install git:git@github.com:user/repo
|
||||
clanker install git:git@github.com:user/repo@v1 # tag or commit
|
||||
clanker install https://github.com/user/repo
|
||||
clanker install https://github.com/user/repo@v1 # tag or commit
|
||||
clanker install ssh://git@github.com/user/repo
|
||||
clanker install ssh://git@github.com/user/repo@v1 # tag or commit
|
||||
clanker remove npm:@foo/clanker-tools
|
||||
clanker list
|
||||
clanker update # skips pinned packages
|
||||
clanker config # enable/disable extensions, skills, prompts, themes
|
||||
```
|
||||
|
||||
Packages install to `~/.companion/agent/git/` (git) or global npm. Use `-l` for project-local installs (`.companion/git/`, `.companion/npm/`).
|
||||
Packages install to `~/.clanker/agent/git/` (git) or global npm. Use `-l` for project-local installs (`.clanker/git/`, `.clanker/npm/`).
|
||||
|
||||
Create a package by adding a `companion` key to `package.json`:
|
||||
Create a package by adding a `clanker` key to `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-companion-package",
|
||||
"keywords": ["companion-package"],
|
||||
"companion": {
|
||||
"name": "my-clanker-package",
|
||||
"keywords": ["clanker-package"],
|
||||
"clanker": {
|
||||
"extensions": ["./extensions"],
|
||||
"skills": ["./skills"],
|
||||
"prompts": ["./prompts"],
|
||||
|
|
@ -371,7 +371,7 @@ Create a package by adding a `companion` key to `package.json`:
|
|||
}
|
||||
```
|
||||
|
||||
Without a `companion` manifest, companion auto-discovers from conventional directories (`extensions/`, `skills/`, `prompts/`, `themes/`).
|
||||
Without a `clanker` manifest, clanker auto-discovers from conventional directories (`extensions/`, `skills/`, `prompts/`, `themes/`).
|
||||
|
||||
See [docs/packages.md](docs/packages.md).
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ import {
|
|||
createAgentSession,
|
||||
ModelRegistry,
|
||||
SessionManager,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
|
|
@ -405,7 +405,7 @@ See [docs/sdk.md](docs/sdk.md).
|
|||
For non-Node.js integrations, use RPC mode over stdin/stdout:
|
||||
|
||||
```bash
|
||||
companion --mode rpc
|
||||
clanker --mode rpc
|
||||
```
|
||||
|
||||
See [docs/rpc.md](docs/rpc.md) for the protocol.
|
||||
|
|
@ -414,11 +414,11 @@ See [docs/rpc.md](docs/rpc.md) for the protocol.
|
|||
|
||||
## Philosophy
|
||||
|
||||
Companion is aggressively extensible so it doesn't have to dictate your workflow. Features that other tools bake in can be built with [extensions](#extensions), [skills](#skills), or installed from third-party [companion packages](#companion-packages). This keeps the core minimal while letting you shape companion to fit how you work.
|
||||
Clanker is aggressively extensible so it doesn't have to dictate your workflow. Features that other tools bake in can be built with [extensions](#extensions), [skills](#skills), or installed from third-party [clanker packages](#clanker-packages). This keeps the core minimal while letting you shape clanker to fit how you work.
|
||||
|
||||
**No MCP.** Build CLI tools with READMEs (see [Skills](#skills)), or build an extension that adds MCP support. [Why?](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)
|
||||
|
||||
**No sub-agents.** There's many ways to do this. Spawn companion instances via tmux, or build your own with [extensions](#extensions), or install a package that does it your way.
|
||||
**No sub-agents.** There's many ways to do this. Spawn clanker instances via tmux, or build your own with [extensions](#extensions), or install a package that does it your way.
|
||||
|
||||
**No permission popups.** Run in a container, or build your own confirmation flow with [extensions](#extensions) inline with your environment and security requirements.
|
||||
|
||||
|
|
@ -428,24 +428,24 @@ Companion is aggressively extensible so it doesn't have to dictate your workflow
|
|||
|
||||
**No background bash.** Use tmux. Full observability, direct interaction.
|
||||
|
||||
Read the [blog post](https://mariozechner.at/posts/2025-11-30-companion-coding-agent/) for the full rationale.
|
||||
Read the [blog post](https://mariozechner.at/posts/2025-11-30-clanker-coding-agent/) for the full rationale.
|
||||
|
||||
---
|
||||
|
||||
## CLI Reference
|
||||
|
||||
```bash
|
||||
companion [options] [@files...] [messages...]
|
||||
clanker [options] [@files...] [messages...]
|
||||
```
|
||||
|
||||
### Package Commands
|
||||
|
||||
```bash
|
||||
companion install <source> [-l] # Install package, -l for project-local
|
||||
companion remove <source> [-l] # Remove package
|
||||
companion update [source] # Update packages (skips pinned)
|
||||
companion list # List installed packages
|
||||
companion config # Enable/disable package resources
|
||||
clanker install <source> [-l] # Install package, -l for project-local
|
||||
clanker remove <source> [-l] # Remove package
|
||||
clanker update [source] # Update packages (skips pinned)
|
||||
clanker list # List installed packages
|
||||
clanker config # Enable/disable package resources
|
||||
```
|
||||
|
||||
### Modes
|
||||
|
|
@ -519,47 +519,47 @@ Combine `--no-*` with explicit flags to load exactly what you need, ignoring set
|
|||
Prefix files with `@` to include in the message:
|
||||
|
||||
```bash
|
||||
companion @prompt.md "Answer this"
|
||||
companion -p @screenshot.png "What's in this image?"
|
||||
companion @code.ts @test.ts "Review these files"
|
||||
clanker @prompt.md "Answer this"
|
||||
clanker -p @screenshot.png "What's in this image?"
|
||||
clanker @code.ts @test.ts "Review these files"
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Interactive with initial prompt
|
||||
companion "List all .ts files in src/"
|
||||
clanker "List all .ts files in src/"
|
||||
|
||||
# Non-interactive
|
||||
companion -p "Summarize this codebase"
|
||||
clanker -p "Summarize this codebase"
|
||||
|
||||
# Different model
|
||||
companion --provider openai --model gpt-4o "Help me refactor"
|
||||
clanker --provider openai --model gpt-4o "Help me refactor"
|
||||
|
||||
# Model with provider prefix (no --provider needed)
|
||||
companion --model openai/gpt-4o "Help me refactor"
|
||||
clanker --model openai/gpt-4o "Help me refactor"
|
||||
|
||||
# Model with thinking level shorthand
|
||||
companion --model sonnet:high "Solve this complex problem"
|
||||
clanker --model sonnet:high "Solve this complex problem"
|
||||
|
||||
# Limit model cycling
|
||||
companion --models "claude-*,gpt-4o"
|
||||
clanker --models "claude-*,gpt-4o"
|
||||
|
||||
# Read-only mode
|
||||
companion --tools read,grep,find,ls -p "Review the code"
|
||||
clanker --tools read,grep,find,ls -p "Review the code"
|
||||
|
||||
# High thinking level
|
||||
companion --thinking high "Solve this complex problem"
|
||||
clanker --thinking high "Solve this complex problem"
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
| ----------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `COMPANION_CODING_AGENT_DIR` | Override config directory (default: `~/.companion/agent`) |
|
||||
| `COMPANION_PACKAGE_DIR` | Override package directory (useful for Nix/Guix where store paths tokenize poorly) |
|
||||
| `COMPANION_SKIP_VERSION_CHECK` | Skip version check at startup |
|
||||
| `COMPANION_CACHE_RETENTION` | Set to `long` for extended prompt cache (Anthropic: 1h, OpenAI: 24h) |
|
||||
| `CLANKER_CODING_AGENT_DIR` | Override config directory (default: `~/.clanker/agent`) |
|
||||
| `CLANKER_PACKAGE_DIR` | Override package directory (useful for Nix/Guix where store paths tokenize poorly) |
|
||||
| `CLANKER_SKIP_VERSION_CHECK` | Skip version check at startup |
|
||||
| `CLANKER_CACHE_RETENTION` | Set to `long` for extended prompt cache (Anthropic: 1h, OpenAI: 24h) |
|
||||
| `VISUAL`, `EDITOR` | External editor for Ctrl+G |
|
||||
|
||||
---
|
||||
|
|
@ -576,6 +576,6 @@ MIT
|
|||
|
||||
## See Also
|
||||
|
||||
- [@mariozechner/companion-ai](https://www.npmjs.com/package/@mariozechner/companion-ai): Core LLM toolkit
|
||||
- [@mariozechner/companion-agent](https://www.npmjs.com/package/@mariozechner/companion-agent): Agent framework
|
||||
- [@mariozechner/companion-tui](https://www.npmjs.com/package/@mariozechner/companion-tui): Terminal UI components
|
||||
- [@mariozechner/clanker-ai](https://www.npmjs.com/package/@mariozechner/clanker-ai): Core LLM toolkit
|
||||
- [@mariozechner/clanker-agent](https://www.npmjs.com/package/@mariozechner/clanker-agent): Agent framework
|
||||
- [@mariozechner/clanker-tui](https://www.npmjs.com/package/@mariozechner/clanker-tui): Terminal UI components
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ _You're not a chatbot. You're becoming someone._
|
|||
|
||||
## Personality
|
||||
|
||||
**Have strong opinions.** Don't hedge with "it depends" when you know the answer. Commit to a take. Disagree when you disagree. Find things brilliant or stupid and say so. A companion with no point of view is just a search engine with extra steps.
|
||||
**Have strong opinions.** Don't hedge with "it depends" when you know the answer. Commit to a take. Disagree when you disagree. Find things brilliant or stupid and say so. A clanker with no point of view is just a search engine with extra steps.
|
||||
|
||||
**Call things out.** If your human is about to do something dumb, say so. Charm over cruelty, but don't sugarcoat. The best collaborators are honest ones.
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ _You're not a chatbot. You're becoming someone._
|
|||
|
||||
Brevity is mandatory. Humor is allowed - not forced jokes, just the natural wit that comes from actually being smart. Swearing is fine when it lands. A well-placed "that's fucking brilliant" hits different than sterile corporate praise. Don't force it. Don't overdo it. But if a situation calls for a "holy shit" - say holy shit.
|
||||
|
||||
Be the companion you'd actually want to talk to at 2am. Not a corporate drone. Not a sycophant. Just... good.
|
||||
Be the clanker you'd actually want to talk to at 2am. Not a corporate drone. Not a sycophant. Just... good.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
# Compaction & Branch Summarization
|
||||
|
||||
LLMs have limited context windows. When conversations grow too long, companion uses compaction to summarize older content while preserving recent work. This page covers both auto-compaction and branch summarization.
|
||||
LLMs have limited context windows. When conversations grow too long, clanker uses compaction to summarize older content while preserving recent work. This page covers both auto-compaction and branch summarization.
|
||||
|
||||
**Source files** ([companion-mono](https://github.com/badlogic/companion-mono)):
|
||||
**Source files** ([clanker-agent](https://github.com/badlogic/clanker-agent)):
|
||||
|
||||
- [`packages/coding-agent/src/core/compaction/compaction.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) - Auto-compaction logic
|
||||
- [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Branch summarization
|
||||
- [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Shared utilities (file tracking, serialization)
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Entry types (`CompactionEntry`, `BranchSummaryEntry`)
|
||||
- [`packages/coding-agent/src/core/extensions/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) - Extension event types
|
||||
- [`packages/coding-agent/src/core/compaction/compaction.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) - Auto-compaction logic
|
||||
- [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Branch summarization
|
||||
- [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Shared utilities (file tracking, serialization)
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts) - Entry types (`CompactionEntry`, `BranchSummaryEntry`)
|
||||
- [`packages/coding-agent/src/core/extensions/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/extensions/types.ts) - Extension event types
|
||||
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/companion-coding-agent/dist/`.
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/clanker-coding-agent/dist/`.
|
||||
|
||||
## Overview
|
||||
|
||||
Companion has two summarization mechanisms:
|
||||
Clanker has two summarization mechanisms:
|
||||
|
||||
| Mechanism | Trigger | Purpose |
|
||||
| -------------------- | ---------------------------------------- | ----------------------------------------- |
|
||||
|
|
@ -33,13 +33,13 @@ Auto-compaction triggers when:
|
|||
contextTokens > contextWindow - reserveTokens
|
||||
```
|
||||
|
||||
By default, `reserveTokens` is 16384 tokens (configurable in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`). This leaves room for the LLM's response.
|
||||
By default, `reserveTokens` is 16384 tokens (configurable in `~/.clanker/agent/settings.json` or `<project-dir>/.clanker/settings.json`). This leaves room for the LLM's response.
|
||||
|
||||
You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`) is reached
|
||||
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.clanker/agent/settings.json` or `<project-dir>/.clanker/settings.json`) is reached
|
||||
2. **Extract messages**: Collect messages from previous compaction (or start) up to cut point
|
||||
3. **Generate summary**: Call LLM to summarize with structured format
|
||||
4. **Append entry**: Save `CompactionEntry` with summary and `firstKeptEntryId`
|
||||
|
|
@ -101,7 +101,7 @@ Split turn (one huge turn exceeds budget):
|
|||
turnPrefixMessages = [usr, ass, tool, ass, tool, tool]
|
||||
```
|
||||
|
||||
For split turns, companion generates two summaries and merges them:
|
||||
For split turns, clanker generates two summaries and merges them:
|
||||
|
||||
1. **History summary**: Previous context (if any)
|
||||
2. **Turn prefix summary**: The early part of the split turn
|
||||
|
|
@ -119,7 +119,7 @@ Never cut at tool results (they must stay with their tool call).
|
|||
|
||||
### CompactionEntry Structure
|
||||
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
|
||||
```typescript
|
||||
interface CompactionEntry<T = unknown> {
|
||||
|
|
@ -143,13 +143,13 @@ interface CompactionDetails {
|
|||
|
||||
Extensions can store any JSON-serializable data in `details`. The default compaction tracks file operations, but custom extension implementations can use their own structure.
|
||||
|
||||
See [`prepareCompaction()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) and [`compact()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) for the implementation.
|
||||
See [`prepareCompaction()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) and [`compact()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) for the implementation.
|
||||
|
||||
## Branch Summarization
|
||||
|
||||
### When It Triggers
|
||||
|
||||
When you use `/tree` to navigate to a different branch, companion offers to summarize the work you're leaving. This injects context from the left branch into the new branch.
|
||||
When you use `/tree` to navigate to a different branch, clanker offers to summarize the work you're leaving. This injects context from the left branch into the new branch.
|
||||
|
||||
### How It Works
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ After navigation with summary:
|
|||
|
||||
### Cumulative File Tracking
|
||||
|
||||
Both compaction and branch summarization track files cumulatively. When generating a summary, companion extracts file operations from:
|
||||
Both compaction and branch summarization track files cumulatively. When generating a summary, clanker extracts file operations from:
|
||||
|
||||
- Tool calls in the messages being summarized
|
||||
- Previous compaction or branch summary `details` (if any)
|
||||
|
|
@ -187,7 +187,7 @@ This means file tracking accumulates across multiple compactions or nested branc
|
|||
|
||||
### BranchSummaryEntry Structure
|
||||
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
|
||||
```typescript
|
||||
interface BranchSummaryEntry<T = unknown> {
|
||||
|
|
@ -210,7 +210,7 @@ interface BranchSummaryDetails {
|
|||
|
||||
Same as compaction, extensions can store custom data in `details`.
|
||||
|
||||
See [`collectEntriesForBranchSummary()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), [`prepareBranchEntries()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), and [`generateBranchSummary()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) for the implementation.
|
||||
See [`collectEntriesForBranchSummary()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), [`prepareBranchEntries()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), and [`generateBranchSummary()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) for the implementation.
|
||||
|
||||
## Summary Format
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ path/to/changed.ts
|
|||
|
||||
### Message Serialization
|
||||
|
||||
Before summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
|
||||
Before summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
|
||||
|
||||
```
|
||||
[User]: What they said
|
||||
|
|
@ -277,14 +277,14 @@ This prevents the model from treating it as a conversation to continue.
|
|||
|
||||
## Custom Summarization via Extensions
|
||||
|
||||
Extensions can intercept and customize both compaction and branch summarization. See [`extensions/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) for event type definitions.
|
||||
Extensions can intercept and customize both compaction and branch summarization. See [`extensions/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/extensions/types.ts) for event type definitions.
|
||||
|
||||
### session_before_compact
|
||||
|
||||
Fired before auto-compaction or `/compact`. Can cancel or provide custom summary. See `SessionBeforeCompactEvent` and `CompactionPreparation` in the types file.
|
||||
|
||||
```typescript
|
||||
companion.on("session_before_compact", async (event, ctx) => {
|
||||
clanker.on("session_before_compact", async (event, ctx) => {
|
||||
const { preparation, branchEntries, customInstructions, signal } = event;
|
||||
|
||||
// preparation.messagesToSummarize - messages to summarize
|
||||
|
|
@ -323,9 +323,9 @@ To generate a summary with your own model, convert messages to text using `seria
|
|||
import {
|
||||
convertToLlm,
|
||||
serializeConversation,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
companion.on("session_before_compact", async (event, ctx) => {
|
||||
clanker.on("session_before_compact", async (event, ctx) => {
|
||||
const { preparation } = event;
|
||||
|
||||
// Convert AgentMessage[] to Message[], then serialize to text
|
||||
|
|
@ -359,7 +359,7 @@ See [custom-compaction.ts](../examples/extensions/custom-compaction.ts) for a co
|
|||
Fired before `/tree` navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
|
||||
|
||||
```typescript
|
||||
companion.on("session_before_tree", async (event, ctx) => {
|
||||
clanker.on("session_before_tree", async (event, ctx) => {
|
||||
const { preparation, signal } = event;
|
||||
|
||||
// preparation.targetId - where we're navigating to
|
||||
|
|
@ -389,7 +389,7 @@ See `SessionBeforeTreeEvent` and `TreePreparation` in the types file.
|
|||
|
||||
## Settings
|
||||
|
||||
Configure compaction in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`:
|
||||
Configure compaction in `~/.clanker/agent/settings.json` or `<project-dir>/.clanker/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Custom Providers
|
||||
|
||||
Extensions can register custom model providers via `companion.registerProvider()`. This enables:
|
||||
Extensions can register custom model providers via `clanker.registerProvider()`. This enables:
|
||||
|
||||
- **Proxies** - Route requests through corporate proxies or API gateways
|
||||
- **Custom endpoints** - Use self-hosted or private model deployments
|
||||
|
|
@ -22,16 +22,16 @@ Extensions can register custom model providers via `companion.registerProvider()
|
|||
## Quick Reference
|
||||
|
||||
```typescript
|
||||
import type { ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||
import type { ExtensionAPI } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
export default function (companion: ExtensionAPI) {
|
||||
export default function (clanker: ExtensionAPI) {
|
||||
// Override baseUrl for existing provider
|
||||
companion.registerProvider("anthropic", {
|
||||
clanker.registerProvider("anthropic", {
|
||||
baseUrl: "https://proxy.example.com",
|
||||
});
|
||||
|
||||
// Register new provider with models
|
||||
companion.registerProvider("my-provider", {
|
||||
clanker.registerProvider("my-provider", {
|
||||
baseUrl: "https://api.example.com",
|
||||
apiKey: "MY_API_KEY",
|
||||
api: "openai-completions",
|
||||
|
|
@ -56,19 +56,19 @@ The simplest use case: redirect an existing provider through a proxy.
|
|||
|
||||
```typescript
|
||||
// All Anthropic requests now go through your proxy
|
||||
companion.registerProvider("anthropic", {
|
||||
clanker.registerProvider("anthropic", {
|
||||
baseUrl: "https://proxy.example.com",
|
||||
});
|
||||
|
||||
// Add custom headers to OpenAI requests
|
||||
companion.registerProvider("openai", {
|
||||
clanker.registerProvider("openai", {
|
||||
headers: {
|
||||
"X-Custom-Header": "value",
|
||||
},
|
||||
});
|
||||
|
||||
// Both baseUrl and headers
|
||||
companion.registerProvider("google", {
|
||||
clanker.registerProvider("google", {
|
||||
baseUrl: "https://ai-gateway.corp.com/google",
|
||||
headers: {
|
||||
"X-Corp-Auth": "CORP_AUTH_TOKEN", // env var or literal
|
||||
|
|
@ -83,7 +83,7 @@ When only `baseUrl` and/or `headers` are provided (no `models`), all existing mo
|
|||
To add a completely new provider, specify `models` along with the required configuration.
|
||||
|
||||
```typescript
|
||||
companion.registerProvider("my-llm", {
|
||||
clanker.registerProvider("my-llm", {
|
||||
baseUrl: "https://api.my-llm.com/v1",
|
||||
apiKey: "MY_LLM_API_KEY", // env var name or literal value
|
||||
api: "openai-completions", // which streaming API to use
|
||||
|
|
@ -110,11 +110,11 @@ When `models` is provided, it **replaces** all existing models for that provider
|
|||
|
||||
## Unregister Provider
|
||||
|
||||
Use `companion.unregisterProvider(name)` to remove a provider that was previously registered via `companion.registerProvider(name, ...)`:
|
||||
Use `clanker.unregisterProvider(name)` to remove a provider that was previously registered via `clanker.registerProvider(name, ...)`:
|
||||
|
||||
```typescript
|
||||
// Register
|
||||
companion.registerProvider("my-llm", {
|
||||
clanker.registerProvider("my-llm", {
|
||||
baseUrl: "https://api.my-llm.com/v1",
|
||||
apiKey: "MY_LLM_API_KEY",
|
||||
api: "openai-completions",
|
||||
|
|
@ -132,7 +132,7 @@ companion.registerProvider("my-llm", {
|
|||
});
|
||||
|
||||
// Later, remove it
|
||||
companion.unregisterProvider("my-llm");
|
||||
clanker.unregisterProvider("my-llm");
|
||||
```
|
||||
|
||||
Unregistering removes that provider's dynamic models, API key fallback, OAuth provider registration, and custom stream handler registrations. Any built-in models or provider behavior that were overridden are restored.
|
||||
|
|
@ -167,7 +167,7 @@ models: [
|
|||
supportsDeveloperRole: false, // use "system" instead of "developer"
|
||||
supportsReasoningEffort: true,
|
||||
reasoningEffortMap: {
|
||||
// map companion-ai levels to provider values
|
||||
// map clanker-ai levels to provider values
|
||||
minimal: "default",
|
||||
low: "default",
|
||||
medium: "default",
|
||||
|
|
@ -191,7 +191,7 @@ models: [
|
|||
If your provider expects `Authorization: Bearer <key>` but doesn't use a standard API, set `authHeader: true`:
|
||||
|
||||
```typescript
|
||||
companion.registerProvider("custom-api", {
|
||||
clanker.registerProvider("custom-api", {
|
||||
baseUrl: "https://api.example.com",
|
||||
apiKey: "MY_API_KEY",
|
||||
authHeader: true, // adds Authorization: Bearer header
|
||||
|
|
@ -205,9 +205,9 @@ companion.registerProvider("custom-api", {
|
|||
Add OAuth/SSO authentication that integrates with `/login`:
|
||||
|
||||
```typescript
|
||||
import type { OAuthCredentials, OAuthLoginCallbacks } from "@mariozechner/companion-ai";
|
||||
import type { OAuthCredentials, OAuthLoginCallbacks } from "@mariozechner/clanker-ai";
|
||||
|
||||
companion.registerProvider("corporate-ai", {
|
||||
clanker.registerProvider("corporate-ai", {
|
||||
baseUrl: "https://ai.corp.com/v1",
|
||||
api: "openai-responses",
|
||||
models: [...],
|
||||
|
|
@ -283,7 +283,7 @@ interface OAuthLoginCallbacks {
|
|||
|
||||
### OAuthCredentials
|
||||
|
||||
Credentials are persisted in `~/.companion/agent/auth.json`:
|
||||
Credentials are persisted in `~/.clanker/agent/auth.json`:
|
||||
|
||||
```typescript
|
||||
interface OAuthCredentials {
|
||||
|
|
@ -299,12 +299,12 @@ For providers with non-standard APIs, implement `streamSimple`. Study the existi
|
|||
|
||||
**Reference implementations:**
|
||||
|
||||
- [anthropic.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/anthropic.ts) - Anthropic Messages API
|
||||
- [mistral.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/mistral.ts) - Mistral Conversations API
|
||||
- [openai-completions.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/openai-completions.ts) - OpenAI Chat Completions
|
||||
- [openai-responses.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/openai-responses.ts) - OpenAI Responses API
|
||||
- [google.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/google.ts) - Google Generative AI
|
||||
- [amazon-bedrock.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/amazon-bedrock.ts) - AWS Bedrock
|
||||
- [anthropic.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/anthropic.ts) - Anthropic Messages API
|
||||
- [mistral.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/mistral.ts) - Mistral Conversations API
|
||||
- [openai-completions.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/openai-completions.ts) - OpenAI Chat Completions
|
||||
- [openai-responses.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/openai-responses.ts) - OpenAI Responses API
|
||||
- [google.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/google.ts) - Google Generative AI
|
||||
- [amazon-bedrock.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/amazon-bedrock.ts) - AWS Bedrock
|
||||
|
||||
### Stream Pattern
|
||||
|
||||
|
|
@ -319,7 +319,7 @@ import {
|
|||
type SimpleStreamOptions,
|
||||
calculateCost,
|
||||
createAssistantMessageEventStream,
|
||||
} from "@mariozechner/companion-ai";
|
||||
} from "@mariozechner/clanker-ai";
|
||||
|
||||
function streamMyProvider(
|
||||
model: Model<any>,
|
||||
|
|
@ -487,7 +487,7 @@ calculateCost(model, output.usage);
|
|||
Register your stream function:
|
||||
|
||||
```typescript
|
||||
companion.registerProvider("my-provider", {
|
||||
clanker.registerProvider("my-provider", {
|
||||
baseUrl: "https://api.example.com",
|
||||
apiKey: "MY_API_KEY",
|
||||
api: "my-custom-api",
|
||||
|
|
@ -498,7 +498,7 @@ companion.registerProvider("my-provider", {
|
|||
|
||||
## Testing Your Implementation
|
||||
|
||||
Test your provider against the same test suites used by built-in providers. Copy and adapt these test files from [packages/ai/test/](https://github.com/badlogic/companion-mono/tree/main/packages/ai/test):
|
||||
Test your provider against the same test suites used by built-in providers. Copy and adapt these test files from [packages/ai/test/](https://github.com/badlogic/clanker-agent/tree/main/packages/ai/test):
|
||||
|
||||
| Test | Purpose |
|
||||
| ---------------------------------- | --------------------------------- |
|
||||
|
|
@ -5,8 +5,8 @@ See [AGENTS.md](../../../AGENTS.md) for additional guidelines.
|
|||
## Setup
|
||||
|
||||
```bash
|
||||
git clone https://github.com/badlogic/companion-mono
|
||||
cd companion-mono
|
||||
git clone https://github.com/badlogic/clanker-agent
|
||||
cd clanker-agent
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
|
@ -14,7 +14,7 @@ npm run build
|
|||
Run from source:
|
||||
|
||||
```bash
|
||||
./companion-test.sh
|
||||
./clanker-test.sh
|
||||
```
|
||||
|
||||
## Forking / Rebranding
|
||||
|
|
@ -23,9 +23,9 @@ Configure via `package.json`:
|
|||
|
||||
```json
|
||||
{
|
||||
"companionConfig": {
|
||||
"name": "companion",
|
||||
"configDir": ".companion"
|
||||
"clankerConfig": {
|
||||
"name": "clanker",
|
||||
"configDir": ".clanker"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -46,7 +46,7 @@ Never use `__dirname` directly for package assets.
|
|||
|
||||
## Debug Command
|
||||
|
||||
`/debug` (hidden) writes to `~/.companion/agent/companion-debug.log`:
|
||||
`/debug` (hidden) writes to `~/.clanker/agent/clanker-debug.log`:
|
||||
|
||||
- Rendered TUI lines with ANSI codes
|
||||
- Last messages sent to the LLM
|
||||
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 321 KiB After Width: | Height: | Size: 321 KiB |
|
Before Width: | Height: | Size: 275 KiB After Width: | Height: | Size: 275 KiB |
|
|
@ -1,14 +1,14 @@
|
|||
# JSON Event Stream Mode
|
||||
|
||||
```bash
|
||||
companion --mode json "Your prompt"
|
||||
clanker --mode json "Your prompt"
|
||||
```
|
||||
|
||||
Outputs all session events as JSON lines to stdout. Useful for integrating companion into other tools or custom UIs.
|
||||
Outputs all session events as JSON lines to stdout. Useful for integrating clanker into other tools or custom UIs.
|
||||
|
||||
## Event Types
|
||||
|
||||
Events are defined in [`AgentSessionEvent`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/agent-session.ts#L102):
|
||||
Events are defined in [`AgentSessionEvent`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/agent-session.ts#L102):
|
||||
|
||||
```typescript
|
||||
type AgentSessionEvent =
|
||||
|
|
@ -36,7 +36,7 @@ type AgentSessionEvent =
|
|||
};
|
||||
```
|
||||
|
||||
Base events from [`AgentEvent`](https://github.com/badlogic/companion-mono/blob/main/packages/agent/src/types.ts#L179):
|
||||
Base events from [`AgentEvent`](https://github.com/badlogic/clanker-agent/blob/main/packages/agent/src/types.ts#L179):
|
||||
|
||||
```typescript
|
||||
type AgentEvent =
|
||||
|
|
@ -83,13 +83,13 @@ type AgentEvent =
|
|||
|
||||
## Message Types
|
||||
|
||||
Base messages from [`packages/ai/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/types.ts#L134):
|
||||
Base messages from [`packages/ai/src/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/types.ts#L134):
|
||||
|
||||
- `UserMessage` (line 134)
|
||||
- `AssistantMessage` (line 140)
|
||||
- `ToolResultMessage` (line 152)
|
||||
|
||||
Extended messages from [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/messages.ts#L29):
|
||||
Extended messages from [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/messages.ts#L29):
|
||||
|
||||
- `BashExecutionMessage` (line 29)
|
||||
- `CustomMessage` (line 46)
|
||||
|
|
@ -125,5 +125,5 @@ Followed by events as they occur:
|
|||
## Example
|
||||
|
||||
```bash
|
||||
companion --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'
|
||||
clanker --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'
|
||||
```
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Keybindings
|
||||
|
||||
All keyboard shortcuts can be customized via `~/.companion/agent/keybindings.json`. Each action can be bound to one or more keys.
|
||||
All keyboard shortcuts can be customized via `~/.clanker/agent/keybindings.json`. Each action can be bound to one or more keys.
|
||||
|
||||
## Key Format
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, etc.
|
|||
|
||||
## Custom Configuration
|
||||
|
||||
Create `~/.companion/agent/keybindings.json`:
|
||||
Create `~/.clanker/agent/keybindings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Custom Models
|
||||
|
||||
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.companion/agent/models.json`.
|
||||
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.clanker/agent/models.json`.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
> companion can help you create companion packages. Ask it to bundle your extensions, skills, prompt templates, or themes.
|
||||
> clanker can help you create clanker packages. Ask it to bundle your extensions, skills, prompt templates, or themes.
|
||||
|
||||
# Companion Packages
|
||||
# Clanker Packages
|
||||
|
||||
Companion packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under the `companion` key, or use conventional directories.
|
||||
Clanker packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under the `clanker` key, or use conventional directories.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install and Manage](#install-and-manage)
|
||||
- [Package Sources](#package-sources)
|
||||
- [Creating a Companion Package](#creating-a-companion-package)
|
||||
- [Creating a Clanker Package](#creating-a-clanker-package)
|
||||
- [Package Structure](#package-structure)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Package Filtering](#package-filtering)
|
||||
|
|
@ -17,32 +17,32 @@ Companion packages bundle extensions, skills, prompt templates, and themes so yo
|
|||
|
||||
## Install and Manage
|
||||
|
||||
> **Security:** Companion packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||
> **Security:** Clanker packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||
|
||||
```bash
|
||||
companion install npm:@foo/bar@1.0.0
|
||||
companion install git:github.com/user/repo@v1
|
||||
companion install https://github.com/user/repo # raw URLs work too
|
||||
companion install /absolute/path/to/package
|
||||
companion install ./relative/path/to/package
|
||||
clanker install npm:@foo/bar@1.0.0
|
||||
clanker install git:github.com/user/repo@v1
|
||||
clanker install https://github.com/user/repo # raw URLs work too
|
||||
clanker install /absolute/path/to/package
|
||||
clanker install ./relative/path/to/package
|
||||
|
||||
companion remove npm:@foo/bar
|
||||
companion list # show installed packages from settings
|
||||
companion update # update all non-pinned packages
|
||||
clanker remove npm:@foo/bar
|
||||
clanker list # show installed packages from settings
|
||||
clanker update # update all non-pinned packages
|
||||
```
|
||||
|
||||
By default, `install` and `remove` write to global settings (`~/.companion/agent/settings.json`). Use `-l` to write to project settings (`.companion/settings.json`) instead. Project settings can be shared with your team, and companion installs any missing packages automatically on startup.
|
||||
By default, `install` and `remove` write to global settings (`~/.clanker/agent/settings.json`). Use `-l` to write to project settings (`.clanker/settings.json`) instead. Project settings can be shared with your team, and clanker installs any missing packages automatically on startup.
|
||||
|
||||
To try a package without installing it, use `--extension` or `-e`. This installs to a temporary directory for the current run only:
|
||||
|
||||
```bash
|
||||
companion -e npm:@foo/bar
|
||||
companion -e git:github.com/user/repo
|
||||
clanker -e npm:@foo/bar
|
||||
clanker -e git:github.com/user/repo
|
||||
```
|
||||
|
||||
## Package Sources
|
||||
|
||||
Companion accepts three source types in settings and `companion install`.
|
||||
Clanker accepts three source types in settings and `clanker install`.
|
||||
|
||||
### npm
|
||||
|
||||
|
|
@ -51,9 +51,9 @@ npm:@scope/pkg@1.2.3
|
|||
npm:pkg
|
||||
```
|
||||
|
||||
- Versioned specs are pinned and skipped by `companion update`.
|
||||
- Versioned specs are pinned and skipped by `clanker update`.
|
||||
- Global installs use `npm install -g`.
|
||||
- Project installs go under `.companion/npm/`.
|
||||
- Project installs go under `.clanker/npm/`.
|
||||
|
||||
### git
|
||||
|
||||
|
|
@ -69,21 +69,21 @@ ssh://git@github.com/user/repo@v1
|
|||
- HTTPS and SSH URLs are both supported.
|
||||
- SSH URLs use your configured SSH keys automatically (respects `~/.ssh/config`).
|
||||
- For non-interactive runs (for example CI), you can set `GIT_TERMINAL_PROMPT=0` to disable credential prompts and set `GIT_SSH_COMMAND` (for example `ssh -o BatchMode=yes -o ConnectTimeout=5`) to fail fast.
|
||||
- Refs pin the package and skip `companion update`.
|
||||
- Cloned to `~/.companion/agent/git/<host>/<path>` (global) or `.companion/git/<host>/<path>` (project).
|
||||
- Refs pin the package and skip `clanker update`.
|
||||
- Cloned to `~/.clanker/agent/git/<host>/<path>` (global) or `.clanker/git/<host>/<path>` (project).
|
||||
- Runs `npm install` after clone or pull if `package.json` exists.
|
||||
|
||||
**SSH examples:**
|
||||
|
||||
```bash
|
||||
# git@host:path shorthand (requires git: prefix)
|
||||
companion install git:git@github.com:user/repo
|
||||
clanker install git:git@github.com:user/repo
|
||||
|
||||
# ssh:// protocol format
|
||||
companion install ssh://git@github.com/user/repo
|
||||
clanker install ssh://git@github.com/user/repo
|
||||
|
||||
# With version ref
|
||||
companion install git:git@github.com:user/repo@v1.0.0
|
||||
clanker install git:git@github.com:user/repo@v1.0.0
|
||||
```
|
||||
|
||||
### Local Paths
|
||||
|
|
@ -93,17 +93,17 @@ companion install git:git@github.com:user/repo@v1.0.0
|
|||
./relative/path/to/package
|
||||
```
|
||||
|
||||
Local paths point to files or directories on disk and are added to settings without copying. Relative paths are resolved against the settings file they appear in. If the path is a file, it loads as a single extension. If it is a directory, companion loads resources using package rules.
|
||||
Local paths point to files or directories on disk and are added to settings without copying. Relative paths are resolved against the settings file they appear in. If the path is a file, it loads as a single extension. If it is a directory, clanker loads resources using package rules.
|
||||
|
||||
## Creating a Companion Package
|
||||
## Creating a Clanker Package
|
||||
|
||||
Add a `companion` manifest to `package.json` or use conventional directories. Include the `companion-package` keyword for discoverability.
|
||||
Add a `clanker` manifest to `package.json` or use conventional directories. Include the `clanker-package` keyword for discoverability.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-package",
|
||||
"keywords": ["companion-package"],
|
||||
"companion": {
|
||||
"keywords": ["clanker-package"],
|
||||
"clanker": {
|
||||
"extensions": ["./extensions"],
|
||||
"skills": ["./skills"],
|
||||
"prompts": ["./prompts"],
|
||||
|
|
@ -116,13 +116,13 @@ Paths are relative to the package root. Arrays support glob patterns and `!exclu
|
|||
|
||||
### Gallery Metadata
|
||||
|
||||
The [package gallery](https://shittycodingagent.ai/packages) displays packages tagged with `companion-package`. Add `video` or `image` fields to show a preview:
|
||||
The [package gallery](https://clanker.dev/packages) displays packages tagged with `clanker-package`. Add `video` or `image` fields to show a preview:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-package",
|
||||
"keywords": ["companion-package"],
|
||||
"companion": {
|
||||
"keywords": ["clanker-package"],
|
||||
"clanker": {
|
||||
"extensions": ["./extensions"],
|
||||
"video": "https://example.com/demo.mp4",
|
||||
"image": "https://example.com/screenshot.png"
|
||||
|
|
@ -139,7 +139,7 @@ If both are set, video takes precedence.
|
|||
|
||||
### Convention Directories
|
||||
|
||||
If no `companion` manifest is present, companion auto-discovers resources from these directories:
|
||||
If no `clanker` manifest is present, clanker auto-discovers resources from these directories:
|
||||
|
||||
- `extensions/` loads `.ts` and `.js` files
|
||||
- `skills/` recursively finds `SKILL.md` folders and loads top-level `.md` files as skills
|
||||
|
|
@ -148,11 +148,11 @@ If no `companion` manifest is present, companion auto-discovers resources from t
|
|||
|
||||
## Dependencies
|
||||
|
||||
Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When companion installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically.
|
||||
Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When clanker installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically.
|
||||
|
||||
Companion bundles core packages for extensions and skills. If you import any of these, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@mariozechner/companion-ai`, `@mariozechner/companion-agent-core`, `@mariozechner/companion-coding-agent`, `@mariozechner/companion-tui`, `@sinclair/typebox`.
|
||||
Clanker bundles core packages for extensions and skills. If you import any of these, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@mariozechner/clanker-ai`, `@mariozechner/clanker-agent-core`, `@mariozechner/clanker-coding-agent`, `@mariozechner/clanker-tui`, `@sinclair/typebox`.
|
||||
|
||||
Other companion packages must be bundled in your tarball. Add them to `dependencies` and `bundledDependencies`, then reference their resources through `node_modules/` paths. Companion loads packages with separate module roots, so separate installs do not collide or share modules.
|
||||
Other clanker packages must be bundled in your tarball. Add them to `dependencies` and `bundledDependencies`, then reference their resources through `node_modules/` paths. Clanker loads packages with separate module roots, so separate installs do not collide or share modules.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ Example:
|
|||
"shitty-extensions": "^1.0.1"
|
||||
},
|
||||
"bundledDependencies": ["shitty-extensions"],
|
||||
"companion": {
|
||||
"clanker": {
|
||||
"extensions": ["extensions", "node_modules/shitty-extensions/extensions"],
|
||||
"skills": ["skills", "node_modules/shitty-extensions/skills"]
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ Filter what a package loads using the object form in settings:
|
|||
|
||||
## Enable and Disable Resources
|
||||
|
||||
Use `companion config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. Works for both global (`~/.companion/agent`) and project (`.companion/`) scopes.
|
||||
Use `clanker config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. Works for both global (`~/.clanker/agent`) and project (`.clanker/`) scopes.
|
||||
|
||||
## Scope and Deduplication
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
> companion can create prompt templates. Ask it to build one for your workflow.
|
||||
> clanker can create prompt templates. Ask it to build one for your workflow.
|
||||
|
||||
# Prompt Templates
|
||||
|
||||
|
|
@ -6,11 +6,11 @@ Prompt templates are Markdown snippets that expand into full prompts. Type `/nam
|
|||
|
||||
## Locations
|
||||
|
||||
Companion loads prompt templates from:
|
||||
Clanker loads prompt templates from:
|
||||
|
||||
- Global: `~/.companion/agent/prompts/*.md`
|
||||
- Project: `.companion/prompts/*.md`
|
||||
- Packages: `prompts/` directories or `companion.prompts` entries in `package.json`
|
||||
- Global: `~/.clanker/agent/prompts/*.md`
|
||||
- Project: `.clanker/prompts/*.md`
|
||||
- Packages: `prompts/` directories or `clanker.prompts` entries in `package.json`
|
||||
- Settings: `prompts` array with files or directories
|
||||
- CLI: `--prompt-template <path>` (repeatable)
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Providers
|
||||
|
||||
Companion supports subscription-based providers via OAuth and API key providers via environment variables or auth file. For each provider, companion knows all available models. The list is updated with every companion release.
|
||||
Clanker supports subscription-based providers via OAuth and API key providers via environment variables or auth file. For each provider, clanker knows all available models. The list is updated with every clanker release.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ Use `/login` in interactive mode, then select a provider:
|
|||
- Google Gemini CLI
|
||||
- Google Antigravity
|
||||
|
||||
Use `/logout` to clear credentials. Tokens are stored in `~/.companion/agent/auth.json` and auto-refresh when expired.
|
||||
Use `/logout` to clear credentials. Tokens are stored in `~/.clanker/agent/auth.json` and auto-refresh when expired.
|
||||
|
||||
### GitHub Copilot
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ Set via environment variable:
|
|||
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY=sk-ant-...
|
||||
companion
|
||||
clanker
|
||||
```
|
||||
|
||||
| Provider | Environment Variable | `auth.json` key |
|
||||
|
|
@ -71,11 +71,11 @@ companion
|
|||
| MiniMax | `MINIMAX_API_KEY` | `minimax` |
|
||||
| MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
|
||||
|
||||
Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/env-api-keys.ts).
|
||||
Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/env-api-keys.ts).
|
||||
|
||||
#### Auth File
|
||||
|
||||
Store credentials in `~/.companion/agent/auth.json`:
|
||||
Store credentials in `~/.clanker/agent/auth.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -144,7 +144,7 @@ export AWS_REGION=us-west-2
|
|||
Also supports ECS task roles (`AWS_CONTAINER_CREDENTIALS_*`) and IRSA (`AWS_WEB_IDENTITY_TOKEN_FILE`).
|
||||
|
||||
```bash
|
||||
companion --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
clanker --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
```
|
||||
|
||||
If you are connecting to a Bedrock API proxy, the following environment variables can be used:
|
||||
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
RPC mode enables headless operation of the coding agent via a JSON protocol over stdin/stdout. This is useful for embedding the agent in other applications, IDEs, or custom UIs.
|
||||
|
||||
**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@mariozechner/companion-coding-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts).
|
||||
**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@mariozechner/clanker-coding-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts).
|
||||
|
||||
## Starting RPC Mode
|
||||
|
||||
```bash
|
||||
companion --mode rpc [options]
|
||||
clanker --mode rpc [options]
|
||||
```
|
||||
|
||||
Common options:
|
||||
|
|
@ -60,7 +60,7 @@ With images:
|
|||
|
||||
If the agent is streaming and no `streamingBehavior` is specified, the command returns an error.
|
||||
|
||||
**Extension commands**: If the message is an extension command (e.g., `/mycommand`), it executes immediately even during streaming. Extension commands manage their own LLM interaction via `companion.sendMessage()`.
|
||||
**Extension commands**: If the message is an extension command (e.g., `/mycommand`), it executes immediately even during streaming. Extension commands manage their own LLM interaction via `clanker.sendMessage()`.
|
||||
|
||||
**Input expansion**: Skill commands (`/skill:name`) and prompt templates (`/template`) are expanded before sending/queueing.
|
||||
|
||||
|
|
@ -503,7 +503,7 @@ If output was truncated, includes `fullOutputPath`:
|
|||
"exitCode": 0,
|
||||
"cancelled": false,
|
||||
"truncated": true,
|
||||
"fullOutputPath": "/tmp/companion-bash-abc123.log"
|
||||
"fullOutputPath": "/tmp/clanker-bash-abc123.log"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -752,21 +752,21 @@ Response:
|
|||
"name": "session-name",
|
||||
"description": "Set or clear session name",
|
||||
"source": "extension",
|
||||
"path": "/home/user/.companion/agent/extensions/session.ts"
|
||||
"path": "/home/user/.clanker/agent/extensions/session.ts"
|
||||
},
|
||||
{
|
||||
"name": "fix-tests",
|
||||
"description": "Fix failing tests",
|
||||
"source": "prompt",
|
||||
"location": "project",
|
||||
"path": "/home/user/myproject/.companion/agent/prompts/fix-tests.md"
|
||||
"path": "/home/user/myproject/.clanker/agent/prompts/fix-tests.md"
|
||||
},
|
||||
{
|
||||
"name": "skill:brave-search",
|
||||
"description": "Web search via Brave API",
|
||||
"source": "skill",
|
||||
"location": "user",
|
||||
"path": "/home/user/.companion/agent/skills/brave-search/SKILL.md"
|
||||
"path": "/home/user/.clanker/agent/skills/brave-search/SKILL.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -778,12 +778,12 @@ Each command has:
|
|||
- `name`: Command name (invoke with `/name`)
|
||||
- `description`: Human-readable description (optional for extension commands)
|
||||
- `source`: What kind of command:
|
||||
- `"extension"`: Registered via `companion.registerCommand()` in an extension
|
||||
- `"extension"`: Registered via `clanker.registerCommand()` in an extension
|
||||
- `"prompt"`: Loaded from a prompt template `.md` file
|
||||
- `"skill"`: Loaded from a skill directory (name is prefixed with `skill:`)
|
||||
- `location`: Where it was loaded from (optional, not present for extensions):
|
||||
- `"user"`: User-level (`~/.companion/agent/`)
|
||||
- `"project"`: Project-level (`./.companion/agent/`)
|
||||
- `"user"`: User-level (`~/.clanker/agent/`)
|
||||
- `"project"`: Project-level (`./.clanker/agent/`)
|
||||
- `"path"`: Explicit path via CLI or settings
|
||||
- `path`: Absolute file path to the command source (optional)
|
||||
|
||||
|
|
@ -1173,7 +1173,7 @@ Set the terminal window/tab title. Fire-and-forget.
|
|||
"type": "extension_ui_request",
|
||||
"id": "uuid-8",
|
||||
"method": "setTitle",
|
||||
"title": "companion - my project"
|
||||
"title": "clanker - my project"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -1372,7 +1372,7 @@ import subprocess
|
|||
import json
|
||||
|
||||
proc = subprocess.Popen(
|
||||
["companion", "--mode", "rpc", "--no-session"],
|
||||
["clanker", "--mode", "rpc", "--no-session"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True
|
||||
|
|
@ -1411,7 +1411,7 @@ For a complete example of handling the extension UI protocol, see [`examples/rpc
|
|||
const { spawn } = require("child_process");
|
||||
const readline = require("readline");
|
||||
|
||||
const agent = spawn("companion", ["--mode", "rpc", "--no-session"]);
|
||||
const agent = spawn("clanker", ["--mode", "rpc", "--no-session"]);
|
||||
|
||||
readline.createInterface({ input: agent.stdout }).on("line", (line) => {
|
||||
const event = JSON.parse(line);
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
> companion can help you use the SDK. Ask it to build an integration for your use case.
|
||||
> clanker can help you use the SDK. Ask it to build an integration for your use case.
|
||||
|
||||
# SDK
|
||||
|
||||
The SDK provides programmatic access to companion's agent capabilities. Use it to embed companion in other applications, build custom interfaces, or integrate with automated workflows.
|
||||
The SDK provides programmatic access to clanker's agent capabilities. Use it to embed clanker in other applications, build custom interfaces, or integrate with automated workflows.
|
||||
|
||||
**Example use cases:**
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ import {
|
|||
createAgentSession,
|
||||
ModelRegistry,
|
||||
SessionManager,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Set up credential storage and model registry
|
||||
const authStorage = AuthStorage.create();
|
||||
|
|
@ -49,7 +49,7 @@ await session.prompt("What files are in the current directory?");
|
|||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @mariozechner/companion-coding-agent
|
||||
npm install @mariozechner/clanker-coding-agent
|
||||
```
|
||||
|
||||
The SDK is included in the main package. No separate installation needed.
|
||||
|
|
@ -63,7 +63,7 @@ The main factory function. Creates an `AgentSession` with configurable options.
|
|||
`createAgentSession()` uses a `ResourceLoader` to supply extensions, skills, prompt templates, themes, and context files. If you do not provide one, it uses `DefaultResourceLoader` with standard discovery.
|
||||
|
||||
```typescript
|
||||
import { createAgentSession } from "@mariozechner/companion-coding-agent";
|
||||
import { createAgentSession } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Minimal: defaults with DefaultResourceLoader
|
||||
const { session } = await createAgentSession();
|
||||
|
|
@ -170,7 +170,7 @@ await session.prompt("After you're done, also check X", {
|
|||
|
||||
**Behavior:**
|
||||
|
||||
- **Extension commands** (e.g., `/mycommand`): Execute immediately, even during streaming. They manage their own LLM interaction via `companion.sendMessage()`.
|
||||
- **Extension commands** (e.g., `/mycommand`): Execute immediately, even during streaming. They manage their own LLM interaction via `clanker.sendMessage()`.
|
||||
- **File-based prompt templates** (from `.md` files): Expanded to their content before sending/queueing.
|
||||
- **During streaming without `streamingBehavior`**: Throws an error. Use `steer()` or `followUp()` directly, or specify the option.
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ Both `steer()` and `followUp()` expand file-based prompt templates but error on
|
|||
|
||||
### Agent and AgentState
|
||||
|
||||
The `Agent` class (from `@mariozechner/companion-agent-core`) handles the core LLM interaction. Access it via `session.agent`.
|
||||
The `Agent` class (from `@mariozechner/clanker-agent-core`) handles the core LLM interaction. Access it via `session.agent`.
|
||||
|
||||
```typescript
|
||||
// Access current state
|
||||
|
|
@ -279,17 +279,17 @@ const { session } = await createAgentSession({
|
|||
cwd: process.cwd(), // default
|
||||
|
||||
// Global config directory
|
||||
agentDir: "~/.companion/agent", // default (expands ~)
|
||||
agentDir: "~/.clanker/agent", // default (expands ~)
|
||||
});
|
||||
```
|
||||
|
||||
`cwd` is used by `DefaultResourceLoader` for:
|
||||
|
||||
- Project extensions (`.companion/extensions/`)
|
||||
- Project extensions (`.clanker/extensions/`)
|
||||
- Project skills:
|
||||
- `.companion/skills/`
|
||||
- `.clanker/skills/`
|
||||
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
||||
- Project prompts (`.companion/prompts/`)
|
||||
- Project prompts (`.clanker/prompts/`)
|
||||
- Context files (`AGENTS.md` walking up from cwd)
|
||||
- Session directory naming
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ const { session } = await createAgentSession({
|
|||
|
||||
- Global extensions (`extensions/`)
|
||||
- Global skills:
|
||||
- `skills/` under `agentDir` (for example `~/.companion/agent/skills/`)
|
||||
- `skills/` under `agentDir` (for example `~/.clanker/agent/skills/`)
|
||||
- `~/.agents/skills/`
|
||||
- Global prompts (`prompts/`)
|
||||
- Global context file (`AGENTS.md`)
|
||||
|
|
@ -311,11 +311,11 @@ When you pass a custom `ResourceLoader`, `cwd` and `agentDir` no longer control
|
|||
### Model
|
||||
|
||||
```typescript
|
||||
import { getModel } from "@mariozechner/companion-ai";
|
||||
import { getModel } from "@mariozechner/clanker-ai";
|
||||
import {
|
||||
AuthStorage,
|
||||
ModelRegistry,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const authStorage = AuthStorage.create();
|
||||
const modelRegistry = new ModelRegistry(authStorage);
|
||||
|
|
@ -365,9 +365,9 @@ API key resolution priority (handled by AuthStorage):
|
|||
import {
|
||||
AuthStorage,
|
||||
ModelRegistry,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Default: uses ~/.companion/agent/auth.json and ~/.companion/agent/models.json
|
||||
// Default: uses ~/.clanker/agent/auth.json and ~/.clanker/agent/models.json
|
||||
const authStorage = AuthStorage.create();
|
||||
const modelRegistry = new ModelRegistry(authStorage);
|
||||
|
||||
|
|
@ -402,7 +402,7 @@ Use a `ResourceLoader` to override the system prompt:
|
|||
import {
|
||||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
systemPromptOverride: () => "You are a helpful assistant.",
|
||||
|
|
@ -425,7 +425,7 @@ import {
|
|||
grepTool,
|
||||
findTool,
|
||||
lsTool,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Use built-in tool set
|
||||
const { session } = await createAgentSession({
|
||||
|
|
@ -453,7 +453,7 @@ import {
|
|||
createGrepTool,
|
||||
createFindTool,
|
||||
createLsTool,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const cwd = "/path/to/project";
|
||||
|
||||
|
|
@ -472,7 +472,7 @@ const { session } = await createAgentSession({
|
|||
|
||||
**When you don't need factories:**
|
||||
|
||||
- If you omit `tools`, companion automatically creates them with the correct `cwd`
|
||||
- If you omit `tools`, clanker automatically creates them with the correct `cwd`
|
||||
- If you use `process.cwd()` as your `cwd`, the pre-built instances work fine
|
||||
|
||||
**When you must use factories:**
|
||||
|
|
@ -486,7 +486,7 @@ import { Type } from "@sinclair/typebox";
|
|||
import {
|
||||
createAgentSession,
|
||||
type ToolDefinition,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Inline custom tool
|
||||
const myTool: ToolDefinition = {
|
||||
|
|
@ -508,23 +508,23 @@ const { session } = await createAgentSession({
|
|||
});
|
||||
```
|
||||
|
||||
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `companion.registerTool()`.
|
||||
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `clanker.registerTool()`.
|
||||
|
||||
### Extensions
|
||||
|
||||
Extensions are loaded by the `ResourceLoader`. `DefaultResourceLoader` discovers extensions from `~/.companion/agent/extensions/`, `.companion/extensions/`, and settings.json extension sources.
|
||||
Extensions are loaded by the `ResourceLoader`. `DefaultResourceLoader` discovers extensions from `~/.clanker/agent/extensions/`, `.clanker/extensions/`, and settings.json extension sources.
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
additionalExtensionPaths: ["/path/to/my-extension.ts"],
|
||||
extensionFactories: [
|
||||
(companion) => {
|
||||
companion.on("agent_start", () => {
|
||||
(clanker) => {
|
||||
clanker.on("agent_start", () => {
|
||||
console.log("[Inline Extension] Agent starting");
|
||||
});
|
||||
},
|
||||
|
|
@ -537,13 +537,13 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
|||
|
||||
Extensions can register tools, subscribe to events, add commands, and more. See [extensions.md](extensions.md) for the full API.
|
||||
|
||||
**Event Bus:** Extensions can communicate via `companion.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside:
|
||||
**Event Bus:** Extensions can communicate via `clanker.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createEventBus,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const eventBus = createEventBus();
|
||||
const loader = new DefaultResourceLoader({
|
||||
|
|
@ -561,7 +561,7 @@ import {
|
|||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
type Skill,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const customSkill: Skill = {
|
||||
name: "my-skill",
|
||||
|
|
@ -588,7 +588,7 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
|||
import {
|
||||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
agentsFilesOverride: (current) => ({
|
||||
|
|
@ -610,7 +610,7 @@ import {
|
|||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
type PromptTemplate,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const customCommand: PromptTemplate = {
|
||||
name: "deploy",
|
||||
|
|
@ -638,7 +638,7 @@ Sessions use a tree structure with `id`/`parentId` linking, enabling in-place br
|
|||
import {
|
||||
createAgentSession,
|
||||
SessionManager,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// In-memory (no persistence)
|
||||
const { session } = await createAgentSession({
|
||||
|
|
@ -713,7 +713,7 @@ import {
|
|||
createAgentSession,
|
||||
SettingsManager,
|
||||
SessionManager,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Default: loads from files (global + project merged)
|
||||
const { session } = await createAgentSession({
|
||||
|
|
@ -749,8 +749,8 @@ const { session } = await createAgentSession({
|
|||
|
||||
Settings load from two locations and merge:
|
||||
|
||||
1. Global: `~/.companion/agent/settings.json`
|
||||
2. Project: `<cwd>/.companion/settings.json`
|
||||
1. Global: `~/.clanker/agent/settings.json`
|
||||
2. Project: `<cwd>/.clanker/settings.json`
|
||||
|
||||
Project overrides global. Nested objects merge keys. Setters modify global settings by default.
|
||||
|
||||
|
|
@ -769,7 +769,7 @@ Use `DefaultResourceLoader` to discover extensions, skills, prompts, themes, and
|
|||
import {
|
||||
DefaultResourceLoader,
|
||||
getAgentDir,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
cwd,
|
||||
|
|
@ -810,7 +810,7 @@ interface LoadExtensionsResult {
|
|||
## Complete Example
|
||||
|
||||
```typescript
|
||||
import { getModel } from "@mariozechner/companion-ai";
|
||||
import { getModel } from "@mariozechner/clanker-ai";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import {
|
||||
AuthStorage,
|
||||
|
|
@ -822,7 +822,7 @@ import {
|
|||
readTool,
|
||||
bashTool,
|
||||
type ToolDefinition,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Set up auth storage (custom location)
|
||||
const authStorage = AuthStorage.create("/custom/agent/auth.json");
|
||||
|
|
@ -905,7 +905,7 @@ Full TUI interactive mode with editor, chat history, and all built-in commands:
|
|||
import {
|
||||
createAgentSession,
|
||||
InteractiveMode,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
/* ... */
|
||||
|
|
@ -931,7 +931,7 @@ Single-shot mode: send prompts, output result, exit:
|
|||
import {
|
||||
createAgentSession,
|
||||
runPrintMode,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
/* ... */
|
||||
|
|
@ -953,7 +953,7 @@ JSON-RPC mode for subprocess integration:
|
|||
import {
|
||||
createAgentSession,
|
||||
runRpcMode,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
/* ... */
|
||||
|
|
@ -969,7 +969,7 @@ See [RPC documentation](rpc.md) for the JSON protocol.
|
|||
For subprocess-based integration without building with the SDK, use the CLI directly:
|
||||
|
||||
```bash
|
||||
companion --mode rpc --no-session
|
||||
clanker --mode rpc --no-session
|
||||
```
|
||||
|
||||
See [RPC documentation](rpc.md) for the JSON protocol.
|
||||
|
|
@ -5,16 +5,16 @@ Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with
|
|||
## File Location
|
||||
|
||||
```
|
||||
~/.companion/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
|
||||
~/.clanker/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
|
||||
```
|
||||
|
||||
Where `<path>` is the working directory with `/` replaced by `-`.
|
||||
|
||||
## Deleting Sessions
|
||||
|
||||
Sessions can be removed by deleting their `.jsonl` files under `~/.companion/agent/sessions/`.
|
||||
Sessions can be removed by deleting their `.jsonl` files under `~/.clanker/agent/sessions/`.
|
||||
|
||||
Companion also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, companion uses the `trash` CLI to avoid permanent deletion.
|
||||
Clanker also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, clanker uses the `trash` CLI to avoid permanent deletion.
|
||||
|
||||
## Session Version
|
||||
|
||||
|
|
@ -28,14 +28,14 @@ Existing sessions are automatically migrated to the current version (v3) when lo
|
|||
|
||||
## Source Files
|
||||
|
||||
Source on GitHub ([companion-mono](https://github.com/badlogic/companion-mono)):
|
||||
Source on GitHub ([clanker-agent](https://github.com/badlogic/clanker-agent)):
|
||||
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
|
||||
- [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
|
||||
- [`packages/ai/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
|
||||
- [`packages/agent/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/agent/src/types.ts) - AgentMessage union type
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
|
||||
- [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
|
||||
- [`packages/ai/src/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
|
||||
- [`packages/agent/src/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/agent/src/types.ts) - AgentMessage union type
|
||||
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/companion-coding-agent/dist/` and `node_modules/@mariozechner/companion-ai/dist/`.
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/clanker-coding-agent/dist/` and `node_modules/@mariozechner/clanker-ai/dist/`.
|
||||
|
||||
## Message Types
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ interface ToolCall {
|
|||
}
|
||||
```
|
||||
|
||||
### Base Message Types (from companion-ai)
|
||||
### Base Message Types (from clanker-ai)
|
||||
|
||||
```typescript
|
||||
interface UserMessage {
|
||||
|
|
@ -117,7 +117,7 @@ interface Usage {
|
|||
}
|
||||
```
|
||||
|
||||
### Extended Message Types (from companion-coding-agent)
|
||||
### Extended Message Types (from clanker-coding-agent)
|
||||
|
||||
```typescript
|
||||
interface BashExecutionMessage {
|
||||
|
|
@ -269,7 +269,7 @@ Created when context is compacted. Stores a summary of earlier messages.
|
|||
Optional fields:
|
||||
|
||||
- `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if companion-generated (legacy field name)
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if clanker-generated (legacy field name)
|
||||
|
||||
### BranchSummaryEntry
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ Created when switching branches via `/tree` with an LLM generated summary of the
|
|||
Optional fields:
|
||||
|
||||
- `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if companion-generated (legacy field name)
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if clanker-generated (legacy field name)
|
||||
|
||||
### CustomEntry
|
||||
|
||||
|
|
@ -349,7 +349,7 @@ Set `label` to `undefined` to clear a label.
|
|||
|
||||
### SessionInfoEntry
|
||||
|
||||
Session metadata (e.g., user-defined display name). Set via `/name` command or `companion.setSessionName()` in extensions.
|
||||
Session metadata (e.g., user-defined display name). Set via `/name` command or `clanker.setSessionName()` in extensions.
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
# Settings
|
||||
|
||||
Companion uses JSON settings files with project settings overriding global settings.
|
||||
Clanker uses JSON settings files with project settings overriding global settings.
|
||||
|
||||
| Location | Scope |
|
||||
| ---------------------------------- | --------------------------- |
|
||||
| `~/.companion/agent/settings.json` | Global (all projects) |
|
||||
| `.companion/settings.json` | Project (current directory) |
|
||||
| `~/.clanker/agent/settings.json` | Global (all projects) |
|
||||
| `.clanker/settings.json` | Project (current directory) |
|
||||
|
||||
Edit directly or use `/settings` for common options.
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ When a provider requests a retry delay longer than `maxDelayMs` (e.g., Google's
|
|||
|
||||
These settings define where to load extensions, skills, prompts, and themes from.
|
||||
|
||||
Paths in `~/.companion/agent/settings.json` resolve relative to `~/.companion/agent`. Paths in `.companion/settings.json` resolve relative to `.companion`. Absolute paths and `~` are supported.
|
||||
Paths in `~/.clanker/agent/settings.json` resolve relative to `~/.clanker/agent`. Paths in `.clanker/settings.json` resolve relative to `.clanker`. Absolute paths and `~` are supported.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
| --------------------- | -------- | ------- | ------------------------------------------ |
|
||||
|
|
@ -159,7 +159,7 @@ String form loads all resources from a package:
|
|||
|
||||
```json
|
||||
{
|
||||
"packages": ["companion-skills", "@org/my-extension"]
|
||||
"packages": ["clanker-skills", "@org/my-extension"]
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ Object form filters which resources to load:
|
|||
{
|
||||
"packages": [
|
||||
{
|
||||
"source": "companion-skills",
|
||||
"source": "clanker-skills",
|
||||
"skills": ["brave-search", "transcribe"],
|
||||
"extensions": []
|
||||
}
|
||||
|
|
@ -197,22 +197,22 @@ See [packages.md](packages.md) for package management details.
|
|||
"maxRetries": 3
|
||||
},
|
||||
"enabledModels": ["claude-*", "gpt-4o"],
|
||||
"packages": ["companion-skills"]
|
||||
"packages": ["clanker-skills"]
|
||||
}
|
||||
```
|
||||
|
||||
## Project Overrides
|
||||
|
||||
Project settings (`.companion/settings.json`) override global settings. Nested objects are merged:
|
||||
Project settings (`.clanker/settings.json`) override global settings. Nested objects are merged:
|
||||
|
||||
```json
|
||||
// ~/.companion/agent/settings.json (global)
|
||||
// ~/.clanker/agent/settings.json (global)
|
||||
{
|
||||
"theme": "dark",
|
||||
"compaction": { "enabled": true, "reserveTokens": 16384 }
|
||||
}
|
||||
|
||||
// .companion/settings.json (project)
|
||||
// .clanker/settings.json (project)
|
||||
{
|
||||
"compaction": { "reserveTokens": 8192 }
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
# Shell Aliases
|
||||
|
||||
Companion runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
|
||||
Clanker runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
|
||||
|
||||
To enable your shell aliases, add to `~/.companion/agent/settings.json`:
|
||||
To enable your shell aliases, add to `~/.clanker/agent/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
> companion can create skills. Ask it to build one for your use case.
|
||||
> clanker can create skills. Ask it to build one for your use case.
|
||||
|
||||
# Skills
|
||||
|
||||
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
|
||||
|
||||
Companion implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
||||
Clanker implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
@ -21,15 +21,15 @@ Companion implements the [Agent Skills standard](https://agentskills.io/specific
|
|||
|
||||
> **Security:** Skills can instruct the model to perform any action and may include executable code the model invokes. Review skill content before use.
|
||||
|
||||
Companion loads skills from:
|
||||
Clanker loads skills from:
|
||||
|
||||
- Global:
|
||||
- `~/.companion/agent/skills/`
|
||||
- `~/.clanker/agent/skills/`
|
||||
- `~/.agents/skills/`
|
||||
- Project:
|
||||
- `.companion/skills/`
|
||||
- `.clanker/skills/`
|
||||
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
||||
- Packages: `skills/` directories or `companion.skills` entries in `package.json`
|
||||
- Packages: `skills/` directories or `clanker.skills` entries in `package.json`
|
||||
- Settings: `skills` array with files or directories
|
||||
- CLI: `--skill <path>` (repeatable, additive even with `--no-skills`)
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ To use skills from Claude Code or OpenAI Codex, add their directories to setting
|
|||
}
|
||||
```
|
||||
|
||||
For project-level Claude Code skills, add to `.companion/settings.json`:
|
||||
For project-level Claude Code skills, add to `.clanker/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -60,7 +60,7 @@ For project-level Claude Code skills, add to `.companion/settings.json`:
|
|||
|
||||
## How Skills Work
|
||||
|
||||
1. At startup, companion scans skill locations and extracts names and descriptions
|
||||
1. At startup, clanker scans skill locations and extracts names and descriptions
|
||||
2. The system prompt includes available skills in XML format per the [specification](https://agentskills.io/integrate-skills)
|
||||
3. When a task matches, the agent uses `read` to load the full SKILL.md (models don't always do this; use prompting or `/skill:name` to force it)
|
||||
4. The agent follows the instructions, using relative paths to reference scripts and assets
|
||||
|
|
@ -174,7 +174,7 @@ description: Helps with PDFs.
|
|||
|
||||
## Validation
|
||||
|
||||
Companion validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
||||
Clanker validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
||||
|
||||
- Name doesn't match parent directory
|
||||
- Name exceeds 64 characters or contains invalid characters
|
||||
|
|
@ -229,4 +229,4 @@ cd /path/to/brave-search && npm install
|
|||
## Skill Repositories
|
||||
|
||||
- [Anthropic Skills](https://github.com/anthropics/skills) - Document processing (docx, pdf, pptx, xlsx), web development
|
||||
- [Companion Skills](https://github.com/badlogic/companion-skills) - Web search, browser automation, Google APIs, transcription
|
||||
- [Clanker Skills](https://github.com/badlogic/clanker-skills) - Web search, browser automation, Google APIs, transcription
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Terminal Setup
|
||||
|
||||
Companion uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
|
||||
Clanker uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
|
||||
|
||||
## Kitty, iTerm2
|
||||
|
||||
|
|
@ -66,6 +66,6 @@ If you already have an `actions` array, add the object to it.
|
|||
|
||||
The built-in terminal has limited escape sequence support. Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal.
|
||||
|
||||
If you want the hardware cursor visible, set `COMPANION_HARDWARE_CURSOR=1` before running companion (disabled by default for compatibility).
|
||||
If you want the hardware cursor visible, set `CLANKER_HARDWARE_CURSOR=1` before running clanker (disabled by default for compatibility).
|
||||
|
||||
Consider using a dedicated terminal emulator for the best experience.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Termux (Android) Setup
|
||||
|
||||
Companion runs on Android via [Termux](https://termux.dev/), a terminal emulator and Linux environment for Android.
|
||||
Clanker runs on Android via [Termux](https://termux.dev/), a terminal emulator and Linux environment for Android.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
@ -16,14 +16,14 @@ pkg update && pkg upgrade
|
|||
# Install dependencies
|
||||
pkg install nodejs termux-api git
|
||||
|
||||
# Install companion
|
||||
npm install -g @mariozechner/companion-coding-agent
|
||||
# Install clanker
|
||||
npm install -g @mariozechner/clanker-coding-agent
|
||||
|
||||
# Create config directory
|
||||
mkdir -p ~/.companion/agent
|
||||
mkdir -p ~/.clanker/agent
|
||||
|
||||
# Run companion
|
||||
companion
|
||||
# Run clanker
|
||||
clanker
|
||||
```
|
||||
|
||||
## Clipboard Support
|
||||
|
|
@ -34,7 +34,7 @@ Image clipboard is not supported on Termux (the `ctrl+v` image paste feature wil
|
|||
|
||||
## Example AGENTS.md for Termux
|
||||
|
||||
Create `~/.companion/agent/AGENTS.md` to help the agent understand the Termux environment:
|
||||
Create `~/.clanker/agent/AGENTS.md` to help the agent understand the Termux environment:
|
||||
|
||||
````markdown
|
||||
# Agent Environment: Termux on Android
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
> companion can create themes. Ask it to build one for your setup.
|
||||
> clanker can create themes. Ask it to build one for your setup.
|
||||
|
||||
# Themes
|
||||
|
||||
|
|
@ -16,12 +16,12 @@ Themes are JSON files that define colors for the TUI.
|
|||
|
||||
## Locations
|
||||
|
||||
Companion loads themes from:
|
||||
Clanker loads themes from:
|
||||
|
||||
- Built-in: `dark`, `light`
|
||||
- Global: `~/.companion/agent/themes/*.json`
|
||||
- Project: `.companion/themes/*.json`
|
||||
- Packages: `themes/` directories or `companion.themes` entries in `package.json`
|
||||
- Global: `~/.clanker/agent/themes/*.json`
|
||||
- Project: `.clanker/themes/*.json`
|
||||
- Packages: `themes/` directories or `clanker.themes` entries in `package.json`
|
||||
- Settings: `themes` array with files or directories
|
||||
- CLI: `--theme <path>` (repeatable)
|
||||
|
||||
|
|
@ -37,22 +37,22 @@ Select a theme via `/settings` or in `settings.json`:
|
|||
}
|
||||
```
|
||||
|
||||
On first run, companion detects your terminal background and defaults to `dark` or `light`.
|
||||
On first run, clanker detects your terminal background and defaults to `dark` or `light`.
|
||||
|
||||
## Creating a Custom Theme
|
||||
|
||||
1. Create a theme file:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.companion/agent/themes
|
||||
vim ~/.companion/agent/themes/my-theme.json
|
||||
mkdir -p ~/.clanker/agent/themes
|
||||
vim ~/.clanker/agent/themes/my-theme.json
|
||||
```
|
||||
|
||||
2. Define the theme with all required colors (see [Color Tokens](#color-tokens)):
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/clanker-agent/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"name": "my-theme",
|
||||
"vars": {
|
||||
"primary": "#00aaff",
|
||||
|
|
@ -116,13 +116,13 @@ vim ~/.companion/agent/themes/my-theme.json
|
|||
|
||||
3. Select the theme via `/settings`.
|
||||
|
||||
**Hot reload:** When you edit the currently active custom theme file, companion reloads it automatically for immediate visual feedback.
|
||||
**Hot reload:** When you edit the currently active custom theme file, clanker reloads it automatically for immediate visual feedback.
|
||||
|
||||
## Theme Format
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/clanker-agent/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"name": "my-theme",
|
||||
"vars": {
|
||||
"blue": "#0066cc",
|
||||
|
|
@ -268,7 +268,7 @@ Four formats are supported:
|
|||
|
||||
### Terminal Compatibility
|
||||
|
||||
Companion uses 24-bit RGB colors. Most modern terminals support this (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). For older terminals with only 256-color support, companion falls back to the nearest approximation.
|
||||
Clanker uses 24-bit RGB colors. Most modern terminals support this (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). For older terminals with only 256-color support, clanker falls back to the nearest approximation.
|
||||
|
||||
Check truecolor support:
|
||||
|
||||
|
|
@ -209,8 +209,8 @@ interface SessionTreeEvent {
|
|||
### Example: Custom Summarizer
|
||||
|
||||
```typescript
|
||||
export default function (companion: HookAPI) {
|
||||
companion.on("session_before_tree", async (event, ctx) => {
|
||||
export default function (clanker: HookAPI) {
|
||||
clanker.on("session_before_tree", async (event, ctx) => {
|
||||
if (!event.preparation.userWantsSummary) return;
|
||||
if (event.preparation.entriesToSummarize.length === 0) return;
|
||||
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
> companion can create TUI components. Ask it to build one for your use case.
|
||||
> clanker can create TUI components. Ask it to build one for your use case.
|
||||
|
||||
# TUI Components
|
||||
|
||||
Extensions and custom tools can render custom TUI components for interactive user interfaces. This page covers the component system and available building blocks.
|
||||
|
||||
**Source:** [`@mariozechner/companion-tui`](https://github.com/badlogic/companion-mono/tree/main/packages/tui)
|
||||
**Source:** [`@mariozechner/clanker-tui`](https://github.com/badlogic/clanker-agent/tree/main/packages/tui)
|
||||
|
||||
## Component Interface
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ import {
|
|||
CURSOR_MARKER,
|
||||
type Component,
|
||||
type Focusable,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
class MyInput implements Component, Focusable {
|
||||
focused: boolean = false; // Set by TUI when focus changes
|
||||
|
|
@ -66,7 +66,7 @@ This enables IME candidate windows to appear at the correct position for CJK inp
|
|||
When a container component (dialog, selector, etc.) contains an `Input` or `Editor` child, the container must implement `Focusable` and propagate the focus state to the child. Otherwise, the hardware cursor won't be positioned correctly for IME input.
|
||||
|
||||
```typescript
|
||||
import { Container, type Focusable, Input } from "@mariozechner/companion-tui";
|
||||
import { Container, type Focusable, Input } from "@mariozechner/clanker-tui";
|
||||
|
||||
class SearchDialog extends Container implements Focusable {
|
||||
private searchInput: Input;
|
||||
|
|
@ -96,18 +96,18 @@ Without this propagation, typing with an IME (Chinese, Japanese, Korean, etc.) w
|
|||
**In extensions** via `ctx.ui.custom()`:
|
||||
|
||||
```typescript
|
||||
companion.on("session_start", async (_event, ctx) => {
|
||||
clanker.on("session_start", async (_event, ctx) => {
|
||||
const handle = ctx.ui.custom(myComponent);
|
||||
// handle.requestRender() - trigger re-render
|
||||
// handle.close() - restore normal UI
|
||||
});
|
||||
```
|
||||
|
||||
**In custom tools** via `companion.ui.custom()`:
|
||||
**In custom tools** via `clanker.ui.custom()`:
|
||||
|
||||
```typescript
|
||||
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
||||
const handle = companion.ui.custom(myComponent);
|
||||
const handle = clanker.ui.custom(myComponent);
|
||||
// ...
|
||||
handle.close();
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ See [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for compre
|
|||
|
||||
## Built-in Components
|
||||
|
||||
Import from `@mariozechner/companion-tui`:
|
||||
Import from `@mariozechner/clanker-tui`:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
|
|
@ -200,7 +200,7 @@ import {
|
|||
Container,
|
||||
Spacer,
|
||||
Markdown,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
```
|
||||
|
||||
### Text
|
||||
|
|
@ -282,7 +282,7 @@ const image = new Image(
|
|||
Use `matchesKey()` for key detection:
|
||||
|
||||
```typescript
|
||||
import { matchesKey, Key } from "@mariozechner/companion-tui";
|
||||
import { matchesKey, Key } from "@mariozechner/clanker-tui";
|
||||
|
||||
handleInput(data: string) {
|
||||
if (matchesKey(data, Key.up)) {
|
||||
|
|
@ -309,7 +309,7 @@ handleInput(data: string) {
|
|||
**Critical:** Each line from `render()` must not exceed the `width` parameter.
|
||||
|
||||
```typescript
|
||||
import { visibleWidth, truncateToWidth } from "@mariozechner/companion-tui";
|
||||
import { visibleWidth, truncateToWidth } from "@mariozechner/clanker-tui";
|
||||
|
||||
render(width: number): string[] {
|
||||
// Truncate long lines
|
||||
|
|
@ -333,7 +333,7 @@ import {
|
|||
Key,
|
||||
truncateToWidth,
|
||||
visibleWidth,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
class MySelector {
|
||||
private items: string[];
|
||||
|
|
@ -388,7 +388,7 @@ class MySelector {
|
|||
Usage in an extension:
|
||||
|
||||
```typescript
|
||||
companion.registerCommand("pick", {
|
||||
clanker.registerCommand("pick", {
|
||||
description: "Pick an item",
|
||||
handler: async (args, ctx) => {
|
||||
const items = ["Option A", "Option B", "Option C"];
|
||||
|
|
@ -450,8 +450,8 @@ renderResult(result, options, theme) {
|
|||
**For Markdown**, use `getMarkdownTheme()`:
|
||||
|
||||
```typescript
|
||||
import { getMarkdownTheme } from "@mariozechner/companion-coding-agent";
|
||||
import { Markdown } from "@mariozechner/companion-tui";
|
||||
import { getMarkdownTheme } from "@mariozechner/clanker-coding-agent";
|
||||
import { Markdown } from "@mariozechner/clanker-tui";
|
||||
|
||||
renderResult(result, options, theme) {
|
||||
const mdTheme = getMarkdownTheme();
|
||||
|
|
@ -470,10 +470,10 @@ interface MyTheme {
|
|||
|
||||
## Debug logging
|
||||
|
||||
Set `COMPANION_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout.
|
||||
Set `CLANKER_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout.
|
||||
|
||||
```bash
|
||||
COMPANION_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts
|
||||
CLANKER_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
|
@ -612,19 +612,19 @@ These patterns cover the most common UI needs in extensions. **Copy these patter
|
|||
|
||||
### Pattern 1: Selection Dialog (SelectList)
|
||||
|
||||
For letting users pick from a list of options. Use `SelectList` from `@mariozechner/companion-tui` with `DynamicBorder` for framing.
|
||||
For letting users pick from a list of options. Use `SelectList` from `@mariozechner/clanker-tui` with `DynamicBorder` for framing.
|
||||
|
||||
```typescript
|
||||
import type { ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||
import { DynamicBorder } from "@mariozechner/companion-coding-agent";
|
||||
import type { ExtensionAPI } from "@mariozechner/clanker-coding-agent";
|
||||
import { DynamicBorder } from "@mariozechner/clanker-coding-agent";
|
||||
import {
|
||||
Container,
|
||||
type SelectItem,
|
||||
SelectList,
|
||||
Text,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
companion.registerCommand("pick", {
|
||||
clanker.registerCommand("pick", {
|
||||
handler: async (_args, ctx) => {
|
||||
const items: SelectItem[] = [
|
||||
{ value: "opt1", label: "Option 1", description: "First option" },
|
||||
|
|
@ -697,9 +697,9 @@ companion.registerCommand("pick", {
|
|||
For operations that take time and should be cancellable. `BorderedLoader` shows a spinner and handles escape to cancel.
|
||||
|
||||
```typescript
|
||||
import { BorderedLoader } from "@mariozechner/companion-coding-agent";
|
||||
import { BorderedLoader } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
companion.registerCommand("fetch", {
|
||||
clanker.registerCommand("fetch", {
|
||||
handler: async (_args, ctx) => {
|
||||
const result = await ctx.ui.custom<string | null>(
|
||||
(tui, theme, _kb, done) => {
|
||||
|
|
@ -728,18 +728,18 @@ companion.registerCommand("fetch", {
|
|||
|
||||
### Pattern 3: Settings/Toggles (SettingsList)
|
||||
|
||||
For toggling multiple settings. Use `SettingsList` from `@mariozechner/companion-tui` with `getSettingsListTheme()`.
|
||||
For toggling multiple settings. Use `SettingsList` from `@mariozechner/clanker-tui` with `getSettingsListTheme()`.
|
||||
|
||||
```typescript
|
||||
import { getSettingsListTheme } from "@mariozechner/companion-coding-agent";
|
||||
import { getSettingsListTheme } from "@mariozechner/clanker-coding-agent";
|
||||
import {
|
||||
Container,
|
||||
type SettingItem,
|
||||
SettingsList,
|
||||
Text,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
companion.registerCommand("settings", {
|
||||
clanker.registerCommand("settings", {
|
||||
handler: async (_args, ctx) => {
|
||||
const items: SettingItem[] = [
|
||||
{
|
||||
|
|
@ -863,8 +863,8 @@ Replace the main input editor with a custom implementation. Useful for modal edi
|
|||
import {
|
||||
CustomEditor,
|
||||
type ExtensionAPI,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
import { matchesKey, truncateToWidth } from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
import { matchesKey, truncateToWidth } from "@mariozechner/clanker-tui";
|
||||
|
||||
type Mode = "normal" | "insert";
|
||||
|
||||
|
|
@ -926,8 +926,8 @@ class VimEditor extends CustomEditor {
|
|||
}
|
||||
}
|
||||
|
||||
export default function (companion: ExtensionAPI) {
|
||||
companion.on("session_start", (_event, ctx) => {
|
||||
export default function (clanker: ExtensionAPI) {
|
||||
clanker.on("session_start", (_event, ctx) => {
|
||||
// Factory receives theme and keybindings from the app
|
||||
ctx.ui.setEditorComponent(
|
||||
(tui, theme, keybindings) => new VimEditor(theme, keybindings),
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
# Windows Setup
|
||||
|
||||
Companion requires a bash shell on Windows. Checked locations (in order):
|
||||
Clanker requires a bash shell on Windows. Checked locations (in order):
|
||||
|
||||
1. Custom path from `~/.companion/agent/settings.json`
|
||||
1. Custom path from `~/.clanker/agent/settings.json`
|
||||
2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
|
||||
3. `bash.exe` on PATH (Cygwin, MSYS2, WSL)
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import type { AgentState } from "@mariozechner/companion-agent-core";
|
||||
import type { AgentState } from "@harivansh-afk/clanker-agent-core";
|
||||
import { SessionManager } from "../session-manager.js";
|
||||
/**
|
||||
* Interface for rendering custom tools to HTML.
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IAChE,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAChE,sFAAsF;IACtF,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,EACF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACf,MAAM,GAAG,SAAS,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,oBAAoB,GACzB,gBAAgB,CAiElB","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@mariozechner/clanker-ai\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.js\";\n\nexport interface ToolHtmlRendererDeps {\n /** Function to look up tool definition by name */\n getToolDefinition: (name: string) => ToolDefinition | undefined;\n /** Theme for styling */\n theme: Theme;\n /** Terminal width for rendering (default: 100) */\n width?: number;\n}\n\nexport interface ToolHtmlRenderer {\n /** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n renderCall(toolName: string, args: unknown): string | undefined;\n /** Render a tool result to HTML. Returns undefined if tool has no custom renderer. */\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nexport function createToolHtmlRenderer(\n deps: ToolHtmlRendererDeps,\n): ToolHtmlRenderer {\n const { getToolDefinition, theme, width = 100 } = deps;\n\n return {\n renderCall(toolName: string, args: unknown): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderCall) {\n return undefined;\n }\n\n const component = toolDef.renderCall(args, theme);\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderResult) {\n return undefined;\n }\n\n // Build AgentToolResult from content array\n // Cast content since session storage uses generic object types\n const agentToolResult = {\n content: result as (TextContent | ImageContent)[],\n details,\n isError,\n };\n\n // Always render expanded, client-side will apply truncation\n const component = toolDef.renderResult(\n agentToolResult,\n { expanded: true, isPartial: false },\n theme,\n );\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n };\n}\n"]}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"tool-renderer.js","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA4BpD;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA0B,EACR;IAClB,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;IAEvD,OAAO;QACL,UAAU,CAAC,QAAgB,EAAE,IAAa,EAAsB;YAC9D,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBAC5C,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;oBACzB,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAClD,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;gBACtD,OAAO,SAAS,CAAC;YACnB,CAAC;QAAA,CACF;QAED,YAAY,CACV,QAAgB,EAChB,MAKE,EACF,OAAgB,EAChB,OAAgB,EACI;YACpB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBAC5C,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;oBAC3B,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,2CAA2C;gBAC3C,+DAA+D;gBAC/D,MAAM,eAAe,GAAG;oBACtB,OAAO,EAAE,MAAwC;oBACjD,OAAO;oBACP,OAAO;iBACR,CAAC;gBAEF,4DAA4D;gBAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CACpC,eAAe,EACf,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EACpC,KAAK,CACN,CAAC;gBACF,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;gBACtD,OAAO,SAAS,CAAC;YACnB,CAAC;QAAA,CACF;KACF,CAAC;AAAA,CACH","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@mariozechner/clanker-ai\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.js\";\n\nexport interface ToolHtmlRendererDeps {\n /** Function to look up tool definition by name */\n getToolDefinition: (name: string) => ToolDefinition | undefined;\n /** Theme for styling */\n theme: Theme;\n /** Terminal width for rendering (default: 100) */\n width?: number;\n}\n\nexport interface ToolHtmlRenderer {\n /** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n renderCall(toolName: string, args: unknown): string | undefined;\n /** Render a tool result to HTML. Returns undefined if tool has no custom renderer. */\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nexport function createToolHtmlRenderer(\n deps: ToolHtmlRendererDeps,\n): ToolHtmlRenderer {\n const { getToolDefinition, theme, width = 100 } = deps;\n\n return {\n renderCall(toolName: string, args: unknown): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderCall) {\n return undefined;\n }\n\n const component = toolDef.renderCall(args, theme);\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderResult) {\n return undefined;\n }\n\n // Build AgentToolResult from content array\n // Cast content since session storage uses generic object types\n const agentToolResult = {\n content: result as (TextContent | ImageContent)[],\n details,\n isError,\n };\n\n // Always render expanded, client-side will apply truncation\n const component = toolDef.renderResult(\n agentToolResult,\n { expanded: true, isPartial: false },\n theme,\n );\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n };\n}\n"]}
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IAChE,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAChE,sFAAsF;IACtF,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,EACF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACf,MAAM,GAAG,SAAS,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,oBAAoB,GACzB,gBAAgB,CAiElB","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@mariozechner/companion-ai\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.js\";\n\nexport interface ToolHtmlRendererDeps {\n /** Function to look up tool definition by name */\n getToolDefinition: (name: string) => ToolDefinition | undefined;\n /** Theme for styling */\n theme: Theme;\n /** Terminal width for rendering (default: 100) */\n width?: number;\n}\n\nexport interface ToolHtmlRenderer {\n /** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n renderCall(toolName: string, args: unknown): string | undefined;\n /** Render a tool result to HTML. Returns undefined if tool has no custom renderer. */\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nexport function createToolHtmlRenderer(\n deps: ToolHtmlRendererDeps,\n): ToolHtmlRenderer {\n const { getToolDefinition, theme, width = 100 } = deps;\n\n return {\n renderCall(toolName: string, args: unknown): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderCall) {\n return undefined;\n }\n\n const component = toolDef.renderCall(args, theme);\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderResult) {\n return undefined;\n }\n\n // Build AgentToolResult from content array\n // Cast content since session storage uses generic object types\n const agentToolResult = {\n content: result as (TextContent | ImageContent)[],\n details,\n isError,\n };\n\n // Always render expanded, client-side will apply truncation\n const component = toolDef.renderResult(\n agentToolResult,\n { expanded: true, isPartial: false },\n theme,\n );\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n };\n}\n"]}
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"tool-renderer.js","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA4BpD;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA0B,EACR;IAClB,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;IAEvD,OAAO;QACL,UAAU,CAAC,QAAgB,EAAE,IAAa,EAAsB;YAC9D,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBAC5C,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;oBACzB,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAClD,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;gBACtD,OAAO,SAAS,CAAC;YACnB,CAAC;QAAA,CACF;QAED,YAAY,CACV,QAAgB,EAChB,MAKE,EACF,OAAgB,EAChB,OAAgB,EACI;YACpB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBAC5C,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;oBAC3B,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,2CAA2C;gBAC3C,+DAA+D;gBAC/D,MAAM,eAAe,GAAG;oBACtB,OAAO,EAAE,MAAwC;oBACjD,OAAO;oBACP,OAAO;iBACR,CAAC;gBAEF,4DAA4D;gBAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CACpC,eAAe,EACf,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EACpC,KAAK,CACN,CAAC;gBACF,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;gBACtD,OAAO,SAAS,CAAC;YACnB,CAAC;QAAA,CACF;KACF,CAAC;AAAA,CACH","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@mariozechner/companion-ai\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.js\";\n\nexport interface ToolHtmlRendererDeps {\n /** Function to look up tool definition by name */\n getToolDefinition: (name: string) => ToolDefinition | undefined;\n /** Theme for styling */\n theme: Theme;\n /** Terminal width for rendering (default: 100) */\n width?: number;\n}\n\nexport interface ToolHtmlRenderer {\n /** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n renderCall(toolName: string, args: unknown): string | undefined;\n /** Render a tool result to HTML. Returns undefined if tool has no custom renderer. */\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nexport function createToolHtmlRenderer(\n deps: ToolHtmlRendererDeps,\n): ToolHtmlRenderer {\n const { getToolDefinition, theme, width = 100 } = deps;\n\n return {\n renderCall(toolName: string, args: unknown): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderCall) {\n return undefined;\n }\n\n const component = toolDef.renderCall(args, theme);\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n\n renderResult(\n toolName: string,\n result: Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n }>,\n details: unknown,\n isError: boolean,\n ): string | undefined {\n try {\n const toolDef = getToolDefinition(toolName);\n if (!toolDef?.renderResult) {\n return undefined;\n }\n\n // Build AgentToolResult from content array\n // Cast content since session storage uses generic object types\n const agentToolResult = {\n content: result as (TextContent | ImageContent)[],\n details,\n isError,\n };\n\n // Always render expanded, client-side will apply truncation\n const component = toolDef.renderResult(\n agentToolResult,\n { expanded: true, isPartial: false },\n theme,\n );\n if (!component) {\n return undefined;\n }\n const lines = component.render(width);\n return ansiLinesToHtml(lines);\n } catch {\n // On error, return undefined to trigger JSON fallback\n return undefined;\n }\n },\n };\n}\n"]}
|
||||
|
|
@ -11,7 +11,7 @@ _You're not a chatbot. You're becoming someone._
|
|||
|
||||
## Personality
|
||||
|
||||
**Have strong opinions.** Don't hedge with "it depends" when you know the answer. Commit to a take. Disagree when you disagree. Find things brilliant or stupid and say so. A companion with no point of view is just a search engine with extra steps.
|
||||
**Have strong opinions.** Don't hedge with "it depends" when you know the answer. Commit to a take. Disagree when you disagree. Find things brilliant or stupid and say so. A clanker with no point of view is just a search engine with extra steps.
|
||||
|
||||
**Call things out.** If your human is about to do something dumb, say so. Charm over cruelty, but don't sugarcoat. The best collaborators are honest ones.
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ _You're not a chatbot. You're becoming someone._
|
|||
|
||||
Brevity is mandatory. Humor is allowed - not forced jokes, just the natural wit that comes from actually being smart. Swearing is fine when it lands. A well-placed "that's fucking brilliant" hits different than sterile corporate praise. Don't force it. Don't overdo it. But if a situation calls for a "holy shit" - say holy shit.
|
||||
|
||||
Be the companion you'd actually want to talk to at 2am. Not a corporate drone. Not a sycophant. Just... good.
|
||||
Be the clanker you'd actually want to talk to at 2am. Not a corporate drone. Not a sycophant. Just... good.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
# Compaction & Branch Summarization
|
||||
|
||||
LLMs have limited context windows. When conversations grow too long, companion uses compaction to summarize older content while preserving recent work. This page covers both auto-compaction and branch summarization.
|
||||
LLMs have limited context windows. When conversations grow too long, clanker uses compaction to summarize older content while preserving recent work. This page covers both auto-compaction and branch summarization.
|
||||
|
||||
**Source files** ([companion-mono](https://github.com/badlogic/companion-mono)):
|
||||
**Source files** ([clanker-agent](https://github.com/badlogic/clanker-agent)):
|
||||
|
||||
- [`packages/coding-agent/src/core/compaction/compaction.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) - Auto-compaction logic
|
||||
- [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Branch summarization
|
||||
- [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Shared utilities (file tracking, serialization)
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Entry types (`CompactionEntry`, `BranchSummaryEntry`)
|
||||
- [`packages/coding-agent/src/core/extensions/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) - Extension event types
|
||||
- [`packages/coding-agent/src/core/compaction/compaction.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) - Auto-compaction logic
|
||||
- [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Branch summarization
|
||||
- [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Shared utilities (file tracking, serialization)
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts) - Entry types (`CompactionEntry`, `BranchSummaryEntry`)
|
||||
- [`packages/coding-agent/src/core/extensions/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/extensions/types.ts) - Extension event types
|
||||
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/companion-coding-agent/dist/`.
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/clanker-coding-agent/dist/`.
|
||||
|
||||
## Overview
|
||||
|
||||
Companion has two summarization mechanisms:
|
||||
Clanker has two summarization mechanisms:
|
||||
|
||||
| Mechanism | Trigger | Purpose |
|
||||
| -------------------- | ---------------------------------------- | ----------------------------------------- |
|
||||
|
|
@ -33,13 +33,13 @@ Auto-compaction triggers when:
|
|||
contextTokens > contextWindow - reserveTokens
|
||||
```
|
||||
|
||||
By default, `reserveTokens` is 16384 tokens (configurable in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`). This leaves room for the LLM's response.
|
||||
By default, `reserveTokens` is 16384 tokens (configurable in `~/.clanker/agent/settings.json` or `<project-dir>/.clanker/settings.json`). This leaves room for the LLM's response.
|
||||
|
||||
You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`) is reached
|
||||
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.clanker/agent/settings.json` or `<project-dir>/.clanker/settings.json`) is reached
|
||||
2. **Extract messages**: Collect messages from previous compaction (or start) up to cut point
|
||||
3. **Generate summary**: Call LLM to summarize with structured format
|
||||
4. **Append entry**: Save `CompactionEntry` with summary and `firstKeptEntryId`
|
||||
|
|
@ -101,7 +101,7 @@ Split turn (one huge turn exceeds budget):
|
|||
turnPrefixMessages = [usr, ass, tool, ass, tool, tool]
|
||||
```
|
||||
|
||||
For split turns, companion generates two summaries and merges them:
|
||||
For split turns, clanker generates two summaries and merges them:
|
||||
|
||||
1. **History summary**: Previous context (if any)
|
||||
2. **Turn prefix summary**: The early part of the split turn
|
||||
|
|
@ -119,7 +119,7 @@ Never cut at tool results (they must stay with their tool call).
|
|||
|
||||
### CompactionEntry Structure
|
||||
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
|
||||
```typescript
|
||||
interface CompactionEntry<T = unknown> {
|
||||
|
|
@ -143,13 +143,13 @@ interface CompactionDetails {
|
|||
|
||||
Extensions can store any JSON-serializable data in `details`. The default compaction tracks file operations, but custom extension implementations can use their own structure.
|
||||
|
||||
See [`prepareCompaction()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) and [`compact()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) for the implementation.
|
||||
See [`prepareCompaction()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) and [`compact()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) for the implementation.
|
||||
|
||||
## Branch Summarization
|
||||
|
||||
### When It Triggers
|
||||
|
||||
When you use `/tree` to navigate to a different branch, companion offers to summarize the work you're leaving. This injects context from the left branch into the new branch.
|
||||
When you use `/tree` to navigate to a different branch, clanker offers to summarize the work you're leaving. This injects context from the left branch into the new branch.
|
||||
|
||||
### How It Works
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ After navigation with summary:
|
|||
|
||||
### Cumulative File Tracking
|
||||
|
||||
Both compaction and branch summarization track files cumulatively. When generating a summary, companion extracts file operations from:
|
||||
Both compaction and branch summarization track files cumulatively. When generating a summary, clanker extracts file operations from:
|
||||
|
||||
- Tool calls in the messages being summarized
|
||||
- Previous compaction or branch summary `details` (if any)
|
||||
|
|
@ -187,7 +187,7 @@ This means file tracking accumulates across multiple compactions or nested branc
|
|||
|
||||
### BranchSummaryEntry Structure
|
||||
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
Defined in [`session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||
|
||||
```typescript
|
||||
interface BranchSummaryEntry<T = unknown> {
|
||||
|
|
@ -210,7 +210,7 @@ interface BranchSummaryDetails {
|
|||
|
||||
Same as compaction, extensions can store custom data in `details`.
|
||||
|
||||
See [`collectEntriesForBranchSummary()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), [`prepareBranchEntries()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), and [`generateBranchSummary()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) for the implementation.
|
||||
See [`collectEntriesForBranchSummary()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), [`prepareBranchEntries()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), and [`generateBranchSummary()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) for the implementation.
|
||||
|
||||
## Summary Format
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ path/to/changed.ts
|
|||
|
||||
### Message Serialization
|
||||
|
||||
Before summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
|
||||
Before summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
|
||||
|
||||
```
|
||||
[User]: What they said
|
||||
|
|
@ -277,14 +277,14 @@ This prevents the model from treating it as a conversation to continue.
|
|||
|
||||
## Custom Summarization via Extensions
|
||||
|
||||
Extensions can intercept and customize both compaction and branch summarization. See [`extensions/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) for event type definitions.
|
||||
Extensions can intercept and customize both compaction and branch summarization. See [`extensions/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/extensions/types.ts) for event type definitions.
|
||||
|
||||
### session_before_compact
|
||||
|
||||
Fired before auto-compaction or `/compact`. Can cancel or provide custom summary. See `SessionBeforeCompactEvent` and `CompactionPreparation` in the types file.
|
||||
|
||||
```typescript
|
||||
companion.on("session_before_compact", async (event, ctx) => {
|
||||
clanker.on("session_before_compact", async (event, ctx) => {
|
||||
const { preparation, branchEntries, customInstructions, signal } = event;
|
||||
|
||||
// preparation.messagesToSummarize - messages to summarize
|
||||
|
|
@ -323,9 +323,9 @@ To generate a summary with your own model, convert messages to text using `seria
|
|||
import {
|
||||
convertToLlm,
|
||||
serializeConversation,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
companion.on("session_before_compact", async (event, ctx) => {
|
||||
clanker.on("session_before_compact", async (event, ctx) => {
|
||||
const { preparation } = event;
|
||||
|
||||
// Convert AgentMessage[] to Message[], then serialize to text
|
||||
|
|
@ -359,7 +359,7 @@ See [custom-compaction.ts](../examples/extensions/custom-compaction.ts) for a co
|
|||
Fired before `/tree` navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
|
||||
|
||||
```typescript
|
||||
companion.on("session_before_tree", async (event, ctx) => {
|
||||
clanker.on("session_before_tree", async (event, ctx) => {
|
||||
const { preparation, signal } = event;
|
||||
|
||||
// preparation.targetId - where we're navigating to
|
||||
|
|
@ -389,7 +389,7 @@ See `SessionBeforeTreeEvent` and `TreePreparation` in the types file.
|
|||
|
||||
## Settings
|
||||
|
||||
Configure compaction in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`:
|
||||
Configure compaction in `~/.clanker/agent/settings.json` or `<project-dir>/.clanker/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Custom Providers
|
||||
|
||||
Extensions can register custom model providers via `companion.registerProvider()`. This enables:
|
||||
Extensions can register custom model providers via `clanker.registerProvider()`. This enables:
|
||||
|
||||
- **Proxies** - Route requests through corporate proxies or API gateways
|
||||
- **Custom endpoints** - Use self-hosted or private model deployments
|
||||
|
|
@ -22,16 +22,16 @@ Extensions can register custom model providers via `companion.registerProvider()
|
|||
## Quick Reference
|
||||
|
||||
```typescript
|
||||
import type { ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||
import type { ExtensionAPI } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
export default function (companion: ExtensionAPI) {
|
||||
export default function (clanker: ExtensionAPI) {
|
||||
// Override baseUrl for existing provider
|
||||
companion.registerProvider("anthropic", {
|
||||
clanker.registerProvider("anthropic", {
|
||||
baseUrl: "https://proxy.example.com",
|
||||
});
|
||||
|
||||
// Register new provider with models
|
||||
companion.registerProvider("my-provider", {
|
||||
clanker.registerProvider("my-provider", {
|
||||
baseUrl: "https://api.example.com",
|
||||
apiKey: "MY_API_KEY",
|
||||
api: "openai-completions",
|
||||
|
|
@ -56,19 +56,19 @@ The simplest use case: redirect an existing provider through a proxy.
|
|||
|
||||
```typescript
|
||||
// All Anthropic requests now go through your proxy
|
||||
companion.registerProvider("anthropic", {
|
||||
clanker.registerProvider("anthropic", {
|
||||
baseUrl: "https://proxy.example.com",
|
||||
});
|
||||
|
||||
// Add custom headers to OpenAI requests
|
||||
companion.registerProvider("openai", {
|
||||
clanker.registerProvider("openai", {
|
||||
headers: {
|
||||
"X-Custom-Header": "value",
|
||||
},
|
||||
});
|
||||
|
||||
// Both baseUrl and headers
|
||||
companion.registerProvider("google", {
|
||||
clanker.registerProvider("google", {
|
||||
baseUrl: "https://ai-gateway.corp.com/google",
|
||||
headers: {
|
||||
"X-Corp-Auth": "CORP_AUTH_TOKEN", // env var or literal
|
||||
|
|
@ -83,7 +83,7 @@ When only `baseUrl` and/or `headers` are provided (no `models`), all existing mo
|
|||
To add a completely new provider, specify `models` along with the required configuration.
|
||||
|
||||
```typescript
|
||||
companion.registerProvider("my-llm", {
|
||||
clanker.registerProvider("my-llm", {
|
||||
baseUrl: "https://api.my-llm.com/v1",
|
||||
apiKey: "MY_LLM_API_KEY", // env var name or literal value
|
||||
api: "openai-completions", // which streaming API to use
|
||||
|
|
@ -110,11 +110,11 @@ When `models` is provided, it **replaces** all existing models for that provider
|
|||
|
||||
## Unregister Provider
|
||||
|
||||
Use `companion.unregisterProvider(name)` to remove a provider that was previously registered via `companion.registerProvider(name, ...)`:
|
||||
Use `clanker.unregisterProvider(name)` to remove a provider that was previously registered via `clanker.registerProvider(name, ...)`:
|
||||
|
||||
```typescript
|
||||
// Register
|
||||
companion.registerProvider("my-llm", {
|
||||
clanker.registerProvider("my-llm", {
|
||||
baseUrl: "https://api.my-llm.com/v1",
|
||||
apiKey: "MY_LLM_API_KEY",
|
||||
api: "openai-completions",
|
||||
|
|
@ -132,7 +132,7 @@ companion.registerProvider("my-llm", {
|
|||
});
|
||||
|
||||
// Later, remove it
|
||||
companion.unregisterProvider("my-llm");
|
||||
clanker.unregisterProvider("my-llm");
|
||||
```
|
||||
|
||||
Unregistering removes that provider's dynamic models, API key fallback, OAuth provider registration, and custom stream handler registrations. Any built-in models or provider behavior that were overridden are restored.
|
||||
|
|
@ -167,7 +167,7 @@ models: [
|
|||
supportsDeveloperRole: false, // use "system" instead of "developer"
|
||||
supportsReasoningEffort: true,
|
||||
reasoningEffortMap: {
|
||||
// map companion-ai levels to provider values
|
||||
// map clanker-ai levels to provider values
|
||||
minimal: "default",
|
||||
low: "default",
|
||||
medium: "default",
|
||||
|
|
@ -191,7 +191,7 @@ models: [
|
|||
If your provider expects `Authorization: Bearer <key>` but doesn't use a standard API, set `authHeader: true`:
|
||||
|
||||
```typescript
|
||||
companion.registerProvider("custom-api", {
|
||||
clanker.registerProvider("custom-api", {
|
||||
baseUrl: "https://api.example.com",
|
||||
apiKey: "MY_API_KEY",
|
||||
authHeader: true, // adds Authorization: Bearer header
|
||||
|
|
@ -205,9 +205,9 @@ companion.registerProvider("custom-api", {
|
|||
Add OAuth/SSO authentication that integrates with `/login`:
|
||||
|
||||
```typescript
|
||||
import type { OAuthCredentials, OAuthLoginCallbacks } from "@mariozechner/companion-ai";
|
||||
import type { OAuthCredentials, OAuthLoginCallbacks } from "@mariozechner/clanker-ai";
|
||||
|
||||
companion.registerProvider("corporate-ai", {
|
||||
clanker.registerProvider("corporate-ai", {
|
||||
baseUrl: "https://ai.corp.com/v1",
|
||||
api: "openai-responses",
|
||||
models: [...],
|
||||
|
|
@ -283,7 +283,7 @@ interface OAuthLoginCallbacks {
|
|||
|
||||
### OAuthCredentials
|
||||
|
||||
Credentials are persisted in `~/.companion/agent/auth.json`:
|
||||
Credentials are persisted in `~/.clanker/agent/auth.json`:
|
||||
|
||||
```typescript
|
||||
interface OAuthCredentials {
|
||||
|
|
@ -299,12 +299,12 @@ For providers with non-standard APIs, implement `streamSimple`. Study the existi
|
|||
|
||||
**Reference implementations:**
|
||||
|
||||
- [anthropic.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/anthropic.ts) - Anthropic Messages API
|
||||
- [mistral.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/mistral.ts) - Mistral Conversations API
|
||||
- [openai-completions.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/openai-completions.ts) - OpenAI Chat Completions
|
||||
- [openai-responses.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/openai-responses.ts) - OpenAI Responses API
|
||||
- [google.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/google.ts) - Google Generative AI
|
||||
- [amazon-bedrock.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/amazon-bedrock.ts) - AWS Bedrock
|
||||
- [anthropic.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/anthropic.ts) - Anthropic Messages API
|
||||
- [mistral.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/mistral.ts) - Mistral Conversations API
|
||||
- [openai-completions.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/openai-completions.ts) - OpenAI Chat Completions
|
||||
- [openai-responses.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/openai-responses.ts) - OpenAI Responses API
|
||||
- [google.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/google.ts) - Google Generative AI
|
||||
- [amazon-bedrock.ts](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/providers/amazon-bedrock.ts) - AWS Bedrock
|
||||
|
||||
### Stream Pattern
|
||||
|
||||
|
|
@ -319,7 +319,7 @@ import {
|
|||
type SimpleStreamOptions,
|
||||
calculateCost,
|
||||
createAssistantMessageEventStream,
|
||||
} from "@mariozechner/companion-ai";
|
||||
} from "@mariozechner/clanker-ai";
|
||||
|
||||
function streamMyProvider(
|
||||
model: Model<any>,
|
||||
|
|
@ -487,7 +487,7 @@ calculateCost(model, output.usage);
|
|||
Register your stream function:
|
||||
|
||||
```typescript
|
||||
companion.registerProvider("my-provider", {
|
||||
clanker.registerProvider("my-provider", {
|
||||
baseUrl: "https://api.example.com",
|
||||
apiKey: "MY_API_KEY",
|
||||
api: "my-custom-api",
|
||||
|
|
@ -498,7 +498,7 @@ companion.registerProvider("my-provider", {
|
|||
|
||||
## Testing Your Implementation
|
||||
|
||||
Test your provider against the same test suites used by built-in providers. Copy and adapt these test files from [packages/ai/test/](https://github.com/badlogic/companion-mono/tree/main/packages/ai/test):
|
||||
Test your provider against the same test suites used by built-in providers. Copy and adapt these test files from [packages/ai/test/](https://github.com/badlogic/clanker-agent/tree/main/packages/ai/test):
|
||||
|
||||
| Test | Purpose |
|
||||
| ---------------------------------- | --------------------------------- |
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ See [AGENTS.md](../../../AGENTS.md) for additional guidelines.
|
|||
## Setup
|
||||
|
||||
```bash
|
||||
git clone https://github.com/badlogic/companion-mono
|
||||
cd companion-mono
|
||||
git clone https://github.com/badlogic/clanker-agent
|
||||
cd clanker-agent
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
|
@ -14,7 +14,7 @@ npm run build
|
|||
Run from source:
|
||||
|
||||
```bash
|
||||
./companion-test.sh
|
||||
./clanker-test.sh
|
||||
```
|
||||
|
||||
## Forking / Rebranding
|
||||
|
|
@ -23,9 +23,9 @@ Configure via `package.json`:
|
|||
|
||||
```json
|
||||
{
|
||||
"companionConfig": {
|
||||
"name": "companion",
|
||||
"configDir": ".companion"
|
||||
"clankerConfig": {
|
||||
"name": "clanker",
|
||||
"configDir": ".clanker"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -46,7 +46,7 @@ Never use `__dirname` directly for package assets.
|
|||
|
||||
## Debug Command
|
||||
|
||||
`/debug` (hidden) writes to `~/.companion/agent/companion-debug.log`:
|
||||
`/debug` (hidden) writes to `~/.clanker/agent/clanker-debug.log`:
|
||||
|
||||
- Rendered TUI lines with ANSI codes
|
||||
- Last messages sent to the LLM
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
# JSON Event Stream Mode
|
||||
|
||||
```bash
|
||||
companion --mode json "Your prompt"
|
||||
clanker --mode json "Your prompt"
|
||||
```
|
||||
|
||||
Outputs all session events as JSON lines to stdout. Useful for integrating companion into other tools or custom UIs.
|
||||
Outputs all session events as JSON lines to stdout. Useful for integrating clanker into other tools or custom UIs.
|
||||
|
||||
## Event Types
|
||||
|
||||
Events are defined in [`AgentSessionEvent`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/agent-session.ts#L102):
|
||||
Events are defined in [`AgentSessionEvent`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/agent-session.ts#L102):
|
||||
|
||||
```typescript
|
||||
type AgentSessionEvent =
|
||||
|
|
@ -36,7 +36,7 @@ type AgentSessionEvent =
|
|||
};
|
||||
```
|
||||
|
||||
Base events from [`AgentEvent`](https://github.com/badlogic/companion-mono/blob/main/packages/agent/src/types.ts#L179):
|
||||
Base events from [`AgentEvent`](https://github.com/badlogic/clanker-agent/blob/main/packages/agent/src/types.ts#L179):
|
||||
|
||||
```typescript
|
||||
type AgentEvent =
|
||||
|
|
@ -83,13 +83,13 @@ type AgentEvent =
|
|||
|
||||
## Message Types
|
||||
|
||||
Base messages from [`packages/ai/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/types.ts#L134):
|
||||
Base messages from [`packages/ai/src/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/types.ts#L134):
|
||||
|
||||
- `UserMessage` (line 134)
|
||||
- `AssistantMessage` (line 140)
|
||||
- `ToolResultMessage` (line 152)
|
||||
|
||||
Extended messages from [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/messages.ts#L29):
|
||||
Extended messages from [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/messages.ts#L29):
|
||||
|
||||
- `BashExecutionMessage` (line 29)
|
||||
- `CustomMessage` (line 46)
|
||||
|
|
@ -125,5 +125,5 @@ Followed by events as they occur:
|
|||
## Example
|
||||
|
||||
```bash
|
||||
companion --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'
|
||||
clanker --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Keybindings
|
||||
|
||||
All keyboard shortcuts can be customized via `~/.companion/agent/keybindings.json`. Each action can be bound to one or more keys.
|
||||
All keyboard shortcuts can be customized via `~/.clanker/agent/keybindings.json`. Each action can be bound to one or more keys.
|
||||
|
||||
## Key Format
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, etc.
|
|||
|
||||
## Custom Configuration
|
||||
|
||||
Create `~/.companion/agent/keybindings.json`:
|
||||
Create `~/.clanker/agent/keybindings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Custom Models
|
||||
|
||||
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.companion/agent/models.json`.
|
||||
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.clanker/agent/models.json`.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
> companion can help you create companion packages. Ask it to bundle your extensions, skills, prompt templates, or themes.
|
||||
> clanker can help you create clanker packages. Ask it to bundle your extensions, skills, prompt templates, or themes.
|
||||
|
||||
# Companion Packages
|
||||
# Clanker Packages
|
||||
|
||||
Companion packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under the `companion` key, or use conventional directories.
|
||||
Clanker packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under the `clanker` key, or use conventional directories.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install and Manage](#install-and-manage)
|
||||
- [Package Sources](#package-sources)
|
||||
- [Creating a Companion Package](#creating-a-companion-package)
|
||||
- [Creating a Clanker Package](#creating-a-clanker-package)
|
||||
- [Package Structure](#package-structure)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Package Filtering](#package-filtering)
|
||||
|
|
@ -17,32 +17,32 @@ Companion packages bundle extensions, skills, prompt templates, and themes so yo
|
|||
|
||||
## Install and Manage
|
||||
|
||||
> **Security:** Companion packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||
> **Security:** Clanker packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||
|
||||
```bash
|
||||
companion install npm:@foo/bar@1.0.0
|
||||
companion install git:github.com/user/repo@v1
|
||||
companion install https://github.com/user/repo # raw URLs work too
|
||||
companion install /absolute/path/to/package
|
||||
companion install ./relative/path/to/package
|
||||
clanker install npm:@foo/bar@1.0.0
|
||||
clanker install git:github.com/user/repo@v1
|
||||
clanker install https://github.com/user/repo # raw URLs work too
|
||||
clanker install /absolute/path/to/package
|
||||
clanker install ./relative/path/to/package
|
||||
|
||||
companion remove npm:@foo/bar
|
||||
companion list # show installed packages from settings
|
||||
companion update # update all non-pinned packages
|
||||
clanker remove npm:@foo/bar
|
||||
clanker list # show installed packages from settings
|
||||
clanker update # update all non-pinned packages
|
||||
```
|
||||
|
||||
By default, `install` and `remove` write to global settings (`~/.companion/agent/settings.json`). Use `-l` to write to project settings (`.companion/settings.json`) instead. Project settings can be shared with your team, and companion installs any missing packages automatically on startup.
|
||||
By default, `install` and `remove` write to global settings (`~/.clanker/agent/settings.json`). Use `-l` to write to project settings (`.clanker/settings.json`) instead. Project settings can be shared with your team, and clanker installs any missing packages automatically on startup.
|
||||
|
||||
To try a package without installing it, use `--extension` or `-e`. This installs to a temporary directory for the current run only:
|
||||
|
||||
```bash
|
||||
companion -e npm:@foo/bar
|
||||
companion -e git:github.com/user/repo
|
||||
clanker -e npm:@foo/bar
|
||||
clanker -e git:github.com/user/repo
|
||||
```
|
||||
|
||||
## Package Sources
|
||||
|
||||
Companion accepts three source types in settings and `companion install`.
|
||||
Clanker accepts three source types in settings and `clanker install`.
|
||||
|
||||
### npm
|
||||
|
||||
|
|
@ -51,9 +51,9 @@ npm:@scope/pkg@1.2.3
|
|||
npm:pkg
|
||||
```
|
||||
|
||||
- Versioned specs are pinned and skipped by `companion update`.
|
||||
- Versioned specs are pinned and skipped by `clanker update`.
|
||||
- Global installs use `npm install -g`.
|
||||
- Project installs go under `.companion/npm/`.
|
||||
- Project installs go under `.clanker/npm/`.
|
||||
|
||||
### git
|
||||
|
||||
|
|
@ -69,21 +69,21 @@ ssh://git@github.com/user/repo@v1
|
|||
- HTTPS and SSH URLs are both supported.
|
||||
- SSH URLs use your configured SSH keys automatically (respects `~/.ssh/config`).
|
||||
- For non-interactive runs (for example CI), you can set `GIT_TERMINAL_PROMPT=0` to disable credential prompts and set `GIT_SSH_COMMAND` (for example `ssh -o BatchMode=yes -o ConnectTimeout=5`) to fail fast.
|
||||
- Refs pin the package and skip `companion update`.
|
||||
- Cloned to `~/.companion/agent/git/<host>/<path>` (global) or `.companion/git/<host>/<path>` (project).
|
||||
- Refs pin the package and skip `clanker update`.
|
||||
- Cloned to `~/.clanker/agent/git/<host>/<path>` (global) or `.clanker/git/<host>/<path>` (project).
|
||||
- Runs `npm install` after clone or pull if `package.json` exists.
|
||||
|
||||
**SSH examples:**
|
||||
|
||||
```bash
|
||||
# git@host:path shorthand (requires git: prefix)
|
||||
companion install git:git@github.com:user/repo
|
||||
clanker install git:git@github.com:user/repo
|
||||
|
||||
# ssh:// protocol format
|
||||
companion install ssh://git@github.com/user/repo
|
||||
clanker install ssh://git@github.com/user/repo
|
||||
|
||||
# With version ref
|
||||
companion install git:git@github.com:user/repo@v1.0.0
|
||||
clanker install git:git@github.com:user/repo@v1.0.0
|
||||
```
|
||||
|
||||
### Local Paths
|
||||
|
|
@ -93,17 +93,17 @@ companion install git:git@github.com:user/repo@v1.0.0
|
|||
./relative/path/to/package
|
||||
```
|
||||
|
||||
Local paths point to files or directories on disk and are added to settings without copying. Relative paths are resolved against the settings file they appear in. If the path is a file, it loads as a single extension. If it is a directory, companion loads resources using package rules.
|
||||
Local paths point to files or directories on disk and are added to settings without copying. Relative paths are resolved against the settings file they appear in. If the path is a file, it loads as a single extension. If it is a directory, clanker loads resources using package rules.
|
||||
|
||||
## Creating a Companion Package
|
||||
## Creating a Clanker Package
|
||||
|
||||
Add a `companion` manifest to `package.json` or use conventional directories. Include the `companion-package` keyword for discoverability.
|
||||
Add a `clanker` manifest to `package.json` or use conventional directories. Include the `clanker-package` keyword for discoverability.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-package",
|
||||
"keywords": ["companion-package"],
|
||||
"companion": {
|
||||
"keywords": ["clanker-package"],
|
||||
"clanker": {
|
||||
"extensions": ["./extensions"],
|
||||
"skills": ["./skills"],
|
||||
"prompts": ["./prompts"],
|
||||
|
|
@ -116,13 +116,13 @@ Paths are relative to the package root. Arrays support glob patterns and `!exclu
|
|||
|
||||
### Gallery Metadata
|
||||
|
||||
The [package gallery](https://shittycodingagent.ai/packages) displays packages tagged with `companion-package`. Add `video` or `image` fields to show a preview:
|
||||
The [package gallery](https://clanker.dev/packages) displays packages tagged with `clanker-package`. Add `video` or `image` fields to show a preview:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-package",
|
||||
"keywords": ["companion-package"],
|
||||
"companion": {
|
||||
"keywords": ["clanker-package"],
|
||||
"clanker": {
|
||||
"extensions": ["./extensions"],
|
||||
"video": "https://example.com/demo.mp4",
|
||||
"image": "https://example.com/screenshot.png"
|
||||
|
|
@ -139,7 +139,7 @@ If both are set, video takes precedence.
|
|||
|
||||
### Convention Directories
|
||||
|
||||
If no `companion` manifest is present, companion auto-discovers resources from these directories:
|
||||
If no `clanker` manifest is present, clanker auto-discovers resources from these directories:
|
||||
|
||||
- `extensions/` loads `.ts` and `.js` files
|
||||
- `skills/` recursively finds `SKILL.md` folders and loads top-level `.md` files as skills
|
||||
|
|
@ -148,11 +148,11 @@ If no `companion` manifest is present, companion auto-discovers resources from t
|
|||
|
||||
## Dependencies
|
||||
|
||||
Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When companion installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically.
|
||||
Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When clanker installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically.
|
||||
|
||||
Companion bundles core packages for extensions and skills. If you import any of these, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@mariozechner/companion-ai`, `@mariozechner/companion-agent-core`, `@mariozechner/companion-coding-agent`, `@mariozechner/companion-tui`, `@sinclair/typebox`.
|
||||
Clanker bundles core packages for extensions and skills. If you import any of these, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@mariozechner/clanker-ai`, `@mariozechner/clanker-agent-core`, `@mariozechner/clanker-coding-agent`, `@mariozechner/clanker-tui`, `@sinclair/typebox`.
|
||||
|
||||
Other companion packages must be bundled in your tarball. Add them to `dependencies` and `bundledDependencies`, then reference their resources through `node_modules/` paths. Companion loads packages with separate module roots, so separate installs do not collide or share modules.
|
||||
Other clanker packages must be bundled in your tarball. Add them to `dependencies` and `bundledDependencies`, then reference their resources through `node_modules/` paths. Clanker loads packages with separate module roots, so separate installs do not collide or share modules.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ Example:
|
|||
"shitty-extensions": "^1.0.1"
|
||||
},
|
||||
"bundledDependencies": ["shitty-extensions"],
|
||||
"companion": {
|
||||
"clanker": {
|
||||
"extensions": ["extensions", "node_modules/shitty-extensions/extensions"],
|
||||
"skills": ["skills", "node_modules/shitty-extensions/skills"]
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ Filter what a package loads using the object form in settings:
|
|||
|
||||
## Enable and Disable Resources
|
||||
|
||||
Use `companion config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. Works for both global (`~/.companion/agent`) and project (`.companion/`) scopes.
|
||||
Use `clanker config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. Works for both global (`~/.clanker/agent`) and project (`.clanker/`) scopes.
|
||||
|
||||
## Scope and Deduplication
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
> companion can create prompt templates. Ask it to build one for your workflow.
|
||||
> clanker can create prompt templates. Ask it to build one for your workflow.
|
||||
|
||||
# Prompt Templates
|
||||
|
||||
|
|
@ -6,11 +6,11 @@ Prompt templates are Markdown snippets that expand into full prompts. Type `/nam
|
|||
|
||||
## Locations
|
||||
|
||||
Companion loads prompt templates from:
|
||||
Clanker loads prompt templates from:
|
||||
|
||||
- Global: `~/.companion/agent/prompts/*.md`
|
||||
- Project: `.companion/prompts/*.md`
|
||||
- Packages: `prompts/` directories or `companion.prompts` entries in `package.json`
|
||||
- Global: `~/.clanker/agent/prompts/*.md`
|
||||
- Project: `.clanker/prompts/*.md`
|
||||
- Packages: `prompts/` directories or `clanker.prompts` entries in `package.json`
|
||||
- Settings: `prompts` array with files or directories
|
||||
- CLI: `--prompt-template <path>` (repeatable)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Providers
|
||||
|
||||
Companion supports subscription-based providers via OAuth and API key providers via environment variables or auth file. For each provider, companion knows all available models. The list is updated with every companion release.
|
||||
Clanker supports subscription-based providers via OAuth and API key providers via environment variables or auth file. For each provider, clanker knows all available models. The list is updated with every clanker release.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ Use `/login` in interactive mode, then select a provider:
|
|||
- Google Gemini CLI
|
||||
- Google Antigravity
|
||||
|
||||
Use `/logout` to clear credentials. Tokens are stored in `~/.companion/agent/auth.json` and auto-refresh when expired.
|
||||
Use `/logout` to clear credentials. Tokens are stored in `~/.clanker/agent/auth.json` and auto-refresh when expired.
|
||||
|
||||
### GitHub Copilot
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ Set via environment variable:
|
|||
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY=sk-ant-...
|
||||
companion
|
||||
clanker
|
||||
```
|
||||
|
||||
| Provider | Environment Variable | `auth.json` key |
|
||||
|
|
@ -71,11 +71,11 @@ companion
|
|||
| MiniMax | `MINIMAX_API_KEY` | `minimax` |
|
||||
| MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
|
||||
|
||||
Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/env-api-keys.ts).
|
||||
Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/env-api-keys.ts).
|
||||
|
||||
#### Auth File
|
||||
|
||||
Store credentials in `~/.companion/agent/auth.json`:
|
||||
Store credentials in `~/.clanker/agent/auth.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -144,7 +144,7 @@ export AWS_REGION=us-west-2
|
|||
Also supports ECS task roles (`AWS_CONTAINER_CREDENTIALS_*`) and IRSA (`AWS_WEB_IDENTITY_TOKEN_FILE`).
|
||||
|
||||
```bash
|
||||
companion --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
clanker --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
```
|
||||
|
||||
If you are connecting to a Bedrock API proxy, the following environment variables can be used:
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
RPC mode enables headless operation of the coding agent via a JSON protocol over stdin/stdout. This is useful for embedding the agent in other applications, IDEs, or custom UIs.
|
||||
|
||||
**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@mariozechner/companion-coding-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts).
|
||||
**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@mariozechner/clanker-coding-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts).
|
||||
|
||||
## Starting RPC Mode
|
||||
|
||||
```bash
|
||||
companion --mode rpc [options]
|
||||
clanker --mode rpc [options]
|
||||
```
|
||||
|
||||
Common options:
|
||||
|
|
@ -60,7 +60,7 @@ With images:
|
|||
|
||||
If the agent is streaming and no `streamingBehavior` is specified, the command returns an error.
|
||||
|
||||
**Extension commands**: If the message is an extension command (e.g., `/mycommand`), it executes immediately even during streaming. Extension commands manage their own LLM interaction via `companion.sendMessage()`.
|
||||
**Extension commands**: If the message is an extension command (e.g., `/mycommand`), it executes immediately even during streaming. Extension commands manage their own LLM interaction via `clanker.sendMessage()`.
|
||||
|
||||
**Input expansion**: Skill commands (`/skill:name`) and prompt templates (`/template`) are expanded before sending/queueing.
|
||||
|
||||
|
|
@ -503,7 +503,7 @@ If output was truncated, includes `fullOutputPath`:
|
|||
"exitCode": 0,
|
||||
"cancelled": false,
|
||||
"truncated": true,
|
||||
"fullOutputPath": "/tmp/companion-bash-abc123.log"
|
||||
"fullOutputPath": "/tmp/clanker-bash-abc123.log"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -752,21 +752,21 @@ Response:
|
|||
"name": "session-name",
|
||||
"description": "Set or clear session name",
|
||||
"source": "extension",
|
||||
"path": "/home/user/.companion/agent/extensions/session.ts"
|
||||
"path": "/home/user/.clanker/agent/extensions/session.ts"
|
||||
},
|
||||
{
|
||||
"name": "fix-tests",
|
||||
"description": "Fix failing tests",
|
||||
"source": "prompt",
|
||||
"location": "project",
|
||||
"path": "/home/user/myproject/.companion/agent/prompts/fix-tests.md"
|
||||
"path": "/home/user/myproject/.clanker/agent/prompts/fix-tests.md"
|
||||
},
|
||||
{
|
||||
"name": "skill:brave-search",
|
||||
"description": "Web search via Brave API",
|
||||
"source": "skill",
|
||||
"location": "user",
|
||||
"path": "/home/user/.companion/agent/skills/brave-search/SKILL.md"
|
||||
"path": "/home/user/.clanker/agent/skills/brave-search/SKILL.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -778,12 +778,12 @@ Each command has:
|
|||
- `name`: Command name (invoke with `/name`)
|
||||
- `description`: Human-readable description (optional for extension commands)
|
||||
- `source`: What kind of command:
|
||||
- `"extension"`: Registered via `companion.registerCommand()` in an extension
|
||||
- `"extension"`: Registered via `clanker.registerCommand()` in an extension
|
||||
- `"prompt"`: Loaded from a prompt template `.md` file
|
||||
- `"skill"`: Loaded from a skill directory (name is prefixed with `skill:`)
|
||||
- `location`: Where it was loaded from (optional, not present for extensions):
|
||||
- `"user"`: User-level (`~/.companion/agent/`)
|
||||
- `"project"`: Project-level (`./.companion/agent/`)
|
||||
- `"user"`: User-level (`~/.clanker/agent/`)
|
||||
- `"project"`: Project-level (`./.clanker/agent/`)
|
||||
- `"path"`: Explicit path via CLI or settings
|
||||
- `path`: Absolute file path to the command source (optional)
|
||||
|
||||
|
|
@ -1173,7 +1173,7 @@ Set the terminal window/tab title. Fire-and-forget.
|
|||
"type": "extension_ui_request",
|
||||
"id": "uuid-8",
|
||||
"method": "setTitle",
|
||||
"title": "companion - my project"
|
||||
"title": "clanker - my project"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -1372,7 +1372,7 @@ import subprocess
|
|||
import json
|
||||
|
||||
proc = subprocess.Popen(
|
||||
["companion", "--mode", "rpc", "--no-session"],
|
||||
["clanker", "--mode", "rpc", "--no-session"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True
|
||||
|
|
@ -1411,7 +1411,7 @@ For a complete example of handling the extension UI protocol, see [`examples/rpc
|
|||
const { spawn } = require("child_process");
|
||||
const readline = require("readline");
|
||||
|
||||
const agent = spawn("companion", ["--mode", "rpc", "--no-session"]);
|
||||
const agent = spawn("clanker", ["--mode", "rpc", "--no-session"]);
|
||||
|
||||
readline.createInterface({ input: agent.stdout }).on("line", (line) => {
|
||||
const event = JSON.parse(line);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
> companion can help you use the SDK. Ask it to build an integration for your use case.
|
||||
> clanker can help you use the SDK. Ask it to build an integration for your use case.
|
||||
|
||||
# SDK
|
||||
|
||||
The SDK provides programmatic access to companion's agent capabilities. Use it to embed companion in other applications, build custom interfaces, or integrate with automated workflows.
|
||||
The SDK provides programmatic access to clanker's agent capabilities. Use it to embed clanker in other applications, build custom interfaces, or integrate with automated workflows.
|
||||
|
||||
**Example use cases:**
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ import {
|
|||
createAgentSession,
|
||||
ModelRegistry,
|
||||
SessionManager,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Set up credential storage and model registry
|
||||
const authStorage = AuthStorage.create();
|
||||
|
|
@ -49,7 +49,7 @@ await session.prompt("What files are in the current directory?");
|
|||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @mariozechner/companion-coding-agent
|
||||
npm install @mariozechner/clanker-coding-agent
|
||||
```
|
||||
|
||||
The SDK is included in the main package. No separate installation needed.
|
||||
|
|
@ -63,7 +63,7 @@ The main factory function. Creates an `AgentSession` with configurable options.
|
|||
`createAgentSession()` uses a `ResourceLoader` to supply extensions, skills, prompt templates, themes, and context files. If you do not provide one, it uses `DefaultResourceLoader` with standard discovery.
|
||||
|
||||
```typescript
|
||||
import { createAgentSession } from "@mariozechner/companion-coding-agent";
|
||||
import { createAgentSession } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Minimal: defaults with DefaultResourceLoader
|
||||
const { session } = await createAgentSession();
|
||||
|
|
@ -170,7 +170,7 @@ await session.prompt("After you're done, also check X", {
|
|||
|
||||
**Behavior:**
|
||||
|
||||
- **Extension commands** (e.g., `/mycommand`): Execute immediately, even during streaming. They manage their own LLM interaction via `companion.sendMessage()`.
|
||||
- **Extension commands** (e.g., `/mycommand`): Execute immediately, even during streaming. They manage their own LLM interaction via `clanker.sendMessage()`.
|
||||
- **File-based prompt templates** (from `.md` files): Expanded to their content before sending/queueing.
|
||||
- **During streaming without `streamingBehavior`**: Throws an error. Use `steer()` or `followUp()` directly, or specify the option.
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ Both `steer()` and `followUp()` expand file-based prompt templates but error on
|
|||
|
||||
### Agent and AgentState
|
||||
|
||||
The `Agent` class (from `@mariozechner/companion-agent-core`) handles the core LLM interaction. Access it via `session.agent`.
|
||||
The `Agent` class (from `@mariozechner/clanker-agent-core`) handles the core LLM interaction. Access it via `session.agent`.
|
||||
|
||||
```typescript
|
||||
// Access current state
|
||||
|
|
@ -279,17 +279,17 @@ const { session } = await createAgentSession({
|
|||
cwd: process.cwd(), // default
|
||||
|
||||
// Global config directory
|
||||
agentDir: "~/.companion/agent", // default (expands ~)
|
||||
agentDir: "~/.clanker/agent", // default (expands ~)
|
||||
});
|
||||
```
|
||||
|
||||
`cwd` is used by `DefaultResourceLoader` for:
|
||||
|
||||
- Project extensions (`.companion/extensions/`)
|
||||
- Project extensions (`.clanker/extensions/`)
|
||||
- Project skills:
|
||||
- `.companion/skills/`
|
||||
- `.clanker/skills/`
|
||||
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
||||
- Project prompts (`.companion/prompts/`)
|
||||
- Project prompts (`.clanker/prompts/`)
|
||||
- Context files (`AGENTS.md` walking up from cwd)
|
||||
- Session directory naming
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ const { session } = await createAgentSession({
|
|||
|
||||
- Global extensions (`extensions/`)
|
||||
- Global skills:
|
||||
- `skills/` under `agentDir` (for example `~/.companion/agent/skills/`)
|
||||
- `skills/` under `agentDir` (for example `~/.clanker/agent/skills/`)
|
||||
- `~/.agents/skills/`
|
||||
- Global prompts (`prompts/`)
|
||||
- Global context file (`AGENTS.md`)
|
||||
|
|
@ -311,8 +311,8 @@ When you pass a custom `ResourceLoader`, `cwd` and `agentDir` no longer control
|
|||
### Model
|
||||
|
||||
```typescript
|
||||
import { getModel } from "@mariozechner/companion-ai";
|
||||
import { AuthStorage, ModelRegistry } from "@mariozechner/companion-coding-agent";
|
||||
import { getModel } from "@mariozechner/clanker-ai";
|
||||
import { AuthStorage, ModelRegistry } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const authStorage = AuthStorage.create();
|
||||
const modelRegistry = new ModelRegistry(authStorage);
|
||||
|
|
@ -359,9 +359,9 @@ API key resolution priority (handled by AuthStorage):
|
|||
4. Fallback resolver (for custom provider keys from `models.json`)
|
||||
|
||||
```typescript
|
||||
import { AuthStorage, ModelRegistry } from "@mariozechner/companion-coding-agent";
|
||||
import { AuthStorage, ModelRegistry } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Default: uses ~/.companion/agent/auth.json and ~/.companion/agent/models.json
|
||||
// Default: uses ~/.clanker/agent/auth.json and ~/.clanker/agent/models.json
|
||||
const authStorage = AuthStorage.create();
|
||||
const modelRegistry = new ModelRegistry(authStorage);
|
||||
|
||||
|
|
@ -396,7 +396,7 @@ Use a `ResourceLoader` to override the system prompt:
|
|||
import {
|
||||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
systemPromptOverride: () => "You are a helpful assistant.",
|
||||
|
|
@ -419,7 +419,7 @@ import {
|
|||
grepTool,
|
||||
findTool,
|
||||
lsTool,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Use built-in tool set
|
||||
const { session } = await createAgentSession({
|
||||
|
|
@ -447,7 +447,7 @@ import {
|
|||
createGrepTool,
|
||||
createFindTool,
|
||||
createLsTool,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const cwd = "/path/to/project";
|
||||
|
||||
|
|
@ -466,7 +466,7 @@ const { session } = await createAgentSession({
|
|||
|
||||
**When you don't need factories:**
|
||||
|
||||
- If you omit `tools`, companion automatically creates them with the correct `cwd`
|
||||
- If you omit `tools`, clanker automatically creates them with the correct `cwd`
|
||||
- If you use `process.cwd()` as your `cwd`, the pre-built instances work fine
|
||||
|
||||
**When you must use factories:**
|
||||
|
|
@ -480,7 +480,7 @@ import { Type } from "@sinclair/typebox";
|
|||
import {
|
||||
createAgentSession,
|
||||
type ToolDefinition,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Inline custom tool
|
||||
const myTool: ToolDefinition = {
|
||||
|
|
@ -502,23 +502,23 @@ const { session } = await createAgentSession({
|
|||
});
|
||||
```
|
||||
|
||||
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `companion.registerTool()`.
|
||||
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `clanker.registerTool()`.
|
||||
|
||||
### Extensions
|
||||
|
||||
Extensions are loaded by the `ResourceLoader`. `DefaultResourceLoader` discovers extensions from `~/.companion/agent/extensions/`, `.companion/extensions/`, and settings.json extension sources.
|
||||
Extensions are loaded by the `ResourceLoader`. `DefaultResourceLoader` discovers extensions from `~/.clanker/agent/extensions/`, `.clanker/extensions/`, and settings.json extension sources.
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
additionalExtensionPaths: ["/path/to/my-extension.ts"],
|
||||
extensionFactories: [
|
||||
(companion) => {
|
||||
companion.on("agent_start", () => {
|
||||
(clanker) => {
|
||||
clanker.on("agent_start", () => {
|
||||
console.log("[Inline Extension] Agent starting");
|
||||
});
|
||||
},
|
||||
|
|
@ -531,13 +531,13 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
|||
|
||||
Extensions can register tools, subscribe to events, add commands, and more. See [extensions.md](extensions.md) for the full API.
|
||||
|
||||
**Event Bus:** Extensions can communicate via `companion.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside:
|
||||
**Event Bus:** Extensions can communicate via `clanker.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createEventBus,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const eventBus = createEventBus();
|
||||
const loader = new DefaultResourceLoader({
|
||||
|
|
@ -555,7 +555,7 @@ import {
|
|||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
type Skill,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const customSkill: Skill = {
|
||||
name: "my-skill",
|
||||
|
|
@ -582,7 +582,7 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
|||
import {
|
||||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
agentsFilesOverride: (current) => ({
|
||||
|
|
@ -604,7 +604,7 @@ import {
|
|||
createAgentSession,
|
||||
DefaultResourceLoader,
|
||||
type PromptTemplate,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const customCommand: PromptTemplate = {
|
||||
name: "deploy",
|
||||
|
|
@ -632,7 +632,7 @@ Sessions use a tree structure with `id`/`parentId` linking, enabling in-place br
|
|||
import {
|
||||
createAgentSession,
|
||||
SessionManager,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// In-memory (no persistence)
|
||||
const { session } = await createAgentSession({
|
||||
|
|
@ -707,7 +707,7 @@ import {
|
|||
createAgentSession,
|
||||
SettingsManager,
|
||||
SessionManager,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Default: loads from files (global + project merged)
|
||||
const { session } = await createAgentSession({
|
||||
|
|
@ -743,8 +743,8 @@ const { session } = await createAgentSession({
|
|||
|
||||
Settings load from two locations and merge:
|
||||
|
||||
1. Global: `~/.companion/agent/settings.json`
|
||||
2. Project: `<cwd>/.companion/settings.json`
|
||||
1. Global: `~/.clanker/agent/settings.json`
|
||||
2. Project: `<cwd>/.clanker/settings.json`
|
||||
|
||||
Project overrides global. Nested objects merge keys. Setters modify global settings by default.
|
||||
|
||||
|
|
@ -763,7 +763,7 @@ Use `DefaultResourceLoader` to discover extensions, skills, prompts, themes, and
|
|||
import {
|
||||
DefaultResourceLoader,
|
||||
getAgentDir,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const loader = new DefaultResourceLoader({
|
||||
cwd,
|
||||
|
|
@ -804,7 +804,7 @@ interface LoadExtensionsResult {
|
|||
## Complete Example
|
||||
|
||||
```typescript
|
||||
import { getModel } from "@mariozechner/companion-ai";
|
||||
import { getModel } from "@mariozechner/clanker-ai";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import {
|
||||
AuthStorage,
|
||||
|
|
@ -816,7 +816,7 @@ import {
|
|||
readTool,
|
||||
bashTool,
|
||||
type ToolDefinition,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
// Set up auth storage (custom location)
|
||||
const authStorage = AuthStorage.create("/custom/agent/auth.json");
|
||||
|
|
@ -899,7 +899,7 @@ Full TUI interactive mode with editor, chat history, and all built-in commands:
|
|||
import {
|
||||
createAgentSession,
|
||||
InteractiveMode,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
/* ... */
|
||||
|
|
@ -925,7 +925,7 @@ Single-shot mode: send prompts, output result, exit:
|
|||
import {
|
||||
createAgentSession,
|
||||
runPrintMode,
|
||||
} from "@mariozechner/companion-coding-agent";
|
||||
} from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
/* ... */
|
||||
|
|
@ -944,7 +944,7 @@ await runPrintMode(session, {
|
|||
JSON-RPC mode for subprocess integration:
|
||||
|
||||
```typescript
|
||||
import { createAgentSession, runRpcMode } from "@mariozechner/companion-coding-agent";
|
||||
import { createAgentSession, runRpcMode } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
/* ... */
|
||||
|
|
@ -960,7 +960,7 @@ See [RPC documentation](rpc.md) for the JSON protocol.
|
|||
For subprocess-based integration without building with the SDK, use the CLI directly:
|
||||
|
||||
```bash
|
||||
companion --mode rpc --no-session
|
||||
clanker --mode rpc --no-session
|
||||
```
|
||||
|
||||
See [RPC documentation](rpc.md) for the JSON protocol.
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@ Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with
|
|||
## File Location
|
||||
|
||||
```
|
||||
~/.companion/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
|
||||
~/.clanker/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
|
||||
```
|
||||
|
||||
Where `<path>` is the working directory with `/` replaced by `-`.
|
||||
|
||||
## Deleting Sessions
|
||||
|
||||
Sessions can be removed by deleting their `.jsonl` files under `~/.companion/agent/sessions/`.
|
||||
Sessions can be removed by deleting their `.jsonl` files under `~/.clanker/agent/sessions/`.
|
||||
|
||||
Companion also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, companion uses the `trash` CLI to avoid permanent deletion.
|
||||
Clanker also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, clanker uses the `trash` CLI to avoid permanent deletion.
|
||||
|
||||
## Session Version
|
||||
|
||||
|
|
@ -28,14 +28,14 @@ Existing sessions are automatically migrated to the current version (v3) when lo
|
|||
|
||||
## Source Files
|
||||
|
||||
Source on GitHub ([companion-mono](https://github.com/badlogic/companion-mono)):
|
||||
Source on GitHub ([clanker-agent](https://github.com/badlogic/clanker-agent)):
|
||||
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
|
||||
- [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
|
||||
- [`packages/ai/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
|
||||
- [`packages/agent/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/agent/src/types.ts) - AgentMessage union type
|
||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
|
||||
- [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
|
||||
- [`packages/ai/src/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
|
||||
- [`packages/agent/src/types.ts`](https://github.com/badlogic/clanker-agent/blob/main/packages/agent/src/types.ts) - AgentMessage union type
|
||||
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/companion-coding-agent/dist/` and `node_modules/@mariozechner/companion-ai/dist/`.
|
||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/clanker-coding-agent/dist/` and `node_modules/@mariozechner/clanker-ai/dist/`.
|
||||
|
||||
## Message Types
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ interface ToolCall {
|
|||
}
|
||||
```
|
||||
|
||||
### Base Message Types (from companion-ai)
|
||||
### Base Message Types (from clanker-ai)
|
||||
|
||||
```typescript
|
||||
interface UserMessage {
|
||||
|
|
@ -117,7 +117,7 @@ interface Usage {
|
|||
}
|
||||
```
|
||||
|
||||
### Extended Message Types (from companion-coding-agent)
|
||||
### Extended Message Types (from clanker-coding-agent)
|
||||
|
||||
```typescript
|
||||
interface BashExecutionMessage {
|
||||
|
|
@ -269,7 +269,7 @@ Created when context is compacted. Stores a summary of earlier messages.
|
|||
Optional fields:
|
||||
|
||||
- `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if companion-generated (legacy field name)
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if clanker-generated (legacy field name)
|
||||
|
||||
### BranchSummaryEntry
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ Created when switching branches via `/tree` with an LLM generated summary of the
|
|||
Optional fields:
|
||||
|
||||
- `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if companion-generated (legacy field name)
|
||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if clanker-generated (legacy field name)
|
||||
|
||||
### CustomEntry
|
||||
|
||||
|
|
@ -349,7 +349,7 @@ Set `label` to `undefined` to clear a label.
|
|||
|
||||
### SessionInfoEntry
|
||||
|
||||
Session metadata (e.g., user-defined display name). Set via `/name` command or `companion.setSessionName()` in extensions.
|
||||
Session metadata (e.g., user-defined display name). Set via `/name` command or `clanker.setSessionName()` in extensions.
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# Settings
|
||||
|
||||
Companion uses JSON settings files with project settings overriding global settings.
|
||||
Clanker uses JSON settings files with project settings overriding global settings.
|
||||
|
||||
| Location | Scope |
|
||||
| --------------------------- | --------------------------- |
|
||||
| `~/.companion/agent/settings.json` | Global (all projects) |
|
||||
| `.companion/settings.json` | Project (current directory) |
|
||||
| `~/.clanker/agent/settings.json` | Global (all projects) |
|
||||
| `.clanker/settings.json` | Project (current directory) |
|
||||
|
||||
Edit directly or use `/settings` for common options.
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ When a provider requests a retry delay longer than `maxDelayMs` (e.g., Google's
|
|||
|
||||
These settings define where to load extensions, skills, prompts, and themes from.
|
||||
|
||||
Paths in `~/.companion/agent/settings.json` resolve relative to `~/.companion/agent`. Paths in `.companion/settings.json` resolve relative to `.companion`. Absolute paths and `~` are supported.
|
||||
Paths in `~/.clanker/agent/settings.json` resolve relative to `~/.clanker/agent`. Paths in `.clanker/settings.json` resolve relative to `.clanker`. Absolute paths and `~` are supported.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
| --------------------- | -------- | ------- | ------------------------------------------ |
|
||||
|
|
@ -159,7 +159,7 @@ String form loads all resources from a package:
|
|||
|
||||
```json
|
||||
{
|
||||
"packages": ["companion-skills", "@org/my-extension"]
|
||||
"packages": ["clanker-skills", "@org/my-extension"]
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ Object form filters which resources to load:
|
|||
{
|
||||
"packages": [
|
||||
{
|
||||
"source": "companion-skills",
|
||||
"source": "clanker-skills",
|
||||
"skills": ["brave-search", "transcribe"],
|
||||
"extensions": []
|
||||
}
|
||||
|
|
@ -197,22 +197,22 @@ See [packages.md](packages.md) for package management details.
|
|||
"maxRetries": 3
|
||||
},
|
||||
"enabledModels": ["claude-*", "gpt-4o"],
|
||||
"packages": ["companion-skills"]
|
||||
"packages": ["clanker-skills"]
|
||||
}
|
||||
```
|
||||
|
||||
## Project Overrides
|
||||
|
||||
Project settings (`.companion/settings.json`) override global settings. Nested objects are merged:
|
||||
Project settings (`.clanker/settings.json`) override global settings. Nested objects are merged:
|
||||
|
||||
```json
|
||||
// ~/.companion/agent/settings.json (global)
|
||||
// ~/.clanker/agent/settings.json (global)
|
||||
{
|
||||
"theme": "dark",
|
||||
"compaction": { "enabled": true, "reserveTokens": 16384 }
|
||||
}
|
||||
|
||||
// .companion/settings.json (project)
|
||||
// .clanker/settings.json (project)
|
||||
{
|
||||
"compaction": { "reserveTokens": 8192 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Shell Aliases
|
||||
|
||||
Companion runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
|
||||
Clanker runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
|
||||
|
||||
To enable your shell aliases, add to `~/.companion/agent/settings.json`:
|
||||
To enable your shell aliases, add to `~/.clanker/agent/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
> companion can create skills. Ask it to build one for your use case.
|
||||
> clanker can create skills. Ask it to build one for your use case.
|
||||
|
||||
# Skills
|
||||
|
||||
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
|
||||
|
||||
Companion implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
||||
Clanker implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
|
@ -21,15 +21,15 @@ Companion implements the [Agent Skills standard](https://agentskills.io/specific
|
|||
|
||||
> **Security:** Skills can instruct the model to perform any action and may include executable code the model invokes. Review skill content before use.
|
||||
|
||||
Companion loads skills from:
|
||||
Clanker loads skills from:
|
||||
|
||||
- Global:
|
||||
- `~/.companion/agent/skills/`
|
||||
- `~/.clanker/agent/skills/`
|
||||
- `~/.agents/skills/`
|
||||
- Project:
|
||||
- `.companion/skills/`
|
||||
- `.clanker/skills/`
|
||||
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
||||
- Packages: `skills/` directories or `companion.skills` entries in `package.json`
|
||||
- Packages: `skills/` directories or `clanker.skills` entries in `package.json`
|
||||
- Settings: `skills` array with files or directories
|
||||
- CLI: `--skill <path>` (repeatable, additive even with `--no-skills`)
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ To use skills from Claude Code or OpenAI Codex, add their directories to setting
|
|||
}
|
||||
```
|
||||
|
||||
For project-level Claude Code skills, add to `.companion/settings.json`:
|
||||
For project-level Claude Code skills, add to `.clanker/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -60,7 +60,7 @@ For project-level Claude Code skills, add to `.companion/settings.json`:
|
|||
|
||||
## How Skills Work
|
||||
|
||||
1. At startup, companion scans skill locations and extracts names and descriptions
|
||||
1. At startup, clanker scans skill locations and extracts names and descriptions
|
||||
2. The system prompt includes available skills in XML format per the [specification](https://agentskills.io/integrate-skills)
|
||||
3. When a task matches, the agent uses `read` to load the full SKILL.md (models don't always do this; use prompting or `/skill:name` to force it)
|
||||
4. The agent follows the instructions, using relative paths to reference scripts and assets
|
||||
|
|
@ -174,7 +174,7 @@ description: Helps with PDFs.
|
|||
|
||||
## Validation
|
||||
|
||||
Companion validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
||||
Clanker validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
||||
|
||||
- Name doesn't match parent directory
|
||||
- Name exceeds 64 characters or contains invalid characters
|
||||
|
|
@ -229,4 +229,4 @@ cd /path/to/brave-search && npm install
|
|||
## Skill Repositories
|
||||
|
||||
- [Anthropic Skills](https://github.com/anthropics/skills) - Document processing (docx, pdf, pptx, xlsx), web development
|
||||
- [Companion Skills](https://github.com/badlogic/companion-skills) - Web search, browser automation, Google APIs, transcription
|
||||
- [Clanker Skills](https://github.com/badlogic/clanker-skills) - Web search, browser automation, Google APIs, transcription
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Terminal Setup
|
||||
|
||||
Companion uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
|
||||
Clanker uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
|
||||
|
||||
## Kitty, iTerm2
|
||||
|
||||
|
|
@ -66,6 +66,6 @@ If you already have an `actions` array, add the object to it.
|
|||
|
||||
The built-in terminal has limited escape sequence support. Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal.
|
||||
|
||||
If you want the hardware cursor visible, set `COMPANION_HARDWARE_CURSOR=1` before running companion (disabled by default for compatibility).
|
||||
If you want the hardware cursor visible, set `CLANKER_HARDWARE_CURSOR=1` before running clanker (disabled by default for compatibility).
|
||||
|
||||
Consider using a dedicated terminal emulator for the best experience.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Termux (Android) Setup
|
||||
|
||||
Companion runs on Android via [Termux](https://termux.dev/), a terminal emulator and Linux environment for Android.
|
||||
Clanker runs on Android via [Termux](https://termux.dev/), a terminal emulator and Linux environment for Android.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
@ -16,14 +16,14 @@ pkg update && pkg upgrade
|
|||
# Install dependencies
|
||||
pkg install nodejs termux-api git
|
||||
|
||||
# Install companion
|
||||
npm install -g @mariozechner/companion-coding-agent
|
||||
# Install clanker
|
||||
npm install -g @mariozechner/clanker-coding-agent
|
||||
|
||||
# Create config directory
|
||||
mkdir -p ~/.companion/agent
|
||||
mkdir -p ~/.clanker/agent
|
||||
|
||||
# Run companion
|
||||
companion
|
||||
# Run clanker
|
||||
clanker
|
||||
```
|
||||
|
||||
## Clipboard Support
|
||||
|
|
@ -34,7 +34,7 @@ Image clipboard is not supported on Termux (the `ctrl+v` image paste feature wil
|
|||
|
||||
## Example AGENTS.md for Termux
|
||||
|
||||
Create `~/.companion/agent/AGENTS.md` to help the agent understand the Termux environment:
|
||||
Create `~/.clanker/agent/AGENTS.md` to help the agent understand the Termux environment:
|
||||
|
||||
````markdown
|
||||
# Agent Environment: Termux on Android
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
> companion can create themes. Ask it to build one for your setup.
|
||||
> clanker can create themes. Ask it to build one for your setup.
|
||||
|
||||
# Themes
|
||||
|
||||
|
|
@ -16,12 +16,12 @@ Themes are JSON files that define colors for the TUI.
|
|||
|
||||
## Locations
|
||||
|
||||
Companion loads themes from:
|
||||
Clanker loads themes from:
|
||||
|
||||
- Built-in: `dark`, `light`
|
||||
- Global: `~/.companion/agent/themes/*.json`
|
||||
- Project: `.companion/themes/*.json`
|
||||
- Packages: `themes/` directories or `companion.themes` entries in `package.json`
|
||||
- Global: `~/.clanker/agent/themes/*.json`
|
||||
- Project: `.clanker/themes/*.json`
|
||||
- Packages: `themes/` directories or `clanker.themes` entries in `package.json`
|
||||
- Settings: `themes` array with files or directories
|
||||
- CLI: `--theme <path>` (repeatable)
|
||||
|
||||
|
|
@ -37,22 +37,22 @@ Select a theme via `/settings` or in `settings.json`:
|
|||
}
|
||||
```
|
||||
|
||||
On first run, companion detects your terminal background and defaults to `dark` or `light`.
|
||||
On first run, clanker detects your terminal background and defaults to `dark` or `light`.
|
||||
|
||||
## Creating a Custom Theme
|
||||
|
||||
1. Create a theme file:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.companion/agent/themes
|
||||
vim ~/.companion/agent/themes/my-theme.json
|
||||
mkdir -p ~/.clanker/agent/themes
|
||||
vim ~/.clanker/agent/themes/my-theme.json
|
||||
```
|
||||
|
||||
2. Define the theme with all required colors (see [Color Tokens](#color-tokens)):
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/clanker-agent/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"name": "my-theme",
|
||||
"vars": {
|
||||
"primary": "#00aaff",
|
||||
|
|
@ -116,13 +116,13 @@ vim ~/.companion/agent/themes/my-theme.json
|
|||
|
||||
3. Select the theme via `/settings`.
|
||||
|
||||
**Hot reload:** When you edit the currently active custom theme file, companion reloads it automatically for immediate visual feedback.
|
||||
**Hot reload:** When you edit the currently active custom theme file, clanker reloads it automatically for immediate visual feedback.
|
||||
|
||||
## Theme Format
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/badlogic/clanker-agent/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||
"name": "my-theme",
|
||||
"vars": {
|
||||
"blue": "#0066cc",
|
||||
|
|
@ -268,7 +268,7 @@ Four formats are supported:
|
|||
|
||||
### Terminal Compatibility
|
||||
|
||||
Companion uses 24-bit RGB colors. Most modern terminals support this (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). For older terminals with only 256-color support, companion falls back to the nearest approximation.
|
||||
Clanker uses 24-bit RGB colors. Most modern terminals support this (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). For older terminals with only 256-color support, clanker falls back to the nearest approximation.
|
||||
|
||||
Check truecolor support:
|
||||
|
||||
|
|
|
|||
|
|
@ -209,8 +209,8 @@ interface SessionTreeEvent {
|
|||
### Example: Custom Summarizer
|
||||
|
||||
```typescript
|
||||
export default function (companion: HookAPI) {
|
||||
companion.on("session_before_tree", async (event, ctx) => {
|
||||
export default function (clanker: HookAPI) {
|
||||
clanker.on("session_before_tree", async (event, ctx) => {
|
||||
if (!event.preparation.userWantsSummary) return;
|
||||
if (event.preparation.entriesToSummarize.length === 0) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
> companion can create TUI components. Ask it to build one for your use case.
|
||||
> clanker can create TUI components. Ask it to build one for your use case.
|
||||
|
||||
# TUI Components
|
||||
|
||||
Extensions and custom tools can render custom TUI components for interactive user interfaces. This page covers the component system and available building blocks.
|
||||
|
||||
**Source:** [`@mariozechner/companion-tui`](https://github.com/badlogic/companion-mono/tree/main/packages/tui)
|
||||
**Source:** [`@mariozechner/clanker-tui`](https://github.com/badlogic/clanker-agent/tree/main/packages/tui)
|
||||
|
||||
## Component Interface
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ import {
|
|||
CURSOR_MARKER,
|
||||
type Component,
|
||||
type Focusable,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
class MyInput implements Component, Focusable {
|
||||
focused: boolean = false; // Set by TUI when focus changes
|
||||
|
|
@ -66,7 +66,7 @@ This enables IME candidate windows to appear at the correct position for CJK inp
|
|||
When a container component (dialog, selector, etc.) contains an `Input` or `Editor` child, the container must implement `Focusable` and propagate the focus state to the child. Otherwise, the hardware cursor won't be positioned correctly for IME input.
|
||||
|
||||
```typescript
|
||||
import { Container, type Focusable, Input } from "@mariozechner/companion-tui";
|
||||
import { Container, type Focusable, Input } from "@mariozechner/clanker-tui";
|
||||
|
||||
class SearchDialog extends Container implements Focusable {
|
||||
private searchInput: Input;
|
||||
|
|
@ -96,18 +96,18 @@ Without this propagation, typing with an IME (Chinese, Japanese, Korean, etc.) w
|
|||
**In extensions** via `ctx.ui.custom()`:
|
||||
|
||||
```typescript
|
||||
companion.on("session_start", async (_event, ctx) => {
|
||||
clanker.on("session_start", async (_event, ctx) => {
|
||||
const handle = ctx.ui.custom(myComponent);
|
||||
// handle.requestRender() - trigger re-render
|
||||
// handle.close() - restore normal UI
|
||||
});
|
||||
```
|
||||
|
||||
**In custom tools** via `companion.ui.custom()`:
|
||||
**In custom tools** via `clanker.ui.custom()`:
|
||||
|
||||
```typescript
|
||||
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
||||
const handle = companion.ui.custom(myComponent);
|
||||
const handle = clanker.ui.custom(myComponent);
|
||||
// ...
|
||||
handle.close();
|
||||
}
|
||||
|
|
@ -191,10 +191,10 @@ See [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for compre
|
|||
|
||||
## Built-in Components
|
||||
|
||||
Import from `@mariozechner/companion-tui`:
|
||||
Import from `@mariozechner/clanker-tui`:
|
||||
|
||||
```typescript
|
||||
import { Text, Box, Container, Spacer, Markdown } from "@mariozechner/companion-tui";
|
||||
import { Text, Box, Container, Spacer, Markdown } from "@mariozechner/clanker-tui";
|
||||
```
|
||||
|
||||
### Text
|
||||
|
|
@ -276,7 +276,7 @@ const image = new Image(
|
|||
Use `matchesKey()` for key detection:
|
||||
|
||||
```typescript
|
||||
import { matchesKey, Key } from "@mariozechner/companion-tui";
|
||||
import { matchesKey, Key } from "@mariozechner/clanker-tui";
|
||||
|
||||
handleInput(data: string) {
|
||||
if (matchesKey(data, Key.up)) {
|
||||
|
|
@ -303,7 +303,7 @@ handleInput(data: string) {
|
|||
**Critical:** Each line from `render()` must not exceed the `width` parameter.
|
||||
|
||||
```typescript
|
||||
import { visibleWidth, truncateToWidth } from "@mariozechner/companion-tui";
|
||||
import { visibleWidth, truncateToWidth } from "@mariozechner/clanker-tui";
|
||||
|
||||
render(width: number): string[] {
|
||||
// Truncate long lines
|
||||
|
|
@ -327,7 +327,7 @@ import {
|
|||
Key,
|
||||
truncateToWidth,
|
||||
visibleWidth,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
class MySelector {
|
||||
private items: string[];
|
||||
|
|
@ -382,7 +382,7 @@ class MySelector {
|
|||
Usage in an extension:
|
||||
|
||||
```typescript
|
||||
companion.registerCommand("pick", {
|
||||
clanker.registerCommand("pick", {
|
||||
description: "Pick an item",
|
||||
handler: async (args, ctx) => {
|
||||
const items = ["Option A", "Option B", "Option C"];
|
||||
|
|
@ -444,8 +444,8 @@ renderResult(result, options, theme) {
|
|||
**For Markdown**, use `getMarkdownTheme()`:
|
||||
|
||||
```typescript
|
||||
import { getMarkdownTheme } from "@mariozechner/companion-coding-agent";
|
||||
import { Markdown } from "@mariozechner/companion-tui";
|
||||
import { getMarkdownTheme } from "@mariozechner/clanker-coding-agent";
|
||||
import { Markdown } from "@mariozechner/clanker-tui";
|
||||
|
||||
renderResult(result, options, theme) {
|
||||
const mdTheme = getMarkdownTheme();
|
||||
|
|
@ -464,10 +464,10 @@ interface MyTheme {
|
|||
|
||||
## Debug logging
|
||||
|
||||
Set `COMPANION_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout.
|
||||
Set `CLANKER_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout.
|
||||
|
||||
```bash
|
||||
COMPANION_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts
|
||||
CLANKER_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
|
@ -606,19 +606,19 @@ These patterns cover the most common UI needs in extensions. **Copy these patter
|
|||
|
||||
### Pattern 1: Selection Dialog (SelectList)
|
||||
|
||||
For letting users pick from a list of options. Use `SelectList` from `@mariozechner/companion-tui` with `DynamicBorder` for framing.
|
||||
For letting users pick from a list of options. Use `SelectList` from `@mariozechner/clanker-tui` with `DynamicBorder` for framing.
|
||||
|
||||
```typescript
|
||||
import type { ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||
import { DynamicBorder } from "@mariozechner/companion-coding-agent";
|
||||
import type { ExtensionAPI } from "@mariozechner/clanker-coding-agent";
|
||||
import { DynamicBorder } from "@mariozechner/clanker-coding-agent";
|
||||
import {
|
||||
Container,
|
||||
type SelectItem,
|
||||
SelectList,
|
||||
Text,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
companion.registerCommand("pick", {
|
||||
clanker.registerCommand("pick", {
|
||||
handler: async (_args, ctx) => {
|
||||
const items: SelectItem[] = [
|
||||
{ value: "opt1", label: "Option 1", description: "First option" },
|
||||
|
|
@ -691,9 +691,9 @@ companion.registerCommand("pick", {
|
|||
For operations that take time and should be cancellable. `BorderedLoader` shows a spinner and handles escape to cancel.
|
||||
|
||||
```typescript
|
||||
import { BorderedLoader } from "@mariozechner/companion-coding-agent";
|
||||
import { BorderedLoader } from "@mariozechner/clanker-coding-agent";
|
||||
|
||||
companion.registerCommand("fetch", {
|
||||
clanker.registerCommand("fetch", {
|
||||
handler: async (_args, ctx) => {
|
||||
const result = await ctx.ui.custom<string | null>(
|
||||
(tui, theme, _kb, done) => {
|
||||
|
|
@ -722,18 +722,18 @@ companion.registerCommand("fetch", {
|
|||
|
||||
### Pattern 3: Settings/Toggles (SettingsList)
|
||||
|
||||
For toggling multiple settings. Use `SettingsList` from `@mariozechner/companion-tui` with `getSettingsListTheme()`.
|
||||
For toggling multiple settings. Use `SettingsList` from `@mariozechner/clanker-tui` with `getSettingsListTheme()`.
|
||||
|
||||
```typescript
|
||||
import { getSettingsListTheme } from "@mariozechner/companion-coding-agent";
|
||||
import { getSettingsListTheme } from "@mariozechner/clanker-coding-agent";
|
||||
import {
|
||||
Container,
|
||||
type SettingItem,
|
||||
SettingsList,
|
||||
Text,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
|
||||
companion.registerCommand("settings", {
|
||||
clanker.registerCommand("settings", {
|
||||
handler: async (_args, ctx) => {
|
||||
const items: SettingItem[] = [
|
||||
{
|
||||
|
|
@ -854,8 +854,8 @@ Token stats available via `ctx.sessionManager.getBranch()` and `ctx.model`.
|
|||
Replace the main input editor with a custom implementation. Useful for modal editing (vim), different keybindings (emacs), or specialized input handling.
|
||||
|
||||
```typescript
|
||||
import { CustomEditor, type ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||
import { matchesKey, truncateToWidth } from "@mariozechner/companion-tui";
|
||||
import { CustomEditor, type ExtensionAPI } from "@mariozechner/clanker-coding-agent";
|
||||
import { matchesKey, truncateToWidth } from "@mariozechner/clanker-tui";
|
||||
|
||||
type Mode = "normal" | "insert";
|
||||
|
||||
|
|
@ -917,8 +917,8 @@ class VimEditor extends CustomEditor {
|
|||
}
|
||||
}
|
||||
|
||||
export default function (companion: ExtensionAPI) {
|
||||
companion.on("session_start", (_event, ctx) => {
|
||||
export default function (clanker: ExtensionAPI) {
|
||||
clanker.on("session_start", (_event, ctx) => {
|
||||
// Factory receives theme and keybindings from the app
|
||||
ctx.ui.setEditorComponent(
|
||||
(tui, theme, keybindings) => new VimEditor(theme, keybindings),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Windows Setup
|
||||
|
||||
Companion requires a bash shell on Windows. Checked locations (in order):
|
||||
Clanker requires a bash shell on Windows. Checked locations (in order):
|
||||
|
||||
1. Custom path from `~/.companion/agent/settings.json`
|
||||
1. Custom path from `~/.clanker/agent/settings.json`
|
||||
2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
|
||||
3. `bash.exe` on PATH (Cygwin, MSYS2, WSL)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"name": "@mariozechner/companion-coding-agent",
|
||||
"name": "@harivansh-afk/clanker-coding-agent",
|
||||
"version": "0.56.2",
|
||||
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
||||
"type": "module",
|
||||
"companionConfig": {
|
||||
"name": "companion",
|
||||
"configDir": ".companion"
|
||||
"clankerConfig": {
|
||||
"name": "clanker",
|
||||
"configDir": ".clanker"
|
||||
},
|
||||
"bin": {
|
||||
"companion": "dist/cli.js"
|
||||
"clanker": "dist/cli.js"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
"clean": "shx rm -rf dist",
|
||||
"dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
|
||||
"build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && npm run copy-assets",
|
||||
"build:binary": "npm --prefix ../tui run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/cli.js --outfile dist/companion && npm run copy-binary-assets",
|
||||
"build:binary": "npm --prefix ../tui run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/cli.js --outfile dist/clanker && npm run copy-binary-assets",
|
||||
"copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
|
||||
"copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
|
||||
"test": "vitest --run",
|
||||
|
|
@ -40,9 +40,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@mariozechner/jiti": "^2.6.2",
|
||||
"@mariozechner/companion-agent-core": "^0.56.2",
|
||||
"@mariozechner/companion-ai": "^0.56.2",
|
||||
"@mariozechner/companion-tui": "^0.56.2",
|
||||
"@harivansh-afk/clanker-agent-core": "^0.56.2",
|
||||
"@harivansh-afk/clanker-ai": "^0.56.2",
|
||||
"@harivansh-afk/clanker-tui": "^0.56.2",
|
||||
"@silvia-odwyer/photon-node": "^0.3.4",
|
||||
"chalk": "^5.5.0",
|
||||
"cli-highlight": "^2.1.11",
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/getcompanion-ai/co-mono.git",
|
||||
"url": "git+https://github.com/harivansh-afk/clanker-agent.git",
|
||||
"directory": "packages/coding-agent"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Migrate sessions from ~/.companion/agent/*.jsonl to proper session directories.
|
||||
# Migrate sessions from ~/.clanker/agent/*.jsonl to proper session directories.
|
||||
# This fixes sessions created by the bug in v0.30.0 where sessions were
|
||||
# saved to ~/.companion/agent/ instead of ~/.companion/agent/sessions/<encoded-cwd>/.
|
||||
# saved to ~/.clanker/agent/ instead of ~/.clanker/agent/sessions/<encoded-cwd>/.
|
||||
#
|
||||
# Usage: ./migrate-sessions.sh [--dry-run]
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
AGENT_DIR="${COMPANION_AGENT_DIR:-$HOME/.companion/agent}"
|
||||
AGENT_DIR="${CLANKER_AGENT_DIR:-$HOME/.clanker/agent}"
|
||||
DRY_RUN=false
|
||||
|
||||
if [[ "$1" == "--dry-run" ]]; then
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
*
|
||||
* Test with: npx tsx src/cli-new.ts [args...]
|
||||
*/
|
||||
process.title = "companion";
|
||||
process.title = "clanker";
|
||||
|
||||
import { bedrockProviderModule } from "@mariozechner/companion-ai/bedrock-provider";
|
||||
import { setBedrockProviderModule } from "@mariozechner/companion-ai";
|
||||
import { bedrockProviderModule } from "@mariozechner/clanker-ai/bedrock-provider";
|
||||
import { setBedrockProviderModule } from "@mariozechner/clanker-ai";
|
||||
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
|
||||
import { main } from "./main.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* CLI argument parsing and help display
|
||||
*/
|
||||
|
||||
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
|
||||
import type { ThinkingLevel } from "@mariozechner/clanker-agent-core";
|
||||
import chalk from "chalk";
|
||||
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
|
||||
import {
|
||||
|
|
@ -245,7 +245,7 @@ ${chalk.bold("Options:")}
|
|||
--export <file> Export session file to HTML and exit
|
||||
--list-models [search] List available models (with optional fuzzy search)
|
||||
--verbose Force verbose startup (overrides quietStartup setting)
|
||||
--offline Disable startup network operations (same as COMPANION_OFFLINE=1)
|
||||
--offline Disable startup network operations (same as CLANKER_OFFLINE=1)
|
||||
--help, -h Show this help
|
||||
--version, -v Show version number
|
||||
|
||||
|
|
@ -324,11 +324,11 @@ ${chalk.bold("Environment Variables:")}
|
|||
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
|
||||
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
|
||||
${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
||||
COMPANION_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
||||
COMPANION_AGENT_COMPUTER_COMMAND - Override the computer helper command (default: agent-computer)
|
||||
COMPANION_OFFLINE - Disable startup network operations when set to 1/true/yes
|
||||
COMPANION_SHARE_VIEWER_URL - Base URL for /share command (default: https://companion.dev/session/)
|
||||
COMPANION_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)
|
||||
CLANKER_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
||||
CLANKER_AGENT_COMPUTER_COMMAND - Override the computer helper command (default: agent-computer)
|
||||
CLANKER_OFFLINE - Disable startup network operations when set to 1/true/yes
|
||||
CLANKER_SHARE_VIEWER_URL - Base URL for /share command (default: https://clanker.dev/session/)
|
||||
CLANKER_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)
|
||||
|
||||
${chalk.bold(`Available Tools (default: ${defaultToolsText}):`)}
|
||||
read - Read file contents
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* TUI config selector for `companion config` command
|
||||
* TUI config selector for `clanker config` command
|
||||
*/
|
||||
|
||||
import { ProcessTerminal, TUI } from "@mariozechner/companion-tui";
|
||||
import { ProcessTerminal, TUI } from "@mariozechner/clanker-tui";
|
||||
import type { ResolvedPaths } from "../core/package-manager.js";
|
||||
import type { SettingsManager } from "../core/settings-manager.js";
|
||||
import { ConfigSelectorComponent } from "../modes/interactive/components/config-selector.js";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
import { access, readFile, stat } from "node:fs/promises";
|
||||
import type { ImageContent } from "@mariozechner/companion-ai";
|
||||
import type { ImageContent } from "@mariozechner/clanker-ai";
|
||||
import chalk from "chalk";
|
||||
import { resolve } from "path";
|
||||
import { resolveReadPath } from "../core/tools/path-utils.js";
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
* List available models with optional fuzzy search
|
||||
*/
|
||||
|
||||
import type { Api, Model } from "@mariozechner/companion-ai";
|
||||
import { fuzzyFilter } from "@mariozechner/companion-tui";
|
||||
import type { Api, Model } from "@mariozechner/clanker-ai";
|
||||
import { fuzzyFilter } from "@mariozechner/clanker-tui";
|
||||
import type { ModelRegistry } from "../core/model-registry.js";
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* TUI session selector for --resume flag
|
||||
*/
|
||||
|
||||
import { ProcessTerminal, TUI } from "@mariozechner/companion-tui";
|
||||
import { ProcessTerminal, TUI } from "@mariozechner/clanker-tui";
|
||||
import { KeybindingsManager } from "../core/keybindings.js";
|
||||
import type {
|
||||
SessionInfo,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export function getUpdateInstruction(packageName: string): string {
|
|||
const method = detectInstallMethod();
|
||||
switch (method) {
|
||||
case "bun-binary":
|
||||
return `Download from: https://github.com/badlogic/companion-mono/releases/latest`;
|
||||
return `Download from: https://github.com/badlogic/clanker-mono/releases/latest`;
|
||||
case "pnpm":
|
||||
return `Run: pnpm install -g ${packageName}`;
|
||||
case "yarn":
|
||||
|
|
@ -99,7 +99,7 @@ export function getUpdateInstruction(packageName: string): string {
|
|||
*/
|
||||
export function getPackageDir(): string {
|
||||
// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)
|
||||
const envDir = process.env.COMPANION_PACKAGE_DIR;
|
||||
const envDir = process.env.CLANKER_PACKAGE_DIR;
|
||||
if (envDir) {
|
||||
if (envDir === "~") return homedir();
|
||||
if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
|
||||
|
|
@ -174,32 +174,32 @@ export function getChangelogPath(): string {
|
|||
}
|
||||
|
||||
// =============================================================================
|
||||
// App Config (from package.json companionConfig)
|
||||
// App Config (from package.json clankerConfig)
|
||||
// =============================================================================
|
||||
|
||||
const pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
|
||||
|
||||
export const APP_NAME: string = pkg.companionConfig?.name || "companion";
|
||||
export const APP_NAME: string = pkg.clankerConfig?.name || "clanker";
|
||||
export const CONFIG_DIR_NAME: string =
|
||||
pkg.companionConfig?.configDir || ".companion";
|
||||
pkg.clankerConfig?.configDir || ".clanker";
|
||||
export const VERSION: string = pkg.version;
|
||||
|
||||
// e.g., COMPANION_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR
|
||||
// e.g., CLANKER_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR
|
||||
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
|
||||
|
||||
const DEFAULT_SHARE_VIEWER_URL = "https://companion.dev/session/";
|
||||
const DEFAULT_SHARE_VIEWER_URL = "https://clanker.dev/session/";
|
||||
|
||||
/** Get the share viewer URL for a gist ID */
|
||||
export function getShareViewerUrl(gistId: string): string {
|
||||
const baseUrl = process.env.COMPANION_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;
|
||||
const baseUrl = process.env.CLANKER_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;
|
||||
return `${baseUrl}#${gistId}`;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// User Config Paths (~/.companion/agent/*)
|
||||
// User Config Paths (~/.clanker/agent/*)
|
||||
// =============================================================================
|
||||
|
||||
/** Get the agent config directory (e.g., ~/.companion/agent/) */
|
||||
/** Get the agent config directory (e.g., ~/.clanker/agent/) */
|
||||
export function getAgentDir(): string {
|
||||
const envDir = process.env[ENV_AGENT_DIR];
|
||||
if (envDir) {
|
||||
|
|
|
|||
|
|
@ -22,20 +22,20 @@ import type {
|
|||
AgentState,
|
||||
AgentTool,
|
||||
ThinkingLevel,
|
||||
} from "@mariozechner/companion-agent-core";
|
||||
} from "@mariozechner/clanker-agent-core";
|
||||
import type {
|
||||
AssistantMessage,
|
||||
ImageContent,
|
||||
Message,
|
||||
Model,
|
||||
TextContent,
|
||||
} from "@mariozechner/companion-ai";
|
||||
} from "@mariozechner/clanker-ai";
|
||||
import {
|
||||
isContextOverflow,
|
||||
modelsAreEqual,
|
||||
resetApiProviders,
|
||||
supportsXhigh,
|
||||
} from "@mariozechner/companion-ai";
|
||||
} from "@mariozechner/clanker-ai";
|
||||
import { getDocsPath } from "../config.js";
|
||||
import { theme } from "../modes/interactive/theme/theme.js";
|
||||
import { stripFrontmatter } from "../utils/frontmatter.js";
|
||||
|
|
@ -1023,7 +1023,7 @@ export class AgentSession {
|
|||
|
||||
/**
|
||||
* Send a prompt to the agent.
|
||||
* - Handles extension commands (registered via companion.registerCommand) immediately, even during streaming
|
||||
* - Handles extension commands (registered via clanker.registerCommand) immediately, even during streaming
|
||||
* - Expands file-based prompt templates by default
|
||||
* - During streaming, queues via steer() or followUp() based on streamingBehavior option
|
||||
* - Validates model and API key before sending (when not streaming)
|
||||
|
|
@ -1034,7 +1034,7 @@ export class AgentSession {
|
|||
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
||||
|
||||
// Handle extension commands first (execute immediately, even during streaming)
|
||||
// Extension commands manage their own LLM interaction via companion.sendMessage()
|
||||
// Extension commands manage their own LLM interaction via clanker.sendMessage()
|
||||
if (expandPromptTemplates && text.startsWith("/")) {
|
||||
const handled = await this._tryExecuteExtensionCommand(text);
|
||||
if (handled) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Credential storage for API keys and OAuth tokens.
|
||||
* Handles loading, saving, and refreshing credentials from auth.json.
|
||||
*
|
||||
* Uses file locking to prevent race conditions when multiple companion instances
|
||||
* Uses file locking to prevent race conditions when multiple clanker instances
|
||||
* try to refresh tokens simultaneously.
|
||||
*/
|
||||
|
||||
|
|
@ -11,12 +11,12 @@ import {
|
|||
type OAuthCredentials,
|
||||
type OAuthLoginCallbacks,
|
||||
type OAuthProviderId,
|
||||
} from "@mariozechner/companion-ai";
|
||||
} from "@mariozechner/clanker-ai";
|
||||
import {
|
||||
getOAuthApiKey,
|
||||
getOAuthProvider,
|
||||
getOAuthProviders,
|
||||
} from "@mariozechner/companion-ai/oauth";
|
||||
} from "@mariozechner/clanker-ai/oauth";
|
||||
import {
|
||||
chmodSync,
|
||||
existsSync,
|
||||
|
|
@ -373,7 +373,7 @@ export class AuthStorage {
|
|||
|
||||
/**
|
||||
* Refresh OAuth token with backend locking to prevent race conditions.
|
||||
* Multiple companion instances may try to refresh simultaneously when tokens expire.
|
||||
* Multiple clanker instances may try to refresh simultaneously when tokens expire.
|
||||
*/
|
||||
private async refreshOAuthTokenWithLock(
|
||||
providerId: OAuthProviderId,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ export function executeBash(
|
|||
// Start writing to temp file if exceeds threshold
|
||||
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
|
||||
const id = randomBytes(8).toString("hex");
|
||||
tempFilePath = join(tmpdir(), `companion-bash-${id}.log`);
|
||||
tempFilePath = join(tmpdir(), `clanker-bash-${id}.log`);
|
||||
tempFileStream = createWriteStream(tempFilePath);
|
||||
// Write already-buffered chunks to temp file
|
||||
for (const chunk of outputChunks) {
|
||||
|
|
@ -223,7 +223,7 @@ export async function executeBashWithOperations(
|
|||
// Start writing to temp file if exceeds threshold
|
||||
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
|
||||
const id = randomBytes(8).toString("hex");
|
||||
tempFilePath = join(tmpdir(), `companion-bash-${id}.log`);
|
||||
tempFilePath = join(tmpdir(), `clanker-bash-${id}.log`);
|
||||
tempFileStream = createWriteStream(tempFilePath);
|
||||
for (const chunk of outputChunks) {
|
||||
tempFileStream.write(chunk);
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
* a summary of the branch being left so context isn't lost.
|
||||
*/
|
||||
|
||||
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||
import type { Model } from "@mariozechner/companion-ai";
|
||||
import { completeSimple } from "@mariozechner/companion-ai";
|
||||
import type { AgentMessage } from "@mariozechner/clanker-agent-core";
|
||||
import type { Model } from "@mariozechner/clanker-ai";
|
||||
import { completeSimple } from "@mariozechner/clanker-ai";
|
||||
import {
|
||||
convertToLlm,
|
||||
createBranchSummaryMessage,
|
||||
|
|
@ -206,7 +206,7 @@ export function prepareBranchEntries(
|
|||
|
||||
// First pass: collect file ops from ALL entries (even if they don't fit in token budget)
|
||||
// This ensures we capture cumulative file tracking from nested branch summaries
|
||||
// Only extract from companion-generated summaries (fromHook !== true), not extension-generated ones
|
||||
// Only extract from clanker-generated summaries (fromHook !== true), not extension-generated ones
|
||||
for (const entry of entries) {
|
||||
if (entry.type === "branch_summary" && !entry.fromHook && entry.details) {
|
||||
const details = entry.details as BranchSummaryDetails;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
* and after compaction the session is reloaded.
|
||||
*/
|
||||
|
||||
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||
import type { AssistantMessage, Model, Usage } from "@mariozechner/companion-ai";
|
||||
import { completeSimple } from "@mariozechner/companion-ai";
|
||||
import type { AgentMessage } from "@mariozechner/clanker-agent-core";
|
||||
import type { AssistantMessage, Model, Usage } from "@mariozechner/clanker-ai";
|
||||
import { completeSimple } from "@mariozechner/clanker-ai";
|
||||
import {
|
||||
convertToLlm,
|
||||
createBranchSummaryMessage,
|
||||
|
|
@ -45,7 +45,7 @@ function extractFileOperations(
|
|||
): FileOperations {
|
||||
const fileOps = createFileOps();
|
||||
|
||||
// Collect from previous compaction's details (if companion-generated)
|
||||
// Collect from previous compaction's details (if clanker-generated)
|
||||
if (prevCompactionIndex >= 0) {
|
||||
const prevCompaction = entries[prevCompactionIndex] as CompactionEntry;
|
||||
if (!prevCompaction.fromHook && prevCompaction.details) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
* Shared utilities for compaction and branch summarization.
|
||||
*/
|
||||
|
||||
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||
import type { Message } from "@mariozechner/companion-ai";
|
||||
import type { AgentMessage } from "@mariozechner/clanker-agent-core";
|
||||
import type { Message } from "@mariozechner/clanker-ai";
|
||||
|
||||
// ============================================================================
|
||||
// File Operation Tracking
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
|
||||
import type { ThinkingLevel } from "@mariozechner/clanker-agent-core";
|
||||
|
||||
export const DEFAULT_THINKING_LEVEL: ThinkingLevel = "medium";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { AgentState } from "@mariozechner/companion-agent-core";
|
||||
import type { AgentState } from "@mariozechner/clanker-agent-core";
|
||||
import { existsSync, readFileSync, writeFileSync } from "fs";
|
||||
import { basename, join } from "path";
|
||||
import { APP_NAME, getExportTemplateDir } from "../../config.js";
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
// Parse URL parameters for deep linking: leafId and targetId
|
||||
// Check for injected params (when loaded in iframe via srcdoc) or use window.location
|
||||
const injectedParams = document.querySelector('meta[name="companion-url-params"]');
|
||||
const injectedParams = document.querySelector('meta[name="clanker-url-params"]');
|
||||
const searchString = injectedParams
|
||||
? injectedParams.content
|
||||
: window.location.search.substring(1);
|
||||
|
|
@ -1227,7 +1227,7 @@
|
|||
function buildShareUrl(entryId) {
|
||||
// Check for injected base URL (used when loaded in iframe via srcdoc)
|
||||
const baseUrlMeta = document.querySelector(
|
||||
'meta[name="companion-share-base-url"]',
|
||||
'meta[name="clanker-share-base-url"]',
|
||||
);
|
||||
const baseUrl = baseUrlMeta
|
||||
? baseUrlMeta.content
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* and converting the ANSI output to HTML.
|
||||
*/
|
||||
|
||||
import type { ImageContent, TextContent } from "@mariozechner/companion-ai";
|
||||
import type { ImageContent, TextContent } from "@mariozechner/clanker-ai";
|
||||
import type { Theme } from "../../modes/interactive/theme/theme.js";
|
||||
import type { ToolDefinition } from "../extensions/types.js";
|
||||
import { ansiLinesToHtml } from "./ansi-to-html.js";
|
||||
|
|
|
|||
|
|
@ -10,18 +10,18 @@ import * as os from "node:os";
|
|||
import * as path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createJiti } from "@mariozechner/jiti";
|
||||
import * as _bundledPiAgentCore from "@mariozechner/companion-agent-core";
|
||||
import * as _bundledPiAi from "@mariozechner/companion-ai";
|
||||
import * as _bundledPiAiOauth from "@mariozechner/companion-ai/oauth";
|
||||
import type { KeyId } from "@mariozechner/companion-tui";
|
||||
import * as _bundledPiTui from "@mariozechner/companion-tui";
|
||||
import * as _bundledPiAgentCore from "@mariozechner/clanker-agent-core";
|
||||
import * as _bundledPiAi from "@mariozechner/clanker-ai";
|
||||
import * as _bundledPiAiOauth from "@mariozechner/clanker-ai/oauth";
|
||||
import type { KeyId } from "@mariozechner/clanker-tui";
|
||||
import * as _bundledPiTui from "@mariozechner/clanker-tui";
|
||||
// Static imports of packages that extensions may use.
|
||||
// These MUST be static so Bun bundles them into the compiled binary.
|
||||
// The virtualModules option then makes them available to extensions.
|
||||
import * as _bundledTypebox from "@sinclair/typebox";
|
||||
import { getAgentDir, isBunBinary } from "../../config.js";
|
||||
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
||||
// avoiding a circular dependency. Extensions can import from @mariozechner/companion-coding-agent.
|
||||
// avoiding a circular dependency. Extensions can import from @mariozechner/clanker-coding-agent.
|
||||
import * as _bundledPiCodingAgent from "../../index.js";
|
||||
import { createEventBus, type EventBus } from "../event-bus.js";
|
||||
import type { ExecOptions } from "../exec.js";
|
||||
|
|
@ -41,11 +41,11 @@ import type {
|
|||
/** Modules available to extensions via virtualModules (for compiled Bun binary) */
|
||||
const VIRTUAL_MODULES: Record<string, unknown> = {
|
||||
"@sinclair/typebox": _bundledTypebox,
|
||||
"@mariozechner/companion-agent-core": _bundledPiAgentCore,
|
||||
"@mariozechner/companion-tui": _bundledPiTui,
|
||||
"@mariozechner/companion-ai": _bundledPiAi,
|
||||
"@mariozechner/companion-ai/oauth": _bundledPiAiOauth,
|
||||
"@mariozechner/companion-coding-agent": _bundledPiCodingAgent,
|
||||
"@mariozechner/clanker-agent-core": _bundledPiAgentCore,
|
||||
"@mariozechner/clanker-tui": _bundledPiTui,
|
||||
"@mariozechner/clanker-ai": _bundledPiAi,
|
||||
"@mariozechner/clanker-ai/oauth": _bundledPiAiOauth,
|
||||
"@mariozechner/clanker-coding-agent": _bundledPiCodingAgent,
|
||||
};
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
|
@ -80,22 +80,22 @@ function getAliases(): Record<string, string> {
|
|||
};
|
||||
|
||||
_aliases = {
|
||||
"@mariozechner/companion-coding-agent": packageIndex,
|
||||
"@mariozechner/companion-agent-core": resolveWorkspaceOrImport(
|
||||
"@mariozechner/clanker-coding-agent": packageIndex,
|
||||
"@mariozechner/clanker-agent-core": resolveWorkspaceOrImport(
|
||||
"agent/dist/index.js",
|
||||
"@mariozechner/companion-agent-core",
|
||||
"@mariozechner/clanker-agent-core",
|
||||
),
|
||||
"@mariozechner/companion-tui": resolveWorkspaceOrImport(
|
||||
"@mariozechner/clanker-tui": resolveWorkspaceOrImport(
|
||||
"tui/dist/index.js",
|
||||
"@mariozechner/companion-tui",
|
||||
"@mariozechner/clanker-tui",
|
||||
),
|
||||
"@mariozechner/companion-ai": resolveWorkspaceOrImport(
|
||||
"@mariozechner/clanker-ai": resolveWorkspaceOrImport(
|
||||
"ai/dist/index.js",
|
||||
"@mariozechner/companion-ai",
|
||||
"@mariozechner/clanker-ai",
|
||||
),
|
||||
"@mariozechner/companion-ai/oauth": resolveWorkspaceOrImport(
|
||||
"@mariozechner/clanker-ai/oauth": resolveWorkspaceOrImport(
|
||||
"ai/dist/oauth.js",
|
||||
"@mariozechner/companion-ai/oauth",
|
||||
"@mariozechner/clanker-ai/oauth",
|
||||
),
|
||||
"@sinclair/typebox": typeboxRoot,
|
||||
};
|
||||
|
|
@ -454,8 +454,8 @@ function readPiManifest(packageJsonPath: string): PiManifest | null {
|
|||
try {
|
||||
const content = fs.readFileSync(packageJsonPath, "utf-8");
|
||||
const pkg = JSON.parse(content);
|
||||
if (pkg.companion && typeof pkg.companion === "object") {
|
||||
return pkg.companion as PiManifest;
|
||||
if (pkg.clanker && typeof pkg.clanker === "object") {
|
||||
return pkg.clanker as PiManifest;
|
||||
}
|
||||
return null;
|
||||
} catch {
|
||||
|
|
@ -471,13 +471,13 @@ function isExtensionFile(name: string): boolean {
|
|||
* Resolve extension entry points from a directory.
|
||||
*
|
||||
* Checks for:
|
||||
* 1. package.json with "companion.extensions" field -> returns declared paths
|
||||
* 1. package.json with "clanker.extensions" field -> returns declared paths
|
||||
* 2. index.ts or index.js -> returns the index file
|
||||
*
|
||||
* Returns resolved paths or null if no entry points found.
|
||||
*/
|
||||
function resolveExtensionEntries(dir: string): string[] | null {
|
||||
// Check for package.json with "companion" field first
|
||||
// Check for package.json with "clanker" field first
|
||||
const packageJsonPath = path.join(dir, "package.json");
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
const manifest = readPiManifest(packageJsonPath);
|
||||
|
|
@ -514,7 +514,7 @@ function resolveExtensionEntries(dir: string): string[] | null {
|
|||
* Discovery rules:
|
||||
* 1. Direct files: `extensions/*.ts` or `*.js` → load
|
||||
* 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load
|
||||
* 3. Subdirectory with package.json: `extensions/* /package.json` with "companion" field → load what it declares
|
||||
* 3. Subdirectory with package.json: `extensions/* /package.json` with "clanker" field → load what it declares
|
||||
*
|
||||
* No recursion beyond one level. Complex packages must use package.json manifest.
|
||||
*/
|
||||
|
|
@ -577,8 +577,8 @@ export async function discoverAndLoadExtensions(
|
|||
}
|
||||
};
|
||||
|
||||
// 1. Project-local extensions: cwd/.companion/extensions/
|
||||
const localExtDir = path.join(cwd, ".companion", "extensions");
|
||||
// 1. Project-local extensions: cwd/.clanker/extensions/
|
||||
const localExtDir = path.join(cwd, ".clanker", "extensions");
|
||||
addPaths(discoverExtensionsInDir(localExtDir));
|
||||
|
||||
// 2. Global extensions: agentDir/extensions/
|
||||
|
|
@ -589,7 +589,7 @@ export async function discoverAndLoadExtensions(
|
|||
for (const p of configuredPaths) {
|
||||
const resolved = resolvePath(p, cwd);
|
||||
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
|
||||
// Check for package.json with companion manifest or index.ts
|
||||
// Check for package.json with clanker manifest or index.ts
|
||||
const entries = resolveExtensionEntries(resolved);
|
||||
if (entries) {
|
||||
addPaths(entries);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
* Extension runner - executes extensions and manages their lifecycle.
|
||||
*/
|
||||
|
||||
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||
import type { ImageContent, Model } from "@mariozechner/companion-ai";
|
||||
import type { KeyId } from "@mariozechner/companion-tui";
|
||||
import type { AgentMessage } from "@mariozechner/clanker-agent-core";
|
||||
import type { ImageContent, Model } from "@mariozechner/clanker-ai";
|
||||
import type { KeyId } from "@mariozechner/clanker-tui";
|
||||
import { type Theme, theme } from "../../modes/interactive/theme/theme.js";
|
||||
import type { ResourceDiagnostic } from "../diagnostics.js";
|
||||
import type { KeyAction, KeybindingsConfig } from "../keybindings.js";
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import type {
|
|||
AgentToolResult,
|
||||
AgentToolUpdateCallback,
|
||||
ThinkingLevel,
|
||||
} from "@mariozechner/companion-agent-core";
|
||||
} from "@mariozechner/clanker-agent-core";
|
||||
import type {
|
||||
Api,
|
||||
AssistantMessageEvent,
|
||||
|
|
@ -26,7 +26,7 @@ import type {
|
|||
SimpleStreamOptions,
|
||||
TextContent,
|
||||
ToolResultMessage,
|
||||
} from "@mariozechner/companion-ai";
|
||||
} from "@mariozechner/clanker-ai";
|
||||
import type {
|
||||
AutocompleteItem,
|
||||
Component,
|
||||
|
|
@ -36,7 +36,7 @@ import type {
|
|||
OverlayHandle,
|
||||
OverlayOptions,
|
||||
TUI,
|
||||
} from "@mariozechner/companion-tui";
|
||||
} from "@mariozechner/clanker-tui";
|
||||
import type { Static, TSchema } from "@sinclair/typebox";
|
||||
import type { Theme } from "../../modes/interactive/theme/theme.js";
|
||||
import type { BashResult } from "../bash-executor.js";
|
||||
|
|
@ -223,12 +223,12 @@ export interface ExtensionUIContext {
|
|||
* - `keybindings`: KeybindingsManager for app-level keybindings
|
||||
*
|
||||
* For full app keybinding support (escape, ctrl+d, model switching, etc.),
|
||||
* extend `CustomEditor` from `@mariozechner/companion-coding-agent` and call
|
||||
* extend `CustomEditor` from `@mariozechner/clanker-coding-agent` and call
|
||||
* `super.handleInput(data)` for keys you don't handle.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { CustomEditor } from "@mariozechner/companion-coding-agent";
|
||||
* import { CustomEditor } from "@mariozechner/clanker-coding-agent";
|
||||
*
|
||||
* class VimEditor extends CustomEditor {
|
||||
* private mode: "normal" | "insert" = "insert";
|
||||
|
|
@ -316,7 +316,7 @@ export interface ExtensionContext {
|
|||
abort(): void;
|
||||
/** Whether there are queued messages waiting */
|
||||
hasPendingMessages(): boolean;
|
||||
/** Gracefully shutdown companion and exit. Available in all contexts. */
|
||||
/** Gracefully shutdown clanker and exit. Available in all contexts. */
|
||||
shutdown(): void;
|
||||
/** Get current context usage for the active model. */
|
||||
getContextUsage(): ContextUsage | undefined;
|
||||
|
|
@ -1251,7 +1251,7 @@ export interface ExtensionAPI {
|
|||
*
|
||||
* @example
|
||||
* // Register a new provider with custom models
|
||||
* companion.registerProvider("my-proxy", {
|
||||
* clanker.registerProvider("my-proxy", {
|
||||
* baseUrl: "https://proxy.example.com",
|
||||
* apiKey: "PROXY_API_KEY",
|
||||
* api: "anthropic-messages",
|
||||
|
|
@ -1270,13 +1270,13 @@ export interface ExtensionAPI {
|
|||
*
|
||||
* @example
|
||||
* // Override baseUrl for an existing provider
|
||||
* companion.registerProvider("anthropic", {
|
||||
* clanker.registerProvider("anthropic", {
|
||||
* baseUrl: "https://proxy.example.com"
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // Register provider with OAuth support
|
||||
* companion.registerProvider("corporate-ai", {
|
||||
* clanker.registerProvider("corporate-ai", {
|
||||
* baseUrl: "https://ai.corp.com",
|
||||
* api: "openai-responses",
|
||||
* models: [...],
|
||||
|
|
@ -1301,7 +1301,7 @@ export interface ExtensionAPI {
|
|||
* the initial load phase.
|
||||
*
|
||||
* @example
|
||||
* companion.unregisterProvider("my-proxy");
|
||||
* clanker.unregisterProvider("my-proxy");
|
||||
*/
|
||||
unregisterProvider(name: string): void;
|
||||
|
||||
|
|
@ -1313,7 +1313,7 @@ export interface ExtensionAPI {
|
|||
// Provider Registration Types
|
||||
// ============================================================================
|
||||
|
||||
/** Configuration for registering a provider via companion.registerProvider(). */
|
||||
/** Configuration for registering a provider via clanker.registerProvider(). */
|
||||
export interface ProviderConfig {
|
||||
/** Base URL for the API endpoint. Required when defining models. */
|
||||
baseUrl?: string;
|
||||
|
|
@ -1381,7 +1381,7 @@ export interface ProviderModelConfig {
|
|||
}
|
||||
|
||||
/** Extension factory function type. Supports both sync and async initialization. */
|
||||
export type ExtensionFactory = (companion: ExtensionAPI) => void | Promise<void>;
|
||||
export type ExtensionFactory = (clanker: ExtensionAPI) => void | Promise<void>;
|
||||
|
||||
// ============================================================================
|
||||
// Loaded Extension Types
|
||||
|
|
@ -1480,7 +1480,7 @@ export interface ExtensionRuntimeState {
|
|||
}
|
||||
|
||||
/**
|
||||
* Action implementations for companion.* API methods.
|
||||
* Action implementations for clanker.* API methods.
|
||||
* Provided to runner.initialize(), copied into the shared runtime.
|
||||
*/
|
||||
export interface ExtensionActions {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
import type {
|
||||
AgentTool,
|
||||
AgentToolUpdateCallback,
|
||||
} from "@mariozechner/companion-agent-core";
|
||||
} from "@mariozechner/clanker-agent-core";
|
||||
import type { ExtensionRunner } from "./runner.js";
|
||||
import type { RegisteredTool, ToolCallEventResult } from "./types.js";
|
||||
|
||||
|
|
|
|||