A framework for AI-driven economic activity. Declarative, composable, observable, deterministic.
# Add to your Claude Code skills
git clone https://github.com/OpenWhale-Org/OpenWhaleLast scanned: 5/30/2026
{
"issues": [
{
"type": "npm-audit",
"message": "esbuild: esbuild enables any website to send any requests to the development server and read the response",
"severity": "medium"
},
{
"type": "npm-audit",
"message": "vite: Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling",
"severity": "medium"
},
{
"type": "npm-audit",
"message": "vite-node: Vulnerability found",
"severity": "medium"
},
{
"type": "npm-audit",
"message": "vitest: Vulnerability found",
"severity": "medium"
}
],
"status": "PASSED",
"scannedAt": "2026-05-30T16:20:07.657Z",
"npmAuditRan": true,
"pipAuditRan": true
}See how OpenWhale compares with popular alternatives.
OpenWhale is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by OpenWhale-Org. A framework for AI-driven economic activity. Declarative, composable, observable, deterministic. It has 150 GitHub stars.
Yes. OpenWhale passed SkillsLLM's automated security scan — a dependency vulnerability audit plus prompt-injection heuristics — with no high-severity issues. You can read the full report in the Security Report section on this page.
Clone the repository with "git clone https://github.com/OpenWhale-Org/OpenWhale" and add it to your Claude Code skills directory (see the Installation section above).
OpenWhale is primarily written in TypeScript. It is open-source under OpenWhale-Org on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh OpenWhale against similar tools.
No comments yet. Be the first to share your thoughts!
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
The programmable layer for composable, AI-native economic strategies
OpenWhale is a TypeScript framework for automated trading strategies. Monitors collect, Strategies decide, Executors act; the three are decoupled, so one strategy runs on any venue and against any data source, and can be written, audited and evolved by an AI.
Development mode with hot reload. For a server see DEPLOYMENT.md.
Prerequisites: Node.js ≥ 20, pnpm ≥ 9 (npm i -g pnpm), git.
1. Clone and install
git clone https://github.com/OpenWhale-Org/OpenWhale.git
cd OpenWhale
pnpm install
2. Configure
cp .env.example .env
Edit .env — three variables are required on first boot:
OPENWHALE_MASTER_KEY=<random secret> # encrypts stored credentials; generate with: openssl rand -hex 32
OPENWHALE_ADMIN_USER=admin # first dashboard account
OPENWHALE_ADMIN_PASSWORD=<password>
The master key cannot be recovered — losing it means re-entering every API key. The admin variables create the first user; remove them after signing in. Everything else in .env.example is optional (ports, venue proxy, allowed origins).
3. Build and start
pnpm build
pnpm dev # gateway on :3001, dashboard on :3000, both with hot reload
pnpm dev:gateway / pnpm dev:dashboard start one side only.
4. Sign in
Open http://localhost:3000 and sign in with the admin user. The dashboard offers a guided tour on first visit: a credential on the Hyperliquid testnet, an account, a copy-trading instance — no real funds.
5. Trade
Credentials → Accounts → Strategies → New strategy. A strategy instance binds params to accounts; activate it and follow it on Instances (live events, executions, runs, PnL).
Docker instead of steps 1–3:
cp .env.example .env # same three variables
docker compose up -d --build
State lives in the openwhale-data volume; details in DEPLOYMENT.md.
The gateway holds the runtime and all secrets; the dashboard is a frontend that proxies /api/* to it (OPENWHALE_GATEWAY_URL, default http://localhost:3001).
OPENWHALE_HTTPS_PROXY=http://127.0.0.1:7897 # REST + WebSocket, every venue
OPENWHALE_HTTPS_PROXY_BINANCEUSDM=off # per venue: ccxt id upper-cased; `off` = direct
HTTPS_PROXY and NODE_USE_ENV_PROXY are not honoured — ccxt uses its own fetch. The variable is namespaced so that order traffic never changes route through an unrelated proxy setting.
Enforced by the gateway: every /api/* route requires a session; the dashboard only carries the cookie. Sessions are opaque SQLite tokens (7-day expiry, revocable); passwords are scrypt-hashed; there are no roles. Before exposing the gateway: terminate TLS in front of it (the session cookie is Secure), keep port 3001 off the public internet, set OPENWHALE_ALLOWED_ORIGIN only for cross-origin frontends. Details in DEPLOYMENT.md.
exchange/perp × binance, …). Domain packages define kinds, venue packages fill cells; a data-driven ccxt roster ships twelve venues.skills/openwhale-dev skill that teaches Claude the framework contract.| Concept | Definition |
|---|---|
| Monitor | Collects data and emits keyed records (venue:symbol). A contract with one or more implementations; users create per-key instances. Emits persist as JSONL and drive triggers. |
| Strategy | Pure decision logic. Declares monitor / executor / account dependencies by label, receives triggers, returns ExecutionInstruction[]. Params: base (required) and tunable (defaulted) zod schemas. |
| Executor | Turns instructions into venue actions through adapter sessions — retries, idempotent client order ids, latency and slippage capture. Credential slots resolve to sessions (by kind) or raw credential data (raw: true); optional: true slots may stay unbound. |
| Instance | Strategy + params + account bindings, activated as a unit. Live events, executions, runs and logs hang off it. |
| Account | A named binding of a credential to an account implementation (generic or venue-specialized). Strategies read balances and positions through it. |
| Trigger | Cron schedules and monitor conditions (multi-source AND within a window). Subscriptions keep monitors collecting without waking the strategy; addMonitorSource adds sources discovered at runtime. |
| Portfolio journal | Optional instance-scoped history: idempotent snapshots, fills, decisions, market bars. Core stores them and derives equity, drawdown and trade reports. |
Monitor ──emit(key, data)──▶ TriggerManager ──StrategyContext──▶ Strategy ──ExecutionInstruction[]──▶ ExecutionQueue ──▶ Executor
└─ run trace persisted
| Page | Function |
|---|---|
| Instances | Cards with folders, drag ordering, live net-PnL badge; per-instance Live Events, Executions, Runs, Logs; Board view with parameter editing, account rebinding, PnL panel. |
| PnL | Realized / fees / funding / net / unrealized from the attribution ledger; by-symbol, raw fills, open positions at venue mark. Funding is split across instances by position at settlement. |
| Runs | Every run's gates, skips, sizing, instructions and log lines. Runs with instructions or errors persist; idle runs are sampled. |
| Monitor boards | Panels declared by plots(): line, bar, candles, sortable table; single/multi-select keys. |
| Params | Forms generated from zod .meta(): sections, sliders, units, conditional fields, market pickers, availability checks, list (row-table) params, live interactive illustrations. |
| Scripts | Plugin-shipped operator utilities run on demand against the runtime; monospace report, optional JSON and file attachments. |
| Compiler / Assistant | Natural-language strategy compiler (experimental). Recommended path: Claude with skills/openwhale-dev. |
const decls = {
monitors: [{ name: 'exchange/ticker', label: 'price' }],
executors: [{ name: 'exchange/perp-trading', label: 'perp' }],
accounts: [{ account: PerpAccount, label: 'main' }],
} as const satisfies StrategyDeclarations
class MomentumStrategy extends BaseStrategy<typeof decls> {
readonly strategyId = 'momentum'
override readonly monitors = decls.monitors
override readonly executors = decls.executors
override readonly accounts = decls.accounts
readonly baseParamsSchema = z.object({
symbol: z.string().meta({ displayName: 'Symbol' }),
threshold: z.number().meta({ displayName: 'Entry price' }),
})
async evaluate(context: StrategyContext) {
const { symbol, threshold } = this.baseParamsSchema.parse(this.params.base)
const tick = context.getData('price', `${this.accountVenue('main')}:${symbol}`)
this.trace('tick:read', { tick }) // recorded in the run trace
if (!tick || tick.price < threshold) return []
return [
this.instruction('perp', 'placeOrder', {
symbol, side: 'buy', type: 'market', amount: 0.01,
}),
]
}
}
const runtime = new OpenWhaleRuntime({ database, credentialStore })
runtime.loadPlugin(binancePlugin, {})
runtime.loadPlugin(hyperliquidPlugin, {})
await runtime.start()
await runtime.activate({
strategyId: 'my-plugin/momentum',
credentials: { main: 'My Binance' }, // the account binding decides the venue
params: { base: { symbol: 'BTC/USDT:USDT', threshold: 60000 } },
})
async evaluate(context: StrategyContext) {
const data = await this.monitorData('market')?.readLatest(this.accountVenue('main'))
const { action, confidence } = await this.llm({
messages: [{ role: 'user', content: JSON.stringify(data) }],
schema: z.object({
action: z.enum(['buy', 'sell', 'hold']),
confidence: z.number(),
}),
})
if (action === 'hold' || confidence < 0.7) return []
return [
this.instruction('perp', 'placeOrder', {
symbol: 'BTC/USDC:USDC', side: action, type: 'market', amount: 0.01,
}),
]
}
export const planPreview: ScriptDefinition = {
id: 'plan-preview',
name: 'Plan preview',
paramsSchema: z.object({ instance: z.string().default('') }),
paramOptions: async (runtime) => ({ instance: await listMyInstances(runtime) }),
run: async ({ params, runtime }) => ({ text: await renderPlan(runtime, params) }),
}
A plugin is a package whose default export is a factory returning its registrations:
export default definePlugin((ctx) => ({
name: 'my-plugin',
version: '1.0.0',
monit