Please give us a star if you're interested in seeing this project get fully built out. It will help me gauge interest. Thank you.
TrenchClaw is an openclaw-like agentic ai harness and runtime for the Solana blockchain. It's a personal solana assistant that executes modular on-chain actions, runs automated trading routines, and gives operators full visibility and control from our lightweight svelte gui. This is very dangerous and will be a while before security is perfected.
Built on @solana/kit and Bun from the ground up, with GUI/mobile surfaces planned for 1.0. Zero legacy dependencies (including legacy @solana/web3.js v1). Functional, composable, tree-shakeable. Designed for operators who care about what ships in their binary.
Current test requirement keys: helius api key for helius-backed reads, jupiter ultra key for swap flows, and an OpenRouter or Gateway API key for chat-driven workflows.
Full architecture: ARCHITECTURE.md
Quick links:
Interested in sponsoring development? Support us: 7McYcR43aYiDttnY5vDw3SR6DpUxHG8GvLzhUsYFJSyA
Use the docs for install and first-run:
Local development should use the same per-instance runtime shape as the shipped product, while keeping mutable state outside the repo.
Default local dev behavior:
bun run dev uses ~/.trenchclaw-dev-runtime for runtime state~/.trenchclaw-dev-runtime/instances/<id>/cache/generated/Important rules for contributors, reviewers, and agents:
.runtime/ is the tracked contract only; runtime code must never write thereCommon setup:
# initialize the default external dev runtime once
bun run dev:runtime:init
# start local dev against the persistent external runtime
bun run dev
# copy selected instance state into the external dev runtime
bun run dev:instance:clone -- \
--from-root /path/to/source-runtime \
--to-root ~/.trenchclaw-dev-runtime \
--from-instance 00 \
--to-instance 00 \
--parts wallets,db,settings
Useful overrides:
bun run dev -- --runtime-root /path/to/runtime --generated-root /path/to/runtime/instances/00/cache/generatedTRENCHCLAW_RUNTIME_STATE_ROOT=/path/to/runtimeThe external dev runtime writes a managed .gitignore so secrets, keypairs, databases, logs, caches, and other personal testing state stay out of git by default.
Desktop chat, activity feed, wallet controls, settings, and live runtime console in one operator surface.
TrenchClaw is a constrained execution runtime, not a free-form chatbot shell.
The shortest correct model is:
apps/trenchclaw is the source of truth.apps/frontends/gui is a client of the runtime.apps/runner packages and launches the runtime plus GUI.apps/trenchclaw/src/tools.src/tools/registry.ts declares the runtime action tools and workspace tools.src/tools/snapshot.ts builds the current tool snapshot from settings, filesystem policy, and release readiness.src/ai/gateway/lanePolicy.ts chooses the tool subset for each lane.src/runtime/chat/service.ts registers only that selected tool subset with the model.workspaceListDirectory, workspaceReadFile, and workspaceBash stay available only when policy allows them..runtime is the repo-tracked contract and template area..runtime-state is the live mutable state root.This design keeps the model on a narrow, explicit tool surface while still allowing enough freedom to inspect the runtime workspace and use a constrained shell when needed. The goal is a local operator runtime with auditable state transitions and deliberate machine boundaries, not a vague assistant with broad host access.
The TypeScript repo is heavier than minimalist alternatives. But it is currently the best and most accurate agent orchestrator for this stack. Here is why.
An "advanced" agent (beyond prompt-in / prompt-out) is mostly state + typed tool I/O + event streaming + orchestration:
That set of needs strongly selects for ecosystems that treat schemas as primary artifacts, JSON as the native interchange, streaming as a first-class API, and web deployment as the default.
Compile-time types + runtime schemas (the missing half in systems languages).
For agents, types alone are insufficient because the LLM must see the contract and your runtime must validate untrusted tool arguments. In the Vercel AI SDK tool model, a tool declares an inputSchema (Zod or JSON Schema) which is both consumed by the LLM (tool selection + argument shaping) and used by the runtime to validate the tool call before execute runs. TypeScript is where this shines:
In most systems-language stacks you end up with one of: great static typing but the schema shown to the model is hand-rolled/duplicated, or runtime validation that requires heavy codegen pipelines. Agent code is glue code. Glue code penalizes heavy codegen.
The Vercel AI SDK is TypeScript-first by design.
Vercel positions the AI SDK as "The AI Toolkit for TypeScript." Tool calling (generateText + tool(...)) is a core primitive. AI SDK strict mode behavior (tool schema compatibility, fail-fast semantics) is exactly the production detail you want in advanced agents. If your orchestration is centered on Vercel AI SDK primitives — tools, streams, UI streaming, provider adapters — the lowest-friction native language is TS.
Structural typing + JSON-native payloads + ergonomic transforms.
Agent payloads are structurally shaped objects: tool args, tool results, intermediate plans, traces. TS is effective because structural typing matches JSON shapes, transform pipelines are concise (map/filter/reduce, Zod transforms), and you can model event streams as discriminated unions and exhaustively switch on them (high leverage for agent traces). In systems languages you're constantly bridging between strongly typed structs and dynamic JSON, adding serialization boilerplate and versioning friction.
The JS/TS agent ecosystem is schema-driven by default.
Community patterns converge on "schema as first-class value," and lots of integrations assume Node/TS toolchain. Even if you don't use LangChain, this means schema-oriented integrations are plug-and-play rather than ports.
This isn't about raw power — it's about where the complexity lives.
In this repo's environment (AI SDK orchestration + schema-first tools + Solana execution), the main risk is usually unsafe or ambiguous tool behavior, not raw compute throughput.
Systems languages still fit extremely well behind strict boundaries (signing, parsing, deterministic execution, high-throughput services). They are usually not the fastest path for the orchestrator that must remain tightly coupled to AI SDK tool contracts and streaming UI behavior.
The strongest default architecture for this stack is:
TypeScript orchestrator (agent brain) + optional systems-language executors (muscle, only when justified)
This preserves agentic flow (fast iteration, schema-first tooling, Vercel AI SDK integration) while using systems languages only where they actually dominate. If no component is bottlenecked by throughput, latency, or native constraints, an all-TypeScript implementation is usually the simpler and better default.
@solana/kit is not just a Solana SDK choice here; it improves the same agentic properties this TypeScript stack optimizes for:
bigint) keep model-selected tool args closer to executable reality.TS is effectively required when all are true:
Under these constraints, systems-language orchestrators often re-create TS-native schema + streaming + UI integration layers from scratch.
TrenchClaw does not use @solana/web3.js v1. It uses @solana/kit (formerly web3.js v2), the official ground-up rewrite from Anza.
The old @solana/web3.js is a monolithic, class-based SDK. Its Connection class bundles every RPC method into a single non-tree-shakeable object. Whether you call one method or fifty, your users download the entire library. It relies on third-party crypto polyfills, uses number where bigint belongs, and provides loose TypeScript types that let bugs slip to runtime.
Kit is the opposite. It is functional, composable, zero-dependency, and fully tree-shakeable. It uses the native Web Crypto API for Ed25519 signing instead of userspace polyfills. It uses bigint for lamport values. It catches missing blockhashes, missing signers, and wrong account types at compile time, not after your transaction fails on-chain.
@solana/web3.js v1 |
@solana/kit v6 |
|
|---|---|---|
| Architecture | Monolithic Connection class |
28 modular packages |
| Bundle (minified) | ~450 KB | ~100 KB compressed |
| Tree-shakeable | No | Yes |
| Dependencies | Multiple (bn.js, borsh, buffer, etc.) | Zero |
| Crypto | Userspace polyfills | Native Web Crypto API (Ed25519) |
| Large numbers | number (lossy above 2^53) |
bigint (safe for lamports) |
| Type safety | Loose | Strict (compile-time signer/blockhash/account checks) |
| Confirmation latency | Baseline | ~200ms faster in real-world testing |
| Maintenance | Security patches only | Active development by Anza |
Real-world impact: the Solana Explorer homepage dropped its bundle from 311 KB to 226 KB (a 26% reduction) after migrating to Kit.
No more Connection class. Kit replaces it with createSolanaRpc() and createSolanaRpcSubscriptions() — lightweight proxy objects that only bundle the methods you actually call. Whether your RPC supports 1 method or 100, the bundle size stays the same.
No more Keypair. Kit uses CryptoKeyPair from the Web Crypto API via generateKeyPairSigner(). Private keys never have to be exposed to the JavaScript environment. Signing happens through TransactionSigner objects that abstract the mechanism — hardware wallet, browser extension, CryptoKey, or noop signer for testing.
No more mutable transactions. Kit uses a functional pipe() pattern to build transaction messages. Each step returns a new immutable object with an updated TypeScript type, so the compiler tracks what your transaction has (fee payer, blockhash, instructions, signers) and what it's missing — before you ever hit the network.
import { pipe, createTransactionMessage, setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions,
signTransactionMessageWithSigners } from '@solana/kit';
const tx = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(payer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
(tx) => appendTransactionMessageInstructions([transferInstruction], tx),
);
const signed = await signTransactionMessageWithSigners(tx);
No more hand-rolled instruction builders. Program interactions use generated clients from Codama IDL files. Drop an IDL JSON in lib/client/idl/, run codegen, get typed instruction builders, account decoders, PDA helpers, and error enums. TrenchClaw imports from these generated clients — never constructs instructions manually.
If you are evaluating Solana agent stacks today, the practical split is this: TrenchClaw is built directly on @solana/kit, while many existing agent ecosystems still rely on legacy @solana/web3.js integrations.
| TrenchClaw | ElizaOS (typical Solana plugin setups) | Agent Kit style starter stacks | |
|---|---|---|---|
| Primary Solana SDK | @solana/kit |
Commonly @solana/web3.js-based plugins/adapters |
Commonly @solana/web3.js wrappers |
| API style | Functional + composable | Framework/plugin driven | Framework/toolkit driven |
| Tree-shaking | Strong (modular Kit packages) | Often weaker due to Connection-style clients |
Often weaker due to broad utility bundles |
| Type guarantees around tx composition | Strong compile-time checks in Kit pipeline | Depends on plugin quality | Depends on toolkit layer |
| Runtime focus | Terminal-first operator runtime | Multi-platform agent framework | General AI-agent developer UX |
| Framework/runtime | Throughput (req/s) |
|---|---|
| Rust + Axum | 21,030 |
| Bun + Fastify | 20,683 |
| ASP.NET Core | 14,707 |
| Go + Gin | 3,546 |
| Python + FastAPI (Uvicorn) | 1,185 |
TrenchClaw uses Bun's built-in SQLite (bun:sqlite) for runtime jobs, receipts, policy/decision traces, market/cache data, and chat persistence (conversations, chat_messages). It keeps state local, restart-safe, and dependency-light.
Schema is Zod-first and auto-synced on boot:
src/contracts/persistence.tssrc/runtime/storage/sqliteSchema.tssrc/runtime/storage/schema.tssrc/runtime/storage/sqliteOrm.tsRuntime log/data layout is split by purpose under src/ai/brain/db/:
runtime/: SQLite DB + runtime event filessessions/: session index + JSONL transcript streamsummaries/: compact per-session markdown summariessystem/: daily system/runtime logsmemory/: daily + long-term memory notesSolana Kit, Jupiter integration, and Codama-generated clients are all TypeScript-native in this repo. Bun gives fast startup, strong HTTP performance, and native TypeScript execution while keeping the codebase in one language.
The current public release does not promise a broad autonomous strategy engine yet. Scheduling and queued jobs are the current automation surface; broader strategy automation and non-Ultra public swap paths are still coming.
Use the dev-only runner bootstrap script to install or upgrade the local development toolchain:
sh ./apps/runner/scripts/bootstrap-dev-tools.sh
That helper manages:
Public standalone installs do not require Bun, Solana CLI, or Helius CLI for first launch. Install those CLIs only when a workflow explicitly needs them.
# Bun (macOS/Linux)
curl -fsSL https://bun.sh/install | bash
# Solana CLI via Anza installer (macOS/Linux, stable channel)
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
# Helius CLI
bun add -g helius-cli@latest
# verify installs
bun --version
solana --version
helius --version
# update commands
bun upgrade
agave-install update
bun add -g helius-cli@latest
Use one command to start the runtime and GUI together:
bun install
bun run app:build
bun run start
What bun run start does:
apps/runner) which then starts the core runtime process (apps/trenchclaw runtime:start).runtime-state/instances/<id>/cache/generated/ on startup, and you can force a full refresh with TRENCHCLAW_BOOT_REFRESH_CONTEXT=1 / TRENCHCLAW_BOOT_REFRESH_KNOWLEDGE=1apps/frontends/gui/dist/api/* from GUI server to runtime serverlaunch GUI now? and opens browser after Enter (type skip to keep runtime CLI-only)bun run start -- doctor for local preflight checksLocal GUI development still uses Vite:
bun run gui:dev
TBD