# Grimoire
> A Portable Execution Language for Onchain Strategies
## Core Concepts
The key ideas behind Grimoire. Understanding these will help you work with both the CLI and the Platform.
### Spells
A **spell** is a strategy written in Grimoire's `.spell` format. It describes what you want to do — which assets, which protocols, under what conditions — in a readable, structured way.
```spell [swap-example.spell]
spell SwapExample {
venues: {
uniswap: @uniswap_v3
}
params: {
amount: 1000
}
on manual: {
uniswap.swap(USDC, ETH, params.amount)
}
}
```
A spell is not code that runs directly. It **compiles** into an intermediate representation (IR) that the runtime can evaluate safely.
### Preview and Commit
Every spell execution follows a two-phase safety model:
#### Preview
The runtime executes the full spell logic — evaluating conditions, planning actions, checking constraints — **without moving any funds**. The result is a **receipt** that describes exactly what would happen.
#### Commit
If the preview receipt is `ready`, commit executes the planned actions onchain. If anything has changed since the preview (price drift, state changes), commit can reject the execution.
This separation means:
* You always see the plan before it runs
* Constraints are checked before irreversible actions
* You can simulate and dry-run as many times as needed
**The typical flow:**
```
validate → simulate (preview) → cast --dry-run (preview + sign) → cast (preview + commit)
```
### Venues and Adapters
A **venue** is a protocol that Grimoire can interact with — Aave, Uniswap, Morpho Blue, and others.
Each venue has an **adapter** that translates spell actions into protocol-specific calls. This means your spell logic stays the same even if you switch between venues.
```spell [venues block]
venues: {
lender: @aave_v3 // swap this to @morpho_blue and the spell still works
}
```
Currently supported venues:
| Venue | Type | Actions |
| ------------- | --------------------- | --------------------------------------------------------- |
| Aave V3 | Lending | lend, withdraw, borrow, repay |
| Uniswap V3/V4 | DEX | swap |
| Morpho Blue | Lending | lend, withdraw, borrow, repay, supply/withdraw collateral |
| Across | Bridge | bridge |
| Hyperliquid | Perps (offchain) | order placement |
| Pendle | Yield | market/liquidity operations |
| Polymarket | Prediction (offchain) | order placement |
### Constraints
Constraints are **runtime policy** — not comments or suggestions. They are checked during preview and can reject execution before anything irreversible happens.
Examples:
* `max_slippage: 0.5%` — reject if slippage exceeds threshold
* `max_single_move: 50000` — cap the size of any single action
* `approval_required_above: 100000` — require explicit approval for large moves
### Advisory Decisions
Some strategies need judgment calls — "Is now a good time to rebalance?" or "Which pool has better yield?"
Grimoire handles this with **advisory decisions**: typed prompts sent to an AI model during execution. The key difference from a free-form AI call is that advisories have:
* A **schema** for the expected output
* A **fallback** value if the model is unavailable
* A **timeout** to prevent hanging
* Full **audit trail** in the execution ledger
```spell [advise block]
decision = advise risk: "Should we rebalance given current gas costs?" {
output: { type: boolean }
timeout: 10
fallback: false
}
```
This keeps AI assistance explicit, bounded, and replayable.
export function Redirect() {
if (typeof window !== 'undefined') {
window.location.replace('/llms-full.txt')
}
return null
}
## Getting Started with the Platform
Set up API authentication and make your first call to the Grimoire Platform.
::::steps
#### Base URL
```
https://api.grimoire.run
```
#### Authentication
All API requests require an API key. Include it in the `x-api-key` header or use a Bearer token in the `Authorization` header:
:::code-group
```bash [x-api-key]
curl -H "x-api-key: YOUR_API_KEY" https://api.grimoire.run/health
```
```bash [Bearer Token]
curl -H "Authorization: Bearer YOUR_API_KEY" https://api.grimoire.run/health
```
:::
#### Check Service Health
Verify the API is reachable:
:::code-group
```bash [Request]
curl https://api.grimoire.run/health
```
```json [Response]
{
"status": "ok",
"version": "1.0.0",
"timestamp": "2026-02-26T12:00:00Z"
}
```
:::
#### Your First API Call: Validate
The simplest endpoint is `/v1/validate`. It takes an action plan and checks it against your policies:
:::code-group
```bash [Request]
curl -X POST https://api.grimoire.run/v1/validate \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"partner_id": "YOUR_PARTNER_ID",
"action_plan": {
"chain": "ethereum",
"actions": [
{
"type": "swap",
"venue": "uniswap_v3",
"params": {
"token_in": "USDC",
"token_out": "ETH",
"amount_in": "1000"
}
}
]
}
}'
```
```json [Response]
{
"status": "accepted",
"validation_id": "val_abc123",
"preview": {
"summary": "Swap 1000 USDC to ETH via Uniswap V3",
"warnings": []
},
"policy_result": {
"version": "1",
"passed_rules": ["ALLOWED_VENUES", "MAX_SLIPPAGE"],
"failed_rules": []
}
}
```
:::
Possible results:
* `accepted` — plan passes all policy checks
* `rejected` — plan violates one or more policies
* `accepted_with_warnings` — plan passes but triggered advisory rules
::::
### Response Format
All API responses follow a consistent envelope:
:::code-group
```json [Success]
{
"ok": true,
"status": "accepted",
"validation_id": "val_abc123"
}
```
```json [Error]
{
"ok": false,
"error": {
"code": "ERR_VALIDATION_FAILED",
"message": "Action plan violates max_single_move policy",
"requestId": "req_abc123"
}
}
```
:::
### API Key Scopes
API keys can be scoped to specific capabilities:
| Scope | Grants access to |
| --------------- | ------------------------------ |
| `validate` | `POST /v1/validate` |
| `run` | `POST /v1/run` |
| `session:read` | `GET /v1/session/{id}` |
| `session:write` | `POST /v1/session/{id}` |
| `policy:read` | `GET` policy endpoints |
| `policy:write` | `POST`, `PUT` policy endpoints |
### Next Steps
* [Validate Actions](/platform/validate) — full validate endpoint documentation
* [Run Intents](/platform/run-intents) — use natural language to create action plans
* [Policies](/platform/policies) — set up automated policy enforcement
## Platform Overview
The Grimoire Platform is a cloud API that builds on the open source engine, adding natural language intents, policy enforcement, session management, and sandboxed execution.
### What the Platform Adds
The open source CLI lets you write and run spells locally. The Platform wraps that engine in an API and adds capabilities that matter for teams and integrations:
* **Natural language intents** — describe what you want in plain English, get a validated action plan back
* **Policy enforcement** — define rules that automatically approve, flag, or reject actions
* **Clarification sessions** — when intent is ambiguous, the API asks follow-up questions instead of guessing
* **Sandboxed execution** — strategy planning runs in isolated environments
* **Audit trail** — every run, decision, and policy evaluation is persisted
### Feature Comparison
| Capability | Open Source CLI | Platform API |
| ------------------------ | --------------- | ---------------- |
| Write and compile spells | Yes | Yes |
| Simulate/preview | Yes | Yes |
| Onchain execution | Yes | Via executor |
| Natural language intents | — | Yes |
| Policy enforcement | — | Yes |
| Clarification sessions | — | Yes |
| Sandboxed execution | — | Yes |
| Multi-user API keys | — | Yes |
| Audit persistence | Local history | Managed database |
### How It Works
```
Intent → Plan → Validate → Preview → (optional) Execute
```
1. **Intent** — you send natural language or a structured action plan
2. **Plan** — the platform translates intent into a Grimoire spell
3. **Validate** — policies are evaluated against the plan
4. **Preview** — the spell runs in simulation to verify outcomes
5. **Execute** — if approved, the plan is committed
If the intent is unclear, the platform enters a **clarification session** — asking targeted questions until the plan is unambiguous.
### API Surface
| Endpoint | Purpose |
| ----------------------- | ---------------------------------------------- |
| `POST /v1/validate` | Validate an action plan against policies |
| `POST /v1/run` | Create an intent session from natural language |
| `POST /v1/session/{id}` | Submit clarification answers |
| `GET /v1/session/{id}` | Get current session state |
| Policy CRUD endpoints | Manage partner policies |
### Next Steps
* [Getting Started](/platform/getting-started) — set up authentication and make your first API call
* [Validate Actions](/platform/validate) — validate action plans
* [Run Intents](/platform/run-intents) — use natural language to create strategies
## Policies
Policies are automated rules that govern what actions are allowed through the Grimoire Platform. Every action plan validated through the API is checked against your active policies.
### What Policies Do
Policies let you define guardrails that are enforced automatically:
* **Limit trade sizes** — reject swaps above a threshold
* **Restrict venues** — only allow specific protocols
* **Require approval** — flag large moves for manual review
* **Cap slippage** — reject trades with excessive slippage
* **Control risk** — enforce health factor minimums for lending positions
Policies are checked during validation (`POST /v1/validate`) and as part of the run flow (`POST /v1/run`).
### Policy Rules
A policy contains one or more rules. Each rule specifies a condition that is evaluated against the action plan.
Example rules:
| Rule Code | Description | Example Params |
| ------------------- | ------------------------------------- | --------------------------------------- |
| `ALLOWED_CHAINS` | Whitelist of permitted chains | `{"chains": ["ethereum", "base"]}` |
| `ALLOWED_VENUES` | Whitelist of permitted venue adapters | `{"venues": ["uniswap_v3", "aave_v3"]}` |
| `ALLOWED_ACTIONS` | Whitelist of permitted action types | `{"actions": ["swap", "deposit"]}` |
| `ALLOWED_TOKENS` | Whitelist of permitted tokens | `{"tokens": ["USDC", "ETH"]}` |
| `MAX_ACTIONS` | Maximum number of actions per plan | `{"max": 5}` |
| `MAX_POSITION_SIZE` | Maximum value for any single action | `{"max": 50000}` |
| `MAX_LEVERAGE` | Maximum leverage ratio | `{"max": 3}` |
| `MAX_SLIPPAGE` | Maximum allowed slippage | `{"max": 0.01}` |
| `MAX_GAS` | Maximum gas cost | `{"max": 0.05}` |
| `MAX_PRICE_IMPACT` | Maximum price impact | `{"max": 0.02}` |
### Managing Policies
#### Create a Policy
```bash [Create Policy]
curl -X POST https://api.grimoire.run/v1/partners/YOUR_PARTNER_ID/policies \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Trading Limits",
"rules": [
{
"code": "MAX_POSITION_SIZE",
"phase": "preview",
"params": { "max": 50000 }
},
{
"code": "MAX_SLIPPAGE",
"phase": "preview",
"params": { "max": 0.01 }
},
{
"code": "ALLOWED_VENUES",
"phase": "compile",
"params": { "venues": ["uniswap_v3", "aave_v3", "morpho_blue"] }
}
]
}'
```
#### Update a Policy
```bash [Update Policy]
curl -X PUT https://api.grimoire.run/v1/partners/YOUR_PARTNER_ID/policies/POLICY_ID \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Trading Limits",
"rules": [
{
"code": "MAX_POSITION_SIZE",
"phase": "preview",
"params": { "max": 100000 }
}
]
}'
```
#### Get a Policy
```bash [Get Policy]
curl https://api.grimoire.run/v1/partners/YOUR_PARTNER_ID/policies/POLICY_ID \
-H "x-api-key: YOUR_API_KEY"
```
#### List All Policies
```bash [List Policies]
curl https://api.grimoire.run/v1/partners/YOUR_PARTNER_ID/policies \
-H "x-api-key: YOUR_API_KEY"
```
### Endpoints
| Method | Endpoint | Description |
| ------ | ---------------------------------------------- | --------------------- |
| `POST` | `/v1/partners/{partnerId}/policies` | Create a new policy |
| `PUT` | `/v1/partners/{partnerId}/policies/{policyId}` | Update a policy |
| `GET` | `/v1/partners/{partnerId}/policies/{policyId}` | Get a specific policy |
| `GET` | `/v1/partners/{partnerId}/policies` | List all policies |
### How Policy Evaluation Works
When an action plan is validated:
1. All active policies for your partner account are loaded
2. Each rule is evaluated against the action plan
3. Results are returned per-rule with pass/fail and details
```json [Policy Results]
{
"policy_result": {
"version": "1",
"passed_rules": ["ALLOWED_VENUES", "MAX_SLIPPAGE"],
"failed_rules": ["MAX_POSITION_SIZE"]
}
}
```
:::note
If any `failed_rules` are present with `severity: "error"` (the default), the validation result is `rejected`. Rules with `severity: "warning"` produce `accepted_with_warnings`.
:::
## Run Intents
The run endpoint translates natural language into a validated action plan.
### Endpoint
```bash [Endpoint]
POST /v1/run
```
### Request
```bash [Request]
curl -X POST https://api.grimoire.run/v1/run \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"partner_id": "YOUR_PARTNER_ID",
"user_message": "Swap 100 USDC to ETH on Uniswap",
"user_context": {"chain": "ethereum"}
}'
```
#### Request Body
| Field | Type | Description |
| -------------------- | ------- | ------------------------------------------------------------------- |
| `partner_id` | string | Your partner ID |
| `user_message` | string | Natural language description of what you want to do |
| `user_context.chain` | string | Target chain: `ethereum`, `arbitrum`, `optimism`, `base`, `polygon` |
| `stream` | boolean | Enable SSE streaming (default: `false`) |
### Response Types
The run endpoint returns one of two response types depending on whether the intent is clear enough to act on. When the intent is unambiguous, you get a preview. When it is ambiguous or missing information, you get clarification questions.
:::code-group
```json [Preview Ready]
{
"type": "preview",
"state": "PREVIEW_READY",
"session_id": "sess_abc123",
"preview": {
"summary": "Swap 100 USDC to ETH via Uniswap V3",
"gas_estimate": "~$1.20",
"price_impact": "0.05%",
"slippage": "0.2%",
"warnings": []
},
"summary": "Swap 100 USDC to ETH on Uniswap V3."
}
```
```json [Clarification Needed]
{
"ok": true,
"type": "clarification",
"state": "CLARIFYING",
"session_id": "sess_abc123",
"fields": [
{
"id": "slippage",
"label": "Maximum slippage tolerance",
"input": "select",
"required": true,
"options": ["0.5%", "1%", "2%"]
}
]
}
```
:::
When you receive a clarification response, submit answers via the [Sessions](/platform/sessions) endpoint.
### Streaming
For real-time progress updates, enable SSE streaming:
```bash [Streaming Request]
curl -X POST https://api.grimoire.run/v1/run \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"partner_id": "YOUR_PARTNER_ID",
"user_message": "Swap 100 USDC to ETH on Uniswap",
"user_context": {"chain": "ethereum"},
"stream": true
}'
```
Events are delivered with ordered sequence numbers (`seq`) for reliable processing:
```bash [SSE Events]
data: {"seq": 1, "type": "thinking", "message": "Analyzing intent..."}
data: {"seq": 2, "type": "summary_chunk", "message": "Building action plan..."}
data: {"seq": 3, "type": "preview_ready", "state": "PREVIEW_READY"}
data: {"seq": 4, "type": "done"}
```
### Examples
**Simple swap:**
```json [Simple Swap]
{"partner_id": "YOUR_PARTNER_ID", "user_message": "Swap 100 USDC to ETH on Uniswap", "user_context": {"chain": "ethereum"}}
```
**Lending:**
```json [Lending]
{"partner_id": "YOUR_PARTNER_ID", "user_message": "Lend 5000 USDC on Aave", "user_context": {"chain": "ethereum"}}
```
**Bridge:**
```json [Bridge]
{"partner_id": "YOUR_PARTNER_ID", "user_message": "Bridge 1000 USDC from Ethereum to Base", "user_context": {"chain": "ethereum"}}
```
**Multi-step:**
```json [Multi-step]
{"partner_id": "YOUR_PARTNER_ID", "user_message": "Withdraw 2000 USDC from Aave and swap half to ETH", "user_context": {"chain": "ethereum"}}
```
### Limitations
* **Recurring intents** (e.g., "rebalance every hour") are not yet supported as first-class actions. These currently return a clarification response.
* **Partial execution** — if the platform cannot fully represent all requested operations, it returns a clarification rather than executing partially.
## Sessions
Sessions manage the back-and-forth when an intent needs clarification before it can be executed.
### How Sessions Work
When you call `/v1/run` and the intent is ambiguous, the API creates a **session** and returns clarification questions. You submit answers, and the session either resolves to a preview or asks more questions.
```bash [Session Flow]
POST /v1/run → clarification → POST /v1/session/{id} → preview (or more clarification)
```
### Session Lifecycle
:::steps
#### 1. Create a Session
Sessions are created automatically when you call `/v1/run`:
```bash [Request]
curl -X POST https://api.grimoire.run/v1/run \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"partner_id": "YOUR_PARTNER_ID", "user_message": "Move my USDC to a better yield", "user_context": {"chain": "ethereum"}}'
```
If clarification is needed:
```json [Response]
{
"ok": true,
"type": "clarification",
"state": "CLARIFYING",
"session_id": "sess_abc123",
"fields": [
{
"id": "venue",
"label": "Preferred protocol",
"input": "select",
"required": true,
"options": ["aave_v3", "morpho_blue"]
},
{
"id": "amount",
"label": "Amount of USDC to move",
"input": "number",
"required": true
}
]
}
```
#### 2. Submit Answers
```bash [Request]
curl -X POST https://api.grimoire.run/v1/session/sess_abc123 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"answers": {
"venue": "morpho_blue",
"amount": 5000
}
}'
```
The response is either another clarification (if more info is needed) or a preview:
```json [Response]
{
"ok": true,
"type": "preview",
"state": "PREVIEW_READY",
"session_id": "sess_abc123",
"preview": {
"summary": "Move 5000 USDC from Aave to Morpho Blue",
"warnings": []
}
}
```
#### 3. Check Session State
At any point, you can check the current state of a session:
```bash [Request]
curl https://api.grimoire.run/v1/session/sess_abc123 \
-H "x-api-key: YOUR_API_KEY"
```
```json [Response]
{
"ok": true,
"session_id": "sess_abc123",
"state": "PREVIEW_READY",
"unresolved_fields": [],
"latest_preview": {
"summary": "Move 5000 USDC from Aave to Morpho Blue",
"warnings": []
},
"latest_summary": "Moving 5000 USDC to Morpho Blue for better yield.",
"expires_at": "2026-02-26T13:00:00Z",
"version": 3
}
```
:::
### Session States
| State | Meaning |
| --------------- | ---------------------------------------- |
| `CREATED` | Session just created |
| `CLASSIFYING` | Analyzing the intent |
| `CLARIFYING` | Waiting for answers to unresolved fields |
| `BUILDING` | Generating the action plan |
| `VALIDATING` | Running policy and preview validation |
| `PREVIEW_READY` | Intent fully resolved, preview available |
| `EXPIRED` | Session TTL elapsed |
### Endpoints
#### Submit Clarification Answers
```bash [Endpoint]
POST /v1/session/{id}
```
| Field | Type | Description |
| --------- | ------- | ------------------------------------------------------------- |
| `answers` | object | Key-value pairs matching the `id` of each clarification field |
| `message` | string | Optional free-text follow-up message |
| `stream` | boolean | Enable SSE streaming |
#### Get Session State
```bash [Endpoint]
GET /v1/session/{id}
```
Returns:
* Current state
* Unresolved fields
* Latest preview or summary
* TTL (session expiration)
* Optimistic version number
### Example Flow
```bash [Example Flow]
User: "Optimize my lending position"
API: What protocol? What asset? What's your target?
User: "Aave, USDC, maximize APY"
API: How much USDC?
User: "All of it, up to 50,000"
API: → PREVIEW_READY with action plan
```
Each round of clarification narrows the intent until the plan is specific enough to simulate and validate.
## Validate Actions
The validate endpoint checks a structured action plan against your policies and optionally previews the execution.
### Endpoint
```bash [Endpoint]
POST /v1/validate
```
### Request & Response
:::code-group
```bash [Request]
curl -X POST https://api.grimoire.run/v1/validate \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"partner_id": "YOUR_PARTNER_ID",
"action_plan": {
"chain": "ethereum",
"actions": [
{
"type": "swap",
"venue": "uniswap_v3",
"params": {
"token_in": "USDC",
"token_out": "ETH",
"amount_in": "5000"
}
}
]
}
}'
```
```json [Response]
{
"status": "accepted",
"validation_id": "val_abc123",
"artifact": {
"spell_hash": "0xabc123...",
"ir_hash": "0xdef456...",
"compiler_version": "0.13.0"
},
"preview": {
"summary": "Swap 5000 USDC to ETH via Uniswap V3",
"gas_estimate": "~$2.50",
"price_impact": "0.1%",
"slippage": "0.3%",
"warnings": []
},
"policy_result": {
"version": "1",
"passed_rules": ["ALLOWED_VENUES", "MAX_SLIPPAGE"],
"failed_rules": []
}
}
```
:::
#### Request Body
| Field | Type | Description |
| ------------------------------ | ------ | ----------------------------------------------------------------------- |
| `partner_id` | string | Your partner ID |
| `action_plan.chain` | string | Chain name: `ethereum`, `arbitrum`, `optimism`, `base`, `polygon` |
| `action_plan.actions` | array | List of actions to validate |
| `action_plan.actions[].type` | string | Action type: `swap`, `deposit`, `withdraw`, `borrow`, `repay`, `bridge` |
| `action_plan.actions[].venue` | string | Venue adapter name (e.g. `uniswap_v3`, `aave_v3`) |
| `action_plan.actions[].params` | object | Action-specific parameters |
| `action_plan.trigger` | object | Optional trigger (default: `{"kind": "manual"}`) |
| `policy_id` | string | Optional policy to evaluate against |
#### Result Values
| Result | Meaning |
| ------------------------ | ----------------------------------------- |
| `accepted` | All policy checks passed |
| `rejected` | One or more policy rules violated |
| `accepted_with_warnings` | Passed, but some advisory rules triggered |
#### Response Fields
| Field | Description |
| ---------------------------- | -------------------------------------------------------------------- |
| `status` | Validation outcome: `accepted`, `rejected`, `accepted_with_warnings` |
| `validation_id` | Unique ID for this validation run |
| `artifact` | Compiled spell and IR hashes for audit |
| `preview.summary` | Human-readable description of what would happen |
| `preview.warnings` | Non-fatal warnings from simulation |
| `policy_result.passed_rules` | Rule codes that passed |
| `policy_result.failed_rules` | Rule codes that failed (present when rejected) |
### How Validation Works
When you submit an action plan:
1. **Schema check** — the plan structure is validated
2. **Spell compilation** — actions are compiled into a Grimoire spell
3. **Preview simulation** — the spell is simulated against live chain data
4. **Policy evaluation** — your partner policies are checked against the plan and preview results
If preview simulation is unavailable (RPC issues, unsupported venue), the response includes a `degraded` flag and policy evaluation proceeds with compile-time information only.
### Use Cases
* **Pre-trade validation** — check if a trade would pass your risk policies before executing
* **Agent guardrails** — validate AI-generated action plans before allowing execution
* **Compliance checks** — ensure actions stay within defined limits
* **Audit** — every validation is persisted with artifact hashes for traceability
## CLI Reference
Core commands for the Grimoire CLI.
### Command Summary
| Command | Description |
| ----------------------- | ------------------------------------- |
| `grimoire setup` | Configure chain and RPC settings |
| `grimoire compile` | Compile a spell to IR |
| `grimoire validate` | Compile + validate structural rules |
| `grimoire simulate` | Run full preview against live data |
| `grimoire cast` | Preview + commit (execute onchain) |
| `grimoire venues` | List registered venue adapters |
| `grimoire venue` | Fetch live data from a specific venue |
| `grimoire venue doctor` | Check adapter/RPC readiness |
| `grimoire history` | List past runs |
| `grimoire log` | Show event ledger for a run |
| `grimoire wallet` | Wallet management commands |
| `grimoire init` | Initialize .grimoire scaffolding |
| `grimoire setup` | Interactive execute-mode onboarding |
| `grimoire compile-all` | Compile all spells in a directory |
| `grimoire resume` | Resume a waiting cross-chain run |
### compile
Compile a spell file to its intermediate representation.
```bash [Terminal]
grimoire compile [options]
```
| Option | Description |
| ----------------- | ---------------------------------- |
| `--pretty` | Pretty-print the IR output |
| `--output ` | Write IR to file instead of stdout |
### compile-all
Compile all `.spell` files in a directory.
```bash [Terminal]
grimoire compile-all [dir] [options]
```
| Option | Description |
| ------------- | ------------------------------- |
| `--fail-fast` | Stop on first compilation error |
| `--json` | Output results as JSON |
### init
Initialize the `.grimoire` scaffolding for the current directory.
```bash [Terminal]
grimoire init [options]
```
| Option | Description |
| ---------------------- | --------------------------------- |
| `--force` | Overwrite existing scaffolding |
| `--runtime-quickstart` | Include quickstart spell examples |
### validate
Compile and run structural validation on a spell.
```bash [Terminal]
grimoire validate [options]
```
| Option | Description |
| ---------- | ----------------------------- |
| `--strict` | Enable strict validation mode |
### simulate
Run a full preview without committing any actions.
```bash [Terminal]
grimoire simulate [options]
```
| Option | Description |
| ---------------------------- | --------------------------------------------- |
| `--chain ` | Target chain ID |
| `--rpc-url ` | RPC endpoint |
| `--params ''` | Override spell parameters |
| `--advisory-replay ` | Replay advisory decisions from a prior run |
| `--destination-chain ` | Destination chain ID for cross-chain spells |
| `--destination-spell ` | Spell to hand off to on the destination chain |
| `--handoff-timeout-sec ` | Seconds to wait for cross-chain handoff |
### cast
Run preview and optionally commit actions onchain.
```bash [Terminal]
grimoire cast [options]
```
| Option | Description |
| ---------------------------- | --------------------------------------------- |
| `--dry-run` | Preview + sign only, do not submit |
| `--key-env ` | Environment variable containing private key |
| `--chain ` | Target chain ID |
| `--rpc-url ` | RPC endpoint |
| `--params ''` | Override spell parameters |
| `--advisory-replay ` | Replay advisory decisions from a prior run |
| `--destination-chain ` | Destination chain ID for cross-chain spells |
| `--destination-spell ` | Spell to hand off to on the destination chain |
| `--handoff-timeout-sec ` | Seconds to wait for cross-chain handoff |
### venue
Fetch live data from a specific venue adapter.
```bash [Terminal]
grimoire venue [options]
```
| Option | Description |
| ----------------- | --------------------------------------- |
| `--chain ` | Target chain ID |
| `--format ` | Output format: `json`, `table`, `spell` |
| `--rpc-url ` | RPC endpoint |
#### venue doctor
Check that a venue adapter is properly configured:
```bash [Terminal]
grimoire venue doctor --chain 1 --adapter uniswap --rpc-url [--json]
```
### history
List past spell runs.
```bash [Terminal]
grimoire history [options]
```
| Option | Description |
| ------------- | ---------------------- |
| `--limit ` | Number of runs to show |
| `--json` | Output as JSON |
### log
Show the event ledger for a specific run.
```bash [Terminal]
grimoire log [options]
```
| Option | Description |
| --------------- | ------------------------ |
| `--last` | Show the most recent run |
| `--run-id ` | Show a specific run |
| `--json` | Output as JSON |
### resume
Resume a cross-chain run that is waiting for its destination spell to complete.
```bash [Terminal]
grimoire resume [options]
```
| Option | Description |
| --------- | ---------------------------- |
| `--watch` | Poll until the run completes |
| `--json` | Output as JSON |
### wallet
Manage wallets for onchain execution.
```bash [Terminal]
grimoire wallet [options]
```
| Command | Description |
| ---------- | ------------------------------ |
| `generate` | Create a new wallet keystore |
| `import` | Import an existing private key |
| `address` | Show wallet address |
| `balance` | Check wallet balance |
| `wrap` | Wrap ETH to WETH |
| `unwrap` | Unwrap WETH to ETH |
**Common options:**
| Option | Description |
| ----------------- | ------------------------------------- |
| `--key-env ` | Environment variable with private key |
| `--chain ` | Target chain ID |
| `--rpc-url ` | RPC endpoint |
| `--amount ` | Amount for wrap/unwrap |
| `--json` | Output as JSON |
### setup
Interactive onboarding wizard for execute mode — configures wallet, RPC, and runs readiness checks.
```bash [Terminal]
grimoire setup [options]
```
| Option | Description |
| ------------------- | ------------------------------------------------------------ |
| `--chain ` | Target chain ID |
| `--rpc-url ` | RPC endpoint |
| `--adapter ` | Adapter for venue doctor check (default: `uniswap`) |
| `--keystore ` | Path to keystore file (default: `~/.grimoire/keystore.json`) |
| `--key-env ` | Environment variable containing private key to import |
| `--no-doctor` | Skip venue doctor checks |
| `--non-interactive` | Disable interactive prompts (for CI) |
| `--json` | Machine-readable output |
Creates `.grimoire/setup.env` with configuration for subsequent commands.
### RPC Resolution
:::note
Grimoire resolves the RPC endpoint in this order:
1. `--rpc-url` flag
2. `RPC_URL_` environment variable (e.g., `RPC_URL_1` for Ethereum mainnet)
3. `RPC_URL` environment variable
:::
### Exit Codes
| Code | Meaning |
| ---- | --------------------------------------- |
| `0` | Success |
| `1` | General error |
| `2` | Validation/compilation failure |
| `3` | Preview rejected (constraint violation) |
| `4` | Commit rejected (drift/safety check) |
## Writing Your First Spell
Create a simple spell from scratch, compile it, and run it.
### Goal
Write a spell that takes a parameter, uses it in logic, and emits an event. This introduces the basic spell structure without touching any protocols.
:::steps
#### 1. Create the Spell File
Create a file called `spells/hello-grimoire.spell`:
```spell [spells/hello-grimoire.spell]
spell HelloGrimoire {
version: "0.1.0"
description: "My first Grimoire spell"
params: {
amount: 42
}
on manual: {
emit("hello", { value: params.amount })
}
}
```
This spell:
* Declares a parameter `amount` with a default value of `42`
* Triggers manually (not on a schedule)
* Emits an event with the parameter value
#### 2. Compile
```bash [Terminal]
grimoire compile spells/hello-grimoire.spell --pretty
```
This shows the compiled intermediate representation (IR). If there are syntax errors, the compiler will tell you exactly what to fix.
#### 3. Validate
```bash [Terminal]
grimoire validate spells/hello-grimoire.spell
```
Validation goes beyond compilation — it checks structural rules, type consistency, and constraint validity.
#### 4. Simulate
```bash [Terminal]
grimoire simulate spells/hello-grimoire.spell --chain 1
```
Simulation runs the full preview. Since this spell has no onchain actions, it will complete without needing wallet credentials.
#### 5. Override Parameters
You can override default parameter values at runtime:
```bash [Terminal]
grimoire simulate spells/hello-grimoire.spell \
--chain 1 \
--params '{"amount": 100}'
```
#### 6. Inspect the Run
```bash [Terminal]
grimoire history
grimoire log --last
```
The history shows your run, and the log shows every event that occurred — including the `hello` event with your parameter value.
:::
### Next Steps
* [Running Spells](/open-source/running-spells) — learn the full preview-to-commit flow for spells that move value
* [Venues & Adapters](/open-source/venues) — see which protocols you can interact with
* [CLI Reference](/open-source/cli-reference) — all command options
## Installation
### Install the CLI
Install Grimoire globally via npm, or run directly with npx (no install needed):
:::code-group
```bash [npm]
npm i -g @grimoirelabs/cli
```
```bash [npx]
npx -y @grimoirelabs/cli@latest --help
```
:::
### Verify Installation
```bash [Terminal]
grimoire --help
```
You should see the list of available commands including `compile`, `validate`, `simulate`, and `cast`.
### Initial Setup
Configure Grimoire for your target chain:
```bash [Terminal]
grimoire setup
```
Runs an interactive onboarding wizard that configures your wallet, RPC endpoint, and validates adapter connectivity. Use `--non-interactive` with `--chain` and `--rpc-url` flags for CI environments.
:::note
**RPC resolution order:** `--rpc-url` flag → `RPC_URL_` env var → `RPC_URL` env var.
:::
### Updating
Update to the latest version, or always use the latest with npx:
:::code-group
```bash [npm]
npm i -g @grimoirelabs/cli@latest
```
```bash [npx]
npx -y @grimoirelabs/cli@latest
```
:::
### Requirements
* Node.js 18+
* An RPC endpoint for the chain you want to target (Alchemy, Infura, or any standard JSON-RPC provider)
* For onchain execution: a wallet with funds (see [Running Spells](/open-source/running-spells) for wallet setup)
## Quick Start
Get from zero to running your first spell in under 5 minutes.
::::steps
#### 1. Install and Set Up
```bash [Terminal]
npm i -g @grimoirelabs/cli
grimoire setup --chain 1 --rpc-url YOUR_RPC_URL
```
#### 2. Run a Known Spell
Grimoire ships with example spells. Start with a compute-only spell that doesn't move any funds:
```bash [Terminal]
grimoire validate spells/compute-only.spell
grimoire simulate spells/compute-only.spell --chain 1
```
`validate` checks the spell compiles correctly. `simulate` runs a full preview against live chain data.
#### 3. Check the Results
After simulation, review what happened:
```bash [Terminal]
grimoire history
grimoire log --last
```
`history` shows all past runs. `log` shows the detailed event ledger for a specific run.
#### 4. Try a Spell with Actions
When you're ready to try a spell that interacts with a protocol:
```bash [Terminal]
# Validate first
grimoire validate spells/uniswap-swap-execute.spell
# Dry-run: preview + sign, but don't submit onchain
grimoire cast spells/uniswap-swap-execute.spell \
--dry-run \
--key-env PRIVATE_KEY \
--rpc-url YOUR_RPC_URL
```
The `--dry-run` flag runs the full preview and signing pipeline without actually submitting the transaction. This is the safest way to test before going live.
#### 5. Execute Live
:::warning
Always run `--dry-run` first and review the preview results before live execution.
:::
When you're confident in the preview results:
```bash [Terminal]
grimoire cast spells/uniswap-swap-execute.spell \
--key-env PRIVATE_KEY \
--rpc-url YOUR_RPC_URL
```
Without `--dry-run`, this runs preview and then commits the actions onchain.
::::
### Safe Execution Path
Always follow this progression:
```
validate → simulate → cast --dry-run → cast
```
1. **validate** — check syntax and structure
2. **simulate** — preview against live data (no wallet needed)
3. **cast --dry-run** — full pipeline including signing (no submission)
4. **cast** — preview + commit (live execution)
### Next Steps
* [Write your first spell](/open-source/first-spell) — create a spell from scratch
* [Core Concepts](/concepts) — understand the preview/commit model
* [CLI Reference](/open-source/cli-reference) — all available commands
## Running Spells
How to take a spell from validation through simulation to live onchain execution.
### The Execution Pipeline
Every spell goes through the same safety pipeline:
```
validate → simulate → cast --dry-run → cast
```
Each step adds more confidence before you commit real value.
::::steps
#### Validate
```bash [Terminal]
grimoire validate spells/my-strategy.spell
```
Checks that the spell compiles, types are correct, and structural rules pass. No chain connection needed.
#### Simulate (Preview)
```bash [Terminal]
grimoire simulate spells/my-strategy.spell \
--chain 1 \
--rpc-url YOUR_RPC_URL
```
Runs the full spell logic against live protocol data. The runtime plans all actions, evaluates constraints, and produces a **receipt** — but nothing is submitted onchain.
The receipt shows:
* Planned actions and their parameters
* Constraint evaluation results
* Expected value movements
* Status: `ready` or `rejected`
#### Dry-Run Cast
```bash [Terminal]
grimoire cast spells/my-strategy.spell \
--dry-run \
--key-env PRIVATE_KEY \
--rpc-url YOUR_RPC_URL
```
This runs the full pipeline including wallet signing, but **does not submit** the transaction. Use this to verify everything works end-to-end before going live.
#### Live Cast
```bash [Terminal]
grimoire cast spells/my-strategy.spell \
--key-env PRIVATE_KEY \
--rpc-url YOUR_RPC_URL
```
Without `--dry-run`, this runs preview and then **commits** — submitting transactions onchain.
:::warning
The runtime re-checks conditions at commit time. If anything has drifted since preview, the commit will be rejected to protect you.
:::
::::
### Wallet Setup
Grimoire manages wallets through its own keystore.
**Generate a new wallet:**
```bash [Terminal]
grimoire wallet generate
```
**Import an existing key:**
```bash [Terminal]
grimoire wallet import --key-env PRIVATE_KEY
```
**Check address and balance:**
```bash [Terminal]
grimoire wallet address
grimoire wallet balance --chain 1 --rpc-url YOUR_RPC_URL
```
**Wrap/unwrap ETH:**
```bash [Terminal]
grimoire wallet wrap --amount 0.1 --chain 1 --rpc-url YOUR_RPC_URL
grimoire wallet unwrap --amount 0.1 --chain 1 --rpc-url YOUR_RPC_URL
```
### Simulation on a Fork
For thorough testing, you can simulate against a local Anvil fork:
```bash [Terminal]
# Start Anvil fork
anvil --fork-url YOUR_RPC_URL --fork-block-number 12345678
# Run against the fork
grimoire simulate spells/my-strategy.spell \
--chain 1 \
--rpc-url http://127.0.0.1:8545
```
:::tip
This gives you a reproducible environment where you can test without affecting mainnet state.
:::
### Reviewing Results
After any run:
```bash [Terminal]
# List all runs
grimoire history
# Show detailed event ledger for the last run
grimoire log --last
# Show a specific run
grimoire log --run-id
```
### Parameter Overrides
Override default spell parameters at runtime:
```bash [Terminal]
grimoire simulate spells/my-strategy.spell \
--chain 1 \
--params '{"amount": 5000}'
```
### Cross-Chain Execution
For spells that span multiple chains:
```bash [Terminal]
grimoire cast spells/bridge-and-swap.spell \
--key-env PRIVATE_KEY \
--rpc-url YOUR_RPC_URL \
--destination-chain 8453 \
--destination-spell spells/swap-on-base.spell
```
## Venues & Adapters
Venues are the protocols Grimoire can interact with. Each venue has an adapter that translates your spell actions into protocol-specific calls.
### Supported Venues
| Venue | Adapter | Type | Actions |
| ----------- | -------------- | --------------------- | --------------------------------------------------------------------------------- |
| Aave V3 | `@aave_v3` | Lending | `lend`, `withdraw`, `borrow`, `repay` |
| Uniswap V3 | `@uniswap_v3` | DEX | `swap` |
| Uniswap V4 | `@uniswap_v4` | DEX | `swap` |
| Morpho Blue | `@morpho_blue` | Lending | `lend`, `withdraw`, `borrow`, `repay`, `supply_collateral`, `withdraw_collateral` |
| Across | `@across` | Bridge | `bridge` |
| Hyperliquid | `@hyperliquid` | Perps (offchain) | `place_order` |
| Pendle | `@pendle` | Yield | `add_liquidity`, `remove_liquidity`, market operations |
| Polymarket | `@polymarket` | Prediction (offchain) | `place_order` |
### Using a Venue in a Spell
Declare venues in your spell's `venues` block:
```spell [my-strategy.spell]
spell MyStrategy {
venues: {
lender: @aave_v3
dex: @uniswap_v3
}
on manual: {
dex.swap(USDC, ETH, 1000)
lender.lend(ETH, 0.5)
}
}
```
The alias (e.g., `lender`, `dex`) is your choice — you can swap the adapter behind it without changing your spell logic.
### Constraint Support
Not all constraints are supported by every adapter. Here's what's available:
| Constraint | Aave V3 | Uniswap | Morpho | Across | Hyperliquid | Pendle | Polymarket |
| ------------------- | ------- | ------- | ------ | ------ | ----------- | ------ | ---------- |
| `max_slippage` | — | Yes | — | Yes | — | Yes | — |
| `min_health_factor` | Yes | — | Yes | — | — | — | — |
| `max_single_move` | Yes | Yes | Yes | Yes | Yes | Yes | — |
| `deadline` | — | Yes | — | — | — | Yes | — |
### Venue CLI Commands
Grimoire includes CLI commands to fetch live protocol data — useful for getting parameters before writing spells.
#### List Available Venues
```bash [Terminal]
grimoire venues
```
#### Check Venue Health
Validate that a venue adapter is properly configured and reachable:
```bash [Terminal]
grimoire venue doctor --chain 1 --adapter uniswap --rpc-url YOUR_RPC_URL
```
#### Fetch Venue Data
Each venue has its own snapshot commands:
**Aave V3:**
```bash [Terminal]
grimoire venue aave health --chain 1 --address 0x...
grimoire venue aave reserves --chain 1 --asset USDC
```
**Morpho Blue:**
```bash [Terminal]
grimoire venue morpho-blue vaults --chain 8453 --asset USDC --min-tvl 5000000 --format spell
```
**Uniswap:**
```bash [Terminal]
grimoire venue uniswap routers --chain 1
```
**Pendle:**
```bash [Terminal]
grimoire venue pendle chains
grimoire venue pendle markets --chain 42161
```
**Hyperliquid:**
```bash [Terminal]
grimoire venue hyperliquid mids
grimoire venue hyperliquid book --asset ETH
```
**Polymarket:**
```bash [Terminal]
grimoire venue polymarket markets
grimoire venue polymarket book --market
grimoire venue polymarket midpoint --market
```
Use `--format spell` on supported commands to get output formatted for direct use in spell parameters.
## Advisory Decisions
Agents can write spells that include AI-powered decision points using `advise` blocks. This is how you embed judgment into a strategy while keeping it auditable.
### SmartRebalance Example
```spell [smart-rebalance.spell]
spell SmartRebalance {
advisors: {
risk: { model: "anthropic:haiku" }
}
venues: {
aave: @aave_v3
morpho: @morpho_blue
}
params: {
amount: 50000
}
on manual: {
decision = advise risk: "Given current gas costs and rate differential, should we rebalance?" {
output: { type: boolean }
timeout: 10
fallback: false
}
if decision {
aave.withdraw(USDC, params.amount)
morpho.lend(USDC, params.amount)
}
}
}
```
Advisory decisions have a typed schema, a timeout, and a fallback — so the spell always has a deterministic path even if the model is unavailable.
### Deterministic Replay
:::note
The fallback value ensures the spell always has a deterministic execution path, even if the advisory model is unavailable or times out.
:::
For deterministic replay of advisory decisions:
:::code-group
```bash [Record]
# Record decisions during simulation
grimoire simulate spells/smart-rebalance.spell --chain 1
```
```bash [Replay]
# Replay the same decisions for live execution
grimoire cast spells/smart-rebalance.spell \
--chain 1 \
--advisory-replay \
--key-env PRIVATE_KEY \
--rpc-url
```
:::
## Coding Agents
Grimoire is designed as a language for **AI agents** to write and execute. Spells have a structured, deterministic syntax that agents can author reliably — and skills give them the context they need to do it well.
### Install Skills
Skills give your coding agent (Claude Code, Cursor, Windsurf, etc.) full knowledge of Grimoire syntax, CLI commands, and venue adapters.
Install all skills with one command:
```bash [Terminal]
npx skills add https://github.com/franalgaba/grimoire
```
This installs:
| Skill | Purpose |
| ---------------------- | ------------------------------------------------------------- |
| `grimoire` | Spell authoring, CLI usage, validation, simulation, execution |
| `grimoire-aave` | Aave V3 market snapshots and reserve data |
| `grimoire-uniswap` | Uniswap V3/V4 router and pool metadata |
| `grimoire-morpho-blue` | Morpho Blue vault discovery |
| `grimoire-hyperliquid` | Hyperliquid mid prices and order books |
| `grimoire-pendle` | Pendle yield markets and assets |
| `grimoire-polymarket` | Polymarket CLOB order books and market data |
:::note
After installing, **restart your agent session** so the skills load.
:::
### How Agents Use Skills
The agent workflow follows the same safety pipeline as manual usage, but skills automate the research and authoring steps:
```
Prompt → Venue snapshot → Write spell → Validate → Simulate → Dry-run → Cast
```
1. **You describe what you want** in natural language
2. **The agent fetches live data** using venue skills (token addresses, pool info, rates)
3. **The agent writes a `.spell` file** using the syntax reference
4. **Validate and simulate** to verify correctness
5. **Dry-run before live execution** for safety
### Venue Snapshots with `--format spell`
:::tip
The `--format spell` flag is key for agents. It outputs venue data in a format that can be directly pasted into a spell's `params` block.
:::
```bash [Terminal]
grimoire venue morpho-blue vaults --chain 8453 --asset USDC --min-tvl 5000000 --format spell
```
```txt [Output]
params: {
vault_address: "0x..."
asset: "USDC"
tvl: 12500000
}
```
Agents use this to populate spells with live, accurate protocol data instead of hardcoding addresses.
### Preflight Checks
Before running venue actions, agents should verify adapter readiness:
```bash [Terminal]
grimoire venue doctor --adapter uniswap --chain 1 --rpc-url --json
grimoire venue doctor --adapter aave --chain 1 --rpc-url --json
```
This checks adapter registration, required environment variables, chain support, and RPC connectivity.
### Safe Execution for Agents
:::danger
Agents should **never skip to live cast** without running dry-run first, and should **always surface the dry-run results** to the user before proceeding.
:::
Agents must always follow the safe execution path — especially for spells that move value:
:::steps
#### Validate syntax and structure
```bash [Terminal]
grimoire validate spells/my-strategy.spell
```
#### Preview against live data
```bash [Terminal]
grimoire simulate spells/my-strategy.spell --chain 1
```
#### Dry-run the full pipeline without submitting
```bash [Terminal]
grimoire cast spells/my-strategy.spell --dry-run --chain 1 --key-env PRIVATE_KEY --rpc-url
```
#### Live execution (only after user confirmation)
```bash [Terminal]
grimoire cast spells/my-strategy.spell --chain 1 --key-env PRIVATE_KEY --rpc-url
```
:::
## Prompt Examples
Real-world prompts you can give your coding agent to write and execute Grimoire spells.
### Swap Tokens on Uniswap
> Create a spell that swaps 1000 USDC to ETH on Uniswap V3 on Ethereum mainnet.
The agent will:
1. Run `grimoire venue uniswap tokens --chain 1 --symbol USDC --format spell` to get token addresses
2. Write a spell with the `@uniswap_v3` adapter
3. Validate and simulate it
Result:
```spell [swap-usdc-to-eth.spell]
spell SwapUsdcToEth {
version: "0.1.0"
description: "Swap 1000 USDC to ETH via Uniswap V3"
venues: {
uniswap: @uniswap_v3
}
params: {
amount: 1000
}
on manual: {
uniswap.swap(USDC, ETH, params.amount)
}
}
```
### Lend on Aave
> Write a spell to lend 5000 USDC on Aave V3 on Ethereum. Add a guard so it only lends if the supply APY is above 3%.
The agent will:
1. Run `grimoire venue aave reserves --chain 1 --asset USDC --format spell` to get current rates
2. Write a spell with the `@aave_v3` adapter and a conditional check
3. Validate with `--strict` mode
```bash [Terminal]
grimoire venue aave reserves --chain 1 --asset USDC --format spell
```
### Yield Strategy Across Venues
> Create a strategy that checks Morpho Blue vault yields on Base, and if any USDC vault has over 5M TVL with a better rate than Aave, moves funds there.
The agent will:
1. Run `grimoire venue morpho-blue vaults --chain 8453 --asset USDC --min-tvl 5000000 --format spell`
2. Run `grimoire venue aave reserves --chain 8453 --asset USDC --format spell`
3. Write a spell that compares rates and conditionally moves funds
4. Use an `advise` block if judgment is needed for the comparison
```bash [Terminal]
grimoire venue morpho-blue vaults --chain 8453 --asset USDC --min-tvl 5000000 --format spell
grimoire venue aave reserves --chain 8453 --asset USDC --format spell
```
### Bridge and Swap
> Bridge 500 USDC from Ethereum to Base using Across, then swap to ETH on Uniswap.
The agent will write a cross-chain spell using the `@across` bridge adapter and the `@uniswap_v3` swap adapter with `--destination-chain` execution.
### Place a Hyperliquid Order
> Place a limit buy for 0.5 ETH at $2,000 on Hyperliquid.
The agent will:
1. Run `grimoire venue hyperliquid mids` to check current prices
2. Write a spell using the `@hyperliquid` offchain adapter
```bash [Terminal]
grimoire venue hyperliquid mids
```