An LLM programming assistant engine built with Go, supporting WebSocket, multi-turn dialogues, tool calling, permission control, and skill extension.
272
stars
632
commits
Go
primary language
Aug 30, 2026
updated
An LLM programming assistant engine built with Go. It provides capabilities via the WebSocket protocol, supporting multi-turn dialogues, tool calling, permission control, and skill extension.
┌───────────-──┐ ┌─────────────┐ ┌─────────────┐
│ WebSocket │ │ HTTP │ │ Feishu │
│ Channel │ │ Channel │ │ Channel │
└──────┬───────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└──────────────────┼──────────────────┘
▼
┌──────────────────┐
│Router + Middleware│ Auth / RateLimit / Logging
└────────┬─────────┘
▼
┌──────────────────┐
│ Query Engine │ 5-Phase Loop
│ (queryloop.go) │ Preprocessing → LLM Streaming → Error Recovery
└───┬──────────┬───┘ → Tool Execution → Continuation Check
│ │
┌─────▼──-─┐ ┌──▼──────────┐
│ Provider │ │ Tool System │
│ (LLM) │ │ 7 Built-in │
└───────-──┘ └─────────────┘
Dependency Direction: Channel → Router → Engine → Provider / Tool (Unidirectional, no circular dependencies)
card.add/set/append/tick/close + prompt.user/reply + session.event) × 13 card kinds; server-side & client-side tool execution, permission / question / plan-review prompts, and crash-recovery of unanswered promptsSKILL.md files, supporting YAML frontmatter, parameter substitution, and priority overridego_rebuild/
├── cmd/server/ # Entry point & Integration tests
│ ├── main.go # 11-step startup process
│ └── main_test.go # E2E tests (build tag: integration)
├── configs/
│ └── config.yaml # Default configuration
├── internal/
│ ├── channel/ # Multi-protocol access layer (WebSocket / HTTP / Feishu)
│ ├── command/ # Command registration & Priority system
│ ├── config/ # Viper configuration management (50+ defaults)
│ ├── engine/ # Core query engine
│ │ ├── queryloop.go # QueryEngine main loop (831 lines)
│ │ ├── executor.go # Parallel/Serial tool executor
│ │ ├── compact/ # LLM context compaction
│ │ ├── context/ # System prompt assembly
│ │ └── session/ # Session state & Lifecycle
│ ├── event/ # In-process pub/sub event bus
│ ├── permission/ # 6-step permission pipeline (6 modes)
│ ├── provider/ # LLM Provider abstraction
│ │ ├── anthropic/ # Direct Anthropic SSE client
│ │ ├── bifrost/ # Multi-Provider adapter
│ │ └── retry/ # Exponential backoff + 529 overload switching
│ ├── router/ # Message routing + Middleware chain
│ ├── skill/ # SKILL.md loading & Parameter substitution
│ ├── storage/ # Storage interfaces (Memory implementation)
│ └── tool/ # Tool system
│ ├── tool.go # Tool interface + 10 extension interfaces
│ ├── registry.go # Thread-safe tool registry
│ ├── pool.go # Immutable per-query tool pool
│ └── bash/fileread/fileedit/filewrite/grep/glob/webfetch/skilltool/
├── pkg/
│ ├── types/ # Shared types (Message, Event, ToolCall, Context)
│ └── errors/ # Domain errors (16 error codes)
├── docs/
│ ├── protocols/ # WebSocket protocol specification (v2.2)
├── Makefile # Build/Run/Test/Lint
└── go.mod # Go 1.26.1
# Build
make build # Outputs to ./dist/harnessclaw-engine
# Run (using default configuration)
make run # go run ./cmd/server -config ./configs/config.yaml
# Run directly with a specific configuration file
./dist/harnessclaw-engine -config ./configs/config.yaml
# Unit tests
make test # go test ./... -v -race -count=1
# Coverage report
make test-cover # Generates coverage.html
# Integration tests (requires real LLM API)
go test -tags=integration ./cmd/server/ -v
go test -tags=integration ./internal/provider/bifrost/ -v
make fmt # Format code
make tidy # Tidy go.mod
make lint # Run linters
make vuln # Scan for vulnerabilities
make clean # Clean build artifacts
The configuration file is located at configs/config.yaml. Main configuration items:
| Configuration Item | Description | Default Value |
|---|---|---|
server.port | HTTP server port | 8080 |
channels.websocket.port | WebSocket port | 8081 |
channels.websocket.path | WebSocket path | /v1/ws |
llm.default_provider | LLM Provider | anthropic |
llm.providers.anthropic.model | Model name | astron-code-latest |
engine.max_turns | Max tool calls per turn | 50 |
engine.auto_compact_threshold | Token ratio threshold for auto-compaction | 0.8 |
session.idle_timeout | Session idle timeout | 30m |
permission.mode | Permission mode | default |
tools.* | Individual tool toggles | All true |
Connection Address: ws://host:8081/v1/ws
The protocol is a UI-first card model: the engine streams cards (a turn, a message, a tool call, a sub-agent, …) that are opened, appended to, and closed, rather than a flat event log.
Client Server
│ │
│── WebSocket upgrade ────────────────────>│
│<──────────────── 101 Switching ─────────│
│<──── session.event (kind=opened) ───────│ handshake + capabilities
│ │
│── user.message ─────────────────────────>│
│<──────────────── card.add ──────────────│ open a card (turn / message / tool / …)
│<──────────────── card.append ───────────│ stream content (channel: text / tool_input)
│<──── prompt.user (permission / … ) ─────│ engine asks; blocks until answered
│── prompt.user_response ─────────────────>│
│<──────────────── card.close ────────────│ card done (+ metrics: tokens, cost)
│<──────────── card.close (kind=turn) ────│ turn finished
│ │
│── session.interrupt (trace_id) ─────────>│ interrupt an in-flight turn
│── session.resume (last_seq) ───────────>│ reconnect & replay missed events
For a copy-paste client, see the Usage Examples; for the full wire contract, see docs/protocols/websocket.md.

Apache-2.0 License. See LICENSE for details.
Go
98.3%
An LLM programming assistant engine built with Go, supporting WebSocket, multi-turn dialogues, tool calling, permission control, and skill extension.
272
stars
632
commits
Go
primary language
Aug 30, 2026
updated
An LLM programming assistant engine built with Go. It provides capabilities via the WebSocket protocol, supporting multi-turn dialogues, tool calling, permission control, and skill extension.
┌───────────-──┐ ┌─────────────┐ ┌─────────────┐
│ WebSocket │ │ HTTP │ │ Feishu │
│ Channel │ │ Channel │ │ Channel │
└──────┬───────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└──────────────────┼──────────────────┘
▼
┌──────────────────┐
│Router + Middleware│ Auth / RateLimit / Logging
└────────┬─────────┘
▼
┌──────────────────┐
│ Query Engine │ 5-Phase Loop
│ (queryloop.go) │ Preprocessing → LLM Streaming → Error Recovery
└───┬──────────┬───┘ → Tool Execution → Continuation Check
│ │
┌─────▼──-─┐ ┌──▼──────────┐
│ Provider │ │ Tool System │
│ (LLM) │ │ 7 Built-in │
└───────-──┘ └─────────────┘
Dependency Direction: Channel → Router → Engine → Provider / Tool (Unidirectional, no circular dependencies)
card.add/set/append/tick/close + prompt.user/reply + session.event) × 13 card kinds; server-side & client-side tool execution, permission / question / plan-review prompts, and crash-recovery of unanswered promptsSKILL.md files, supporting YAML frontmatter, parameter substitution, and priority overridego_rebuild/
├── cmd/server/ # Entry point & Integration tests
│ ├── main.go # 11-step startup process
│ └── main_test.go # E2E tests (build tag: integration)
├── configs/
│ └── config.yaml # Default configuration
├── internal/
│ ├── channel/ # Multi-protocol access layer (WebSocket / HTTP / Feishu)
│ ├── command/ # Command registration & Priority system
│ ├── config/ # Viper configuration management (50+ defaults)
│ ├── engine/ # Core query engine
│ │ ├── queryloop.go # QueryEngine main loop (831 lines)
│ │ ├── executor.go # Parallel/Serial tool executor
│ │ ├── compact/ # LLM context compaction
│ │ ├── context/ # System prompt assembly
│ │ └── session/ # Session state & Lifecycle
│ ├── event/ # In-process pub/sub event bus
│ ├── permission/ # 6-step permission pipeline (6 modes)
│ ├── provider/ # LLM Provider abstraction
│ │ ├── anthropic/ # Direct Anthropic SSE client
│ │ ├── bifrost/ # Multi-Provider adapter
│ │ └── retry/ # Exponential backoff + 529 overload switching
│ ├── router/ # Message routing + Middleware chain
│ ├── skill/ # SKILL.md loading & Parameter substitution
│ ├── storage/ # Storage interfaces (Memory implementation)
│ └── tool/ # Tool system
│ ├── tool.go # Tool interface + 10 extension interfaces
│ ├── registry.go # Thread-safe tool registry
│ ├── pool.go # Immutable per-query tool pool
│ └── bash/fileread/fileedit/filewrite/grep/glob/webfetch/skilltool/
├── pkg/
│ ├── types/ # Shared types (Message, Event, ToolCall, Context)
│ └── errors/ # Domain errors (16 error codes)
├── docs/
│ ├── protocols/ # WebSocket protocol specification (v2.2)
├── Makefile # Build/Run/Test/Lint
└── go.mod # Go 1.26.1
# Build
make build # Outputs to ./dist/harnessclaw-engine
# Run (using default configuration)
make run # go run ./cmd/server -config ./configs/config.yaml
# Run directly with a specific configuration file
./dist/harnessclaw-engine -config ./configs/config.yaml
# Unit tests
make test # go test ./... -v -race -count=1
# Coverage report
make test-cover # Generates coverage.html
# Integration tests (requires real LLM API)
go test -tags=integration ./cmd/server/ -v
go test -tags=integration ./internal/provider/bifrost/ -v
make fmt # Format code
make tidy # Tidy go.mod
make lint # Run linters
make vuln # Scan for vulnerabilities
make clean # Clean build artifacts
The configuration file is located at configs/config.yaml. Main configuration items:
| Configuration Item | Description | Default Value |
|---|---|---|
server.port | HTTP server port | 8080 |
channels.websocket.port | WebSocket port | 8081 |
channels.websocket.path | WebSocket path | /v1/ws |
llm.default_provider | LLM Provider | anthropic |
llm.providers.anthropic.model | Model name | astron-code-latest |
engine.max_turns | Max tool calls per turn | 50 |
engine.auto_compact_threshold | Token ratio threshold for auto-compaction | 0.8 |
session.idle_timeout | Session idle timeout | 30m |
permission.mode | Permission mode | default |
tools.* | Individual tool toggles | All true |
Connection Address: ws://host:8081/v1/ws
The protocol is a UI-first card model: the engine streams cards (a turn, a message, a tool call, a sub-agent, …) that are opened, appended to, and closed, rather than a flat event log.
Client Server
│ │
│── WebSocket upgrade ────────────────────>│
│<──────────────── 101 Switching ─────────│
│<──── session.event (kind=opened) ───────│ handshake + capabilities
│ │
│── user.message ─────────────────────────>│
│<──────────────── card.add ──────────────│ open a card (turn / message / tool / …)
│<──────────────── card.append ───────────│ stream content (channel: text / tool_input)
│<──── prompt.user (permission / … ) ─────│ engine asks; blocks until answered
│── prompt.user_response ─────────────────>│
│<──────────────── card.close ────────────│ card done (+ metrics: tokens, cost)
│<──────────── card.close (kind=turn) ────│ turn finished
│ │
│── session.interrupt (trace_id) ─────────>│ interrupt an in-flight turn
│── session.resume (last_seq) ───────────>│ reconnect & replay missed events
For a copy-paste client, see the Usage Examples; for the full wire contract, see docs/protocols/websocket.md.

Apache-2.0 License. See LICENSE for details.
Go
98.3%