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. It's gud tek built by a long-time solami dev.
TrenchClaw is an openclaw-like agentic ai 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 release 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
- AI chat with OpenRouter and Vercel AI Gateway
- Local instance sign-in, vault, and trading settings
- Managed wallet reads for balances and holdings
- Wallet creation, grouping, and renaming
- Helius RPC-based data fetching
- Dexscreener market and token research
- Jupiter Ultra swaps
- Queue jobs, scheduled Ultra swaps, and action sequences
- Direct transfers and token account cleanup
- Runtime memory, queue, and conversation history
- Desktop GUI for chat, wallets, keys, settings, activity, and runtime status
- CI pipeline, release automation, and build/release tooling
- Full runtime settings editor in the GUI
- Agent-managed scheduler
- Standard swap paths beyond Jupiter Ultra
- Telegram chat connector
- Gatekeeper option for the Helius RPC link
- Jupiter Trigger API flows
Quick links:
- Quickstart
- Capability Matrix
- Runtime Architecture and Boundaries
- Why TypeScript?
- Why Solana Kit
- TrenchClaw vs ElizaOS and Agent Kit
Interested in sponsoring development? Support us: 7McYcR43aYiDttnY5vDw3SR6DpUxHG8GvLzhUsYFJSyA
Experimental software warning: this is currently unsafe, and unexpected behavior is highly likely if you use it.
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 devuses~/trenchclaw-dev-runtimefor runtime state- generated prompt-support files live under
~/trenchclaw-dev-runtime/instances/<id>/cache/generated/ - that state persists across reconnects and restarts
- that state is personal/local and never part of the repo
Important rules for contributors, reviewers, and agents:
- do not store personal vaults, wallets, logs, databases, or generated runtime state in this repository
.runtime/is the tracked contract only; runtime code must never write there- the external dev runtime keeps local testing close to a real user install without polluting PRs
- tests should use temporary runtime roots, not a shared developer runtime
Common 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 01 \ --to-instance 01 \ --parts wallets,db,settingsUseful overrides:
bun run dev -- --runtime-root /path/to/runtime --generated-root /path/to/runtime/instances/01/cache/generatedTRENCHCLAW_RUNTIME_STATE_ROOT=/path/to/runtime
The external dev runtime writes a managed .gitignore so secrets, keypairs, databases, logs, caches, and other personal testing state stay out of git by default.
Public releases ship as standalone compiled trenchclaw binaries. Bun is required for local development and release engineering, not for end-user installs.
# local verification bun run release:build -- --version v0.0.0 --run-checks # optional drafted release body for manual releases # releases/0.0.0.mdRelease publishing runs through the GitHub Actions Release workflow (workflow_dispatch).
release_mode=manualpublishes the current committed versionrelease_mode=patchauto-bumps the next patch version and uses GitHub-generated notesrelease_mode=minorauto-bumps the next minor version and uses GitHub-generated notesrelease_notes_mode=autouses GitHub-generated notes for manual releases toorelease_notes_mode=draftusesreleases/<version>.mdwhen you want a custom manual release body
flowchart LR A["Push / PR"] --> B["CI: test + app build + bundle verify"] B --> C["Release Trigger"] C --> D["Build app bundle"] D --> E["Package tar.gz + sha256"] E --> F["Generate notes from commits since last tag"] F --> G["Publish GitHub release artifacts"] Desktop chat, activity feed, wallet controls, settings, and live runtime console in one operator surface.
TrenchClaw is designed as a constrained execution system, not a free-form chatbot. The architecture separates control-plane reasoning from execution-plane effects, then applies policy and filesystem constraints before any side-effecting operation.
- Runtime core (
apps/trenchclaw/src/ai/core) composes theActionRegistry,ActionDispatcher,PolicyEngine,Scheduler, and typed event bus. - Bootstrap wiring (
apps/trenchclaw/src/runtime/bootstrap.ts) builds the runtime from normalized settings, registers only allowed actions, and injects adapters into action context. - Action contracts are typed (
Action<Input, Output>) and schema-validated before execution. - Event emission is structured (
action:*,policy:block,queue:*,rpc:failover) and persisted to SQLite/files/session logs for traceability.
- On-chain-capable actions live under
apps/trenchclaw/src/solana/actions/wallet-based/*(wallet ops, transfers, swaps, and some not-yet-headline privacy flows). - Off-chain helper actions are explicit modules under
apps/trenchclaw/src/solana/actions/data-fetch/*:- RPC reads (
getAccountInfo,getBalance,getMultipleAccounts,getTokenMetadata,getTokenPrice,getMarketData) - External API reads (
api/dexscreener.ts) - Runtime introspection helpers (
data-fetch/runtime/*)
- RPC reads (
- Adapters isolate provider specifics (
solana/lib/adapters/*), so action logic remains provider-agnostic.
- Runtime settings normalize into two Jupiter profiles:
trading.jupiter.ultraandtrading.jupiter.standard(apps/trenchclaw/src/runtime/load/loader.ts). - Profile selection is derived from
trading.preferredSwap/trading.defaultSwapProfile; Ultra enables Ultra quote/execute permissions, Standard enables standard quote/execute permissions. - Current runtime capability registration exposes the Ultra path (
ultraQuoteSwap,ultraExecuteSwap,ultraSwap,managedUltraSwap) as the main shipped swap surface. - Standard RPC swap actions (
quoteSwap,executeSwap) exist inwallet-based/swap/rpc/*as modular execution primitives, with parity wiring tracked in the roadmap.
- Filesystem access is enforced by manifest, not prompt intent (
apps/trenchclaw/src/runtime/security/filesystem-manifest.ts+src/ai/brain/protected/system/filesystem-manifest.yaml). - Default model permission is deny (
model: none), with explicit read/write allowlists for narrow runtime paths. - Runtime writes are scoped under the runtime-owned and instance-owned roots, with protected key material guarded by explicit policy checks (
solana/lib/wallet/protected-write-policy.ts).
- Effective settings are produced through a deterministic merge pipeline (
runtime/load/loader.ts): base safety profile -> sanitized agent overlay -> user overlay -> protected-path enforcement -> schema validation. - User-protected settings paths (
runtime/load/authority.ts) prevent agent layers from silently escalating critical controls (wallet danger flags, trading limits, execution permissions, RPC/network endpoints, internet access). - Dangerous action execution can require explicit user confirmation tokens, enforced by runtime policy before dispatch.
This design treats the agent as a policy-constrained orchestrator over explicit modules, with auditable state transitions and narrow I/O boundaries.
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:
- Tool contracts that are both machine-readable and runtime-validatable β the model needs a schema to decide how to call tools; your runtime needs to validate arguments before executing anything (guardrails). In practice this becomes "JSON Schema everywhere" + a local validator.
- A first-class event stream β you don't just want final text; you want structured events: partial tokens, tool-call intents, tool args, tool results, retries, errors, traces.
- Composable middleware β logging, redaction, policy checks, rate limits, caching, retries, circuit breakers, and tool routing.
- Rapid iteration β agent quality is dominated by iteration speed: schema tweaks, tool UX, prompt/tool descriptions, trace analysis.
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:
- Zod is ergonomic to author in TS.
- You can infer TS types from schemas (or vice versa) so the schema and the implementation don't drift.
- You can carry schema objects through routing layers without codegen.
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 capability β it's about where the complexity lives.
- Agent orchestration is I/O-bound + integration-heavy, not CPU-bound. Most agent loops spend time calling models, calling web APIs, waiting on DB, streaming events to UI, and validating/routing tool calls. That profile does not reward Rust/Zig/C++ the way a tight compute kernel does.
- The hard part is contract evolution, not execution speed. The dominant failure modes are schema drift, tool ambiguity, partial/invalid args, and inability to safely evolve tool signatures. TS + schema-first patterns reduce drift because the schema object is colocated with the code and passed through the system as data. In systems languages the "contract as data" story becomes a build-time artifact (codegen), a separate schema file that can drift, or runtime reflection that's less ergonomic than TS + Zod β all of which increase iteration cost.
- Streaming UX is easier in the JS runtime model. Token streaming, partial structured outputs, tool-call visualizations, reactive UI updates β the Vercel/Next ecosystem is optimized for that workflow and the AI SDK provides those primitives in the same language and runtime as your UI.
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.
- AI SDK + Zod is a single control plane in TS. The same schema object drives model-visible tool contracts and runtime validation. In Go/Rust stacks this is usually split across generated types, JSON schemas, and adapter layers, which increases mismatch risk.
- Fast guardrail iteration matters more than compile targets. We frequently adjust tool descriptions, policy checks, confirmation gates, and schema constraints. TS lets these changes land in one place and ship quickly without regeneration/rebinding cycles.
- Wallet and execution safety are runtime-policy problems. Confirmation requirements, amount/notional limits, allowlists, idempotency keys, decision traces, and policy block reasons all live in orchestration/runtime layers. That layer benefits most from TS-native schema + event tooling.
- Most Go/Rust "agent frameworks" optimize for infra shape, not operator safety UX. They can be excellent for service performance, but often require extra custom work to match strict tool schemas, rich stream events, and interactive safety controls expected in trading/operator systems.
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)
- TS owns: tool schemas and validation, orchestration loop and routing, streaming events and UI integration, persistence format/versioning of traces, provider adapters (AI SDK).
- Rust/Zig/Go (optional) own: cryptography-heavy or latency-critical primitives (signing, parsing), sandboxed tool executables, deterministic compute kernels, RPC services behind strict schemas.
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:
- Schema-aligned tool boundaries: Kit's typed RPC, transactions, and signer APIs map cleanly into JSON Schema/Zod-based tool contracts.
- Safer orchestration loops: functional, immutable transaction composition reduces hidden mutation bugs inside multi-step tool pipelines.
- Lower drift risk: strict TS types around accounts, signers, blockhash lifetimes, and lamports (
bigint) keep model-selected tool args closer to executable reality. - Better iteration velocity: composable modular imports and generated clients (Codama) make it faster to add or refine Solana actions without rewriting plumbing.
TS is effectively required when all are true:
- Orchestration is centered on Vercel AI SDK primitives (tools, streams, strict-mode behavior).
- Tool contracts evolve rapidly and must stay aligned across model-visible schema, runtime validation, and implementation types.
- The product depends on streaming-first UX in a Next/Vercel-style deployment surface.
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:
- Shared storage primitives + ID/value schemas:
src/runtime/storage/schema-primitives.ts - Runtime row schemas:
src/runtime/storage/sqlite-schema.ts - Runtime payload/state schemas:
src/runtime/storage/schema.ts - SQL table/index contract + boot sync + drift inspection:
src/runtime/storage/sqlite-orm.ts - Runtime prints a compact schema snapshot at boot for operator/model context
Runtime 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 notes
Solana 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.
- Registers and dispatches typed Solana actions with policy gates, retries, and idempotency
- Ships managed wallet reads, wallet management, Dexscreener research, Jupiter Ultra swaps, and direct wallet execution flows
- Composes explicit action sequences, queued jobs, and narrow scheduled swap flows without a broad trigger framework
- Persists runtime state, chat history, and receipts in Bun SQLite so local sessions survive restarts
- Uses RPC, Jupiter, and token-account adapters so the runtime stays provider-agnostic
- Generates typed program clients from Anchor IDLs via Codama instead of hand-rolled instruction builders
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 runner bootstrap script to install or upgrade the local development toolchain:
sh ./apps/runner/scripts/bootstrap-deps.shThat helper manages:
- Bun
- Solana CLI
- Helius CLI
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.
Manual install + update commands
# 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@latestUse one command to start the runtime and GUI together:
bun install bun run app:build bun run startWhat bun run start does:
- Starts the dedicated runner (
apps/runner) which then starts the core runtime process (apps/trenchclaw runtime:start) - Rebuilds missing instance-scoped generated artifacts under
.runtime-state/instances/<id>/cache/generated/on startup, and you can force a full refresh withTRENCHCLAW_BOOT_REFRESH_CONTEXT=1/TRENCHCLAW_BOOT_REFRESH_KNOWLEDGE=1 - Starts runtime API on localhost
- Serves GUI from static
apps/frontends/gui/dist - Proxies
/api/*from GUI server to runtime server - Prompts
launch GUI now?and opens browser after Enter (typeskipto keep runtime CLI-only) - Supports
bun run start -- doctorfor local preflight checks
Local GUI development still uses Vite:
bun run gui:devTBD


