sugarcraft / sugar-crush
Chat-shell TUI for AI coding assistants — port of charmbracelet/crush. Pluggable Backend interface (ship your own Anthropic / OpenAI / Ollama / shell-out adapter). Markdown rendering of replies via CandyShine, scrollback viewport via SugarBits, input area via SugarBits TextArea.
Requires
- php: ^8.3
- aws/aws-sdk-php: ^3.300
- google/cloud-ai-platform: ^1.0
- guzzlehttp/guzzle: ^7.12.1
- openai-php/client: ^0.10
- react/promise: ^3.3
- sugarcraft/candy-buffer: dev-master
- sugarcraft/candy-core: dev-master
- sugarcraft/candy-forms: dev-master
- sugarcraft/candy-pty: dev-master
- sugarcraft/candy-shine: dev-master
- sugarcraft/candy-sprinkles: dev-master
- symfony/yaml: ^7.0
Requires (Dev)
- phpunit/phpunit: ^10.5
Suggests
- ext-curl: Used by the HTTP-based providers (OpenAI, Anthropic, SGLang, Custom).
This package is auto-updated.
Last update: 2026-07-10 03:50:46 UTC
README
SugarCrush
A terminal AI coding agent — PHP port of charmbracelet/crush. It is a candy-core TEA program (a real Model/Program render loop with buffer-diffed output and Markdown-rendered replies) wrapped around a full agent engine: multiple LLM providers, model-driven tool calling gated by hooks, prompt-injecting skills, sub-agents, an MCP client/server, and SQLite session history.
┌─ SugarCrush ───────────────────────────────────────┐
│ user> add a test for the Width helper │
│ │
│ assistant │
│ I'll read the helper first, then write the test. │
│ ⚙ Read src/Util/Width.php │
│ ⚙ Edit tests/Util/WidthTest.php │
│ Done — added 4 cases covering the clamp edges. │
└────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────┐
│ > run them█ │
└────────────────────────────────────────────────────┘
Enter to send · Esc / ^C to quit
History: SugarCrush absorbed the former experimental
candy-crushport. There is now a singleSugarCraft\Crushlibrary.
Run it
composer install ./bin/sugarcrush
With no configuration the binary runs the offline EchoProvider through the full engine, so it launches with zero network and zero keys. Point it at a real model with environment variables:
# OpenAI export SUGARCRUSH_PROVIDER=openai export OPENAI_API_KEY=sk-... export SUGARCRUSH_MODEL=gpt-4o # optional; provider default otherwise ./bin/sugarcrush
SUGARCRUSH_PROVIDER accepts openai, anthropic, claude-code, sglang, bedrock, vertex, or custom. Each reads its own credentials from the environment (e.g. ANTHROPIC_API_KEY, AWS ambient creds for Bedrock, GOOGLE_APPLICATION_CREDENTIALS for Vertex). When a real provider is active, the binary wires the built-in coding tools (Bash/Read/Edit/Glob/Grep/WebFetch) and the safety hooks automatically.
Dependency-free shell-out
To avoid PHP SDKs entirely, set SUGARCRUSH_BACKEND_CMD to a command that reads JSON history on stdin and writes the reply to stdout:
export SUGARCRUSH_BACKEND_CMD=~/bin/anthropic.sh ./bin/sugarcrush
#!/usr/bin/env bash # ~/bin/anthropic.sh — keeps PHP network-dep-free, swap models by editing this file payload=$(jq -nc --argjson h "$(cat)" '{model:"claude-opus-4-8", max_tokens:4096, messages:$h}') curl -sN https://api.anthropic.com/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" -d "$payload" | jq -r '.content[0].text'
Providers
SugarCraft\Crush\Providers\ProviderInterface is the single LLM abstraction (capability introspection, batch + \Generator streaming, function calling, embeddings, per-model cost). Build one directly or from config via ProviderFactory (which resolves ${VAR} / ${VAR:-default} from the environment):
use SugarCraft\Crush\Providers\ProviderFactory; $factory = new ProviderFactory(); $provider = $factory->create(['type' => 'openai', 'apiKey' => '${OPENAI_API_KEY}', 'model' => 'gpt-4o']);
| Provider | Type key | Notes |
|---|---|---|
| OpenAI | openai |
openai-php/client; function calling, embeddings, cost table |
| Anthropic | anthropic |
real Messages API (/v1/messages, x-api-key) |
| Claude Code CLI | claude-code |
drives the claude binary headless; native cost; JSON schema |
| SGLang | sglang |
OpenAI-compatible self-hosted endpoints (Guzzle) |
| AWS Bedrock | bedrock |
Converse API via aws/aws-sdk-php; per-model pricing |
| GCP Vertex | vertex |
Anthropic-on-Vertex via an injectable predictor seam |
| Custom | custom |
any OpenAI-compatible HTTP endpoint |
| Echo | — | EchoProvider: offline, echoes the last turn; default + tests |
The agent loop
EngineBackend bridges the chat-shell Backend seam to the engine. Each user turn runs a bounded agentic loop: call the provider through the Runtime, execute any tool calls through the hook gate, feed the results back, and repeat until the model answers without calling tools — or a maxSteps ceiling is hit.
use SugarCraft\Crush\Backend\EngineBackend; use SugarCraft\Crush\Hooks\{HookManager, HookRegistry}; use SugarCraft\Crush\Tools\BuiltIn\{Bash, Read, Edit, Glob, Grep, WebFetch}; $hooks = new HookManager(new HookRegistry()); $hooks->registerBuiltIns(); // audit + confirm-rm + protect-files $backend = (EngineBackend::new($provider, 'gpt-4o')) ->withTools([new Bash(), new Read(), new Edit(), new Glob(), new Grep(), new WebFetch()]) ->withHooks($hooks); (new Program(new Chat(backend: $backend)))->run();
Capabilities
- Tools —
Tools\BuiltIn\*:Bash,Read,Edit,Glob,Grep,WebFetch. ImplementTools\Toolfor your own. - Hooks —
Hooks\*: pre/post-tool-use guards (allow / deny / modify the input). Built-ins:AuditHook,ConfirmRemoveHook,ProtectFilesHook. YAML config and externalScriptHooksupported. - Skills —
Skills\*: frontmatterSKILL.mdfiles inject prompt context, matched by keyword/path. Discovered from built-ins,~/.sugar-crush/skills, and<project>/.sugar-crush/skills(project wins). Ships php-best-practices, security-audit, phpunit-master, composer-wizard. - Agents —
Agents\*: 6 sub-agent presets (coder/reviewer/debugger/architect/tester/devops) with their own model, tools, skills, and a streaming lifecycle. - MCP —
MCP\*: multi-server client (stdio + HTTP,.mcp.json,${VAR}interpolation) and stdio/HTTP servers to host your own tools. - Sessions —
Session\SessionStore: SQLite (WAL) persistence of sessions/messages/tool-calls with FK-enforced cascade and age-based pruning. - Tokens & export —
Util\TokenTracker(token + cost accumulation) andUtil\Exporter(Markdown / JSON / text transcripts). - Messages — typed
Messages\{System,User,Assistant,ToolResult}Message;UserMessagecarries file/image attachments;AssistantMessagecarries tool calls + reasoning.
Architecture
SugarCrush keeps the proven sugar-crush chassis (the Chat candy-core Model, buffer-diff Renderer, bin/sugarcrush) and runs the ported engine behind it:
bin/sugarcrush
└─ Program → Chat (Model: input, scrollback, inFlight gate, buffer-diff view)
└─ Backend ── EchoBackend / CommandBackend (simple)
└─ EngineBackend (agent loop)
└─ Runtime → ProviderInterface (+ Tools · Hooks · Skills via App)
The chassis speaks the root Message value object; the engine speaks the typed Messages\* hierarchy; EngineBackend converts at the seam.
Custom provider
use SugarCraft\Crush\Providers\{ProviderInterface, CompleteRequest, CompleteResponse, EmbeddingsRequest, EmbeddingsResponse}; final class MyProvider implements ProviderInterface { public function name(): string { return 'mine'; } public function supportsStreaming(): bool { return false; } public function supportsFunctionCalling(): bool { return true; } public function supportsVision(): bool { return false; } public function supportsJsonSchema(): bool { return false; } public function contextWindow(): int { return 128_000; } public function costPer1kTokens(string $model, string $direction): float { return 0.0; } public function complete(CompleteRequest $r): CompleteResponse { /* ... */ } public function completeStream(CompleteRequest $r): \Generator { /* yield CompleteResponse chunks */ } public function embeddings(EmbeddingsRequest $r): EmbeddingsResponse { /* ... */ } }
Tests
cd sugar-crush && composer install && vendor/bin/phpunit
1,239 tests / 2,924 assertions. Coverage spans every subsystem: typed messages + attachments, the 6 built-in tools, all 7 providers (unit-tested with mocked transports — no live calls), the hook framework, skills discovery, sub-agents, the MCP client/servers, the SQLite store, token tracking, export, the TUI components, the Runtime orchestration (streaming accumulation, tool-result correlation, MODIFY hooks), and the EngineBackend agentic loop (incl. the maxSteps guard).
