@dev.sail.money/sailor 1.3.0-227 → 1.3.0-232
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/README.md +59 -498
- package/package.json +5 -5
- package/packages/cli/dist/index.cjs +0 -14
- package/packages/sdk/dist/fees.d.ts +2 -1
- package/packages/sdk/dist/fees.d.ts.map +1 -1
- package/packages/sdk/dist/fees.js +2 -1
- package/packages/sdk/dist/fees.js.map +1 -1
- package/packages/sdk/dist/intelligence.d.ts +1 -1
- package/packages/sdk/dist/intelligence.js +1 -1
- package/packages/sdk/package.json +2 -2
- package/templates/default/.agents/skills/sail-mandates/references/examples-index.md +1 -1
- package/templates/default/.agents/skills/sail-template-swap/SKILL.md +2 -2
- package/templates/default/.agents/skills/sail-template-swap-no-oracle/SKILL.md +2 -2
- package/templates/default/.agents/skills/sail-templates/SKILL.md +2 -2
- package/templates/default/docs/PERMISSION_MODEL.md +2 -2
- package/docs/PERMISSION_MODEL.md +0 -93
- package/examples/README.md +0 -24
- package/examples/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +0 -84
- package/examples/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +0 -97
- package/examples/lifi-permissions/README.md +0 -53
- package/scripts/check-docs.mjs +0 -309
- package/scripts/check-init.mjs +0 -123
- package/scripts/check-update.mjs +0 -177
- package/scripts/clean.mjs +0 -17
- /package/{examples → templates/default/examples}/custom-mandate/.sail/contracts/interfaces/IPermission.sol +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/README.md +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/foundry.toml +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/mandates/BoundedCallPermission.sol +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/mandates/README.md +0 -0
- /package/{examples → templates/default/examples}/custom-mandate/mandates/SailCalldata.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedApproveAndCallBatch.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedLimitless_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedPerp_GMXv2_Arbitrum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedStake_Venice_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSupply_AaveV3_Arbitrum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSwapNative_UniswapV3_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSwap_UniswapV3_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedSwap_UniswapV4_Unichain.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedTransfer_ERC20_Ethereum.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/BoundedVault_ERC4626_Base.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/README.md +0 -0
- /package/{examples → templates/default/examples}/permissions/SailCalldata.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/foundry.toml +0 -0
- /package/{examples → templates/default/examples}/permissions/interfaces/IBatchPermission.sol +0 -0
- /package/{examples → templates/default/examples}/permissions/interfaces/IPermission.sol +0 -0
package/AGENTS.md
CHANGED
|
@@ -14,7 +14,7 @@ tooling to create SMAs, register permission contracts, and run strategy agents.
|
|
|
14
14
|
| `packages/cli` | `sailor` | CLI: init, keys, account, mandate, onboard, station, ui, run, session, scan, status, owner, doctor, capabilities |
|
|
15
15
|
| `packages/ui` | `sailor-ui` | Local dashboard + browser-driven onboarding wizard (per-project port, 3333–3999) |
|
|
16
16
|
| `templates/default` | — | Default agent starter: neutral blank scaffold + Foundry workspace + onboarding guide (AGENTS.md) |
|
|
17
|
-
| `examples/custom-mandate` | — | Solidity reference: IPermission scaffold (not a project template) |
|
|
17
|
+
| `templates/default/examples/custom-mandate` | — | Solidity reference: IPermission scaffold (not a project template) |
|
|
18
18
|
|
|
19
19
|
## Protocol roles
|
|
20
20
|
|
package/README.md
CHANGED
|
@@ -1,85 +1,33 @@
|
|
|
1
1
|
# Sailor
|
|
2
2
|
|
|
3
|
-
> The
|
|
4
|
-
|
|
5
|
-
Sailor is the off-chain operator layer for [Sail Protocol](https://github.com/sail-money/SailProtocol): the tooling an operator uses to create a Separately Managed Account, register a mandate, and run a strategy agent against it. It wraps SailKernel dispatch, MandateFactory registration, and EIP-712 mandate signing behind a TypeScript SDK, a CLI, and a local dashboard. It does not deploy the protocol or author permission templates — those live in Sail Protocol. It targets already-deployed SailKernel instances and gives operators the tooling to drive them.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## What's inside
|
|
10
|
-
|
|
11
|
-
| Package | Name | Role |
|
|
12
|
-
|---|---|---|
|
|
13
|
-
| `packages/sdk` | `@sail.money/sdk` / `@sail.money/sailor/sdk` | TypeScript library: SailorClient, EIP-712 helpers, ABIs, deployment registry, chain registry |
|
|
14
|
-
| `packages/cli` | `@sail.money/sailor` | CLI for account setup, mandate signing, and agent execution |
|
|
15
|
-
| `packages/ui` | `sailor-ui` | Local dashboard (per-project port; see Dashboard below) |
|
|
16
|
-
| `templates/default` | — | The agent starter `sailor init` scaffolds: slim `AGENTS.md` + on-demand skills under `.agents/skills/` |
|
|
17
|
-
| `examples/permissions` | — | Worked permission contracts by protocol and chain (reference, unaudited) |
|
|
18
|
-
| `examples/custom-mandate` | — | Solidity reference: IPermission authoring scaffold |
|
|
19
|
-
| `examples/lifi-permissions` | — | Solidity reference: LiFi clone permission contracts (source of the clone implementations) |
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Protocol model
|
|
24
|
-
|
|
25
|
-
```mermaid
|
|
26
|
-
flowchart TD
|
|
27
|
-
Owner["**Owner**<br/>holds the Safe · signs the mandate"]
|
|
28
|
-
Manager["**Manager**<br/>agent · signs dispatches"]
|
|
29
|
-
SMA["**SMA**<br/>Safe · holds assets · executes"]
|
|
30
|
-
Mandate["**Mandate**<br/>set of permission contracts"]
|
|
31
|
-
Kernel["**Sail Kernel**<br/>evaluates permission · trusted core<br/>dispatches to Safe on success"]
|
|
32
|
-
|
|
33
|
-
Owner -- "01 deploys & owns" --> SMA
|
|
34
|
-
Owner -- "02 signs mandate (EIP-712)" --> Mandate
|
|
35
|
-
Owner -- "03 appoints · instant revocation" --> Manager
|
|
36
|
-
Manager -- "04 signs dispatch (EIP-712)" --> Kernel
|
|
37
|
-
Mandate -- "05 defines bounds" --> Kernel
|
|
38
|
-
Kernel -- "06 ✓ executes · ✗ outside mandate: reverts" --> SMA
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Sailor is the operator tooling that drives the Manager/dispatch and mandate-registration flows (steps 02–05).
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Roles
|
|
46
|
-
|
|
47
|
-
Sail Protocol separates three authority roles. Sailor operates all of them:
|
|
3
|
+
> The open-source toolkit — TypeScript SDK, CLI, and local dashboard — for operating agent-managed Separately Managed Accounts on [Sail Protocol](https://github.com/sail-money/protocol).
|
|
48
4
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| **Manager** | Executes dispatches within mandate bounds. Signs each dispatch. | The agent wallet — encrypted in `.sail/keys/manager.json` |
|
|
5
|
+
[](https://www.npmjs.com/package/@sail.money/sailor)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://github.com/sail-money/Sailor/actions/workflows/tests.yml)
|
|
8
|
+
[](https://nodejs.org)
|
|
54
9
|
|
|
55
|
-
|
|
10
|
+
## What you can build
|
|
56
11
|
|
|
57
|
-
|
|
12
|
+
An autonomous or semi-autonomous agent that manages capital inside a **self-custodial Safe**, bounded by **onchain permissions it cannot exceed**. The owner holds the Safe and signs a mandate — a set of permission contracts encoding exactly what the agent may do (which venues, which tokens, what size). The agent executes within those bounds; anything outside them is rejected by the SailKernel before it touches funds, and the owner can revoke the agent's dispatch rights instantly without moving assets. The trust model — what the contracts enforce versus what stays off-chain — is specified in the [Sail Protocol repo](https://github.com/sail-money/protocol) and the [whitepaper](https://github.com/sail-money/protocol/blob/main/docs/whitepaper/Sail_Protocol_Whitepaper.pdf).
|
|
58
13
|
|
|
59
|
-
|
|
14
|
+
## What's in the box
|
|
60
15
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Run `npx sailor init my-agent`, open the scaffolded folder in Claude Code, Cursor, or any AI coding assistant, and say **"start"**.
|
|
68
|
-
|
|
69
|
-
### How the assistant is guided
|
|
70
|
-
|
|
71
|
-
The scaffold follows the open [Agent Skills](https://agentskills.io) standard: a slim, always-loaded `AGENTS.md` carries the welcome flow, project-state map, and hard invariants, while detailed procedures live in seven on-demand skills under `.agents/skills/` (onboarding, project info, servers, transactions, mandates, CI, extensions). Assistants that scan skills load each one only when relevant; assistants that don't follow the routing table in `AGENTS.md` to the same plain-markdown files. Works in Claude Code, Cursor, Copilot, and Codex.
|
|
16
|
+
| Piece | What it does |
|
|
17
|
+
|---|---|
|
|
18
|
+
| **SDK** (`@sail.money/sailor/sdk`) | `SailorClient`, encrypted keyring, EIP-712 signing, dispatch submission, deployment + chain registries, template encoders |
|
|
19
|
+
| **CLI** (`sailor`) | Everything from `sailor init` to `sailor run`: keys, SMA deployment, mandate lifecycle, agent loop, doctor, session control |
|
|
20
|
+
| **Dashboard** (`sailor ui`) | Local web UI for onboarding, balances, mandate health, activity, and owner signing |
|
|
21
|
+
| **Scaffolded skills** | Step-by-step procedures under `.agents/skills/` that your AI coding assistant follows to set up and operate the agent |
|
|
72
22
|
|
|
73
|
-
|
|
23
|
+
**About the scaffold.** `sailor init` scaffolds your project from `templates/default/`, which ships two things together: the `.agents/skills` your assistant follows, and the **worked example permissions** (`templates/default/examples/` → your project's `examples/`) those skills teach from — protocol-specific bounding patterns (Uniswap, Aave, GMX, ERC-4626, and more) plus an `IPermission` authoring workspace. The examples are shipped teaching material inside every scaffold, not repo furniture.
|
|
74
24
|
|
|
75
25
|
## Installation
|
|
76
26
|
|
|
77
|
-
###
|
|
78
|
-
|
|
79
|
-
Create a folder, step into it, then install and init:
|
|
27
|
+
### npm
|
|
80
28
|
|
|
81
29
|
```bash
|
|
82
|
-
# bash / zsh
|
|
30
|
+
# bash / zsh (macOS, Linux)
|
|
83
31
|
mkdir my-agent && cd my-agent && npm i @sail.money/sailor && npx sailor init
|
|
84
32
|
```
|
|
85
33
|
|
|
@@ -88,476 +36,89 @@ mkdir my-agent && cd my-agent && npm i @sail.money/sailor && npx sailor init
|
|
|
88
36
|
mkdir my-agent ; cd my-agent ; npm i @sail.money/sailor ; npx sailor init
|
|
89
37
|
```
|
|
90
38
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
> **npx shortcut** — skips the explicit install; npm downloads sailor on the fly:
|
|
94
|
-
> ```sh
|
|
95
|
-
> mkdir my-agent && cd my-agent && npx sailor init
|
|
96
|
-
> ```
|
|
97
|
-
|
|
98
|
-
### Global CLI (for direct sailor commands)
|
|
99
|
-
|
|
100
|
-
```sh
|
|
101
|
-
npm install -g @sail.money/sailor
|
|
102
|
-
sailor init my-agent
|
|
103
|
-
```
|
|
39
|
+
Requires Node.js **>= 18**. For a global CLI instead: `npm install -g @sail.money/sailor`.
|
|
104
40
|
|
|
105
41
|
### Docker (no Node.js required)
|
|
106
42
|
|
|
107
|
-
Run sailor from a pre-built image — useful when you don't want to install Node.js or want an isolated environment:
|
|
108
|
-
|
|
109
43
|
```bash
|
|
110
44
|
mkdir my-agent && cd my-agent
|
|
111
45
|
docker run -d --name agent -P -v "${PWD}:/workspace" sailmoney/sailor
|
|
112
46
|
docker exec agent sailor init
|
|
113
47
|
```
|
|
114
48
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
---
|
|
49
|
+
Project files live on your host via the volume mount; prefix `sailor` commands with `docker exec agent`. Full details: [docs/docker.md](./docs/docker.md).
|
|
118
50
|
|
|
119
51
|
## Quickstart
|
|
120
52
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- Node.js 18+
|
|
124
|
-
- A wallet (MetaMask, Rabby, Phantom, and more)
|
|
125
|
-
- An RPC URL (e.g. Alchemy free tier)
|
|
126
|
-
- A supported chain: **Ethereum, Base, Arbitrum, Unichain, Base Sepolia, or Eth Sepolia** — verified deployments are bundled in `@sail.money/sailor`.
|
|
127
|
-
|
|
128
|
-
### Recommended — assistant-driven
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
# bash / zsh / macOS
|
|
132
|
-
mkdir my-agent && cd my-agent && npm i @sail.money/sailor && npx sailor init && npm install
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
```powershell
|
|
136
|
-
# PowerShell (Windows)
|
|
137
|
-
mkdir my-agent ; cd my-agent ; npm i @sail.money/sailor ; npx sailor init ; npm install
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Open this folder in Claude Code, Cursor, Codex, or any AI coding assistant and say **"start"**. The scaffolded `AGENTS.md` and its skills guide the assistant through the whole flow — SMA deployment, strategy definition, mandate authoring, running, and automation. No manual steps required.
|
|
141
|
-
|
|
142
|
-
### Direct CLI reference
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
# Discovery
|
|
146
|
-
sailor chains # list supported chains and kernel addresses
|
|
147
|
-
sailor capabilities # what you can build on this chain — read-only, no gas
|
|
148
|
-
sailor doctor # kernel model + RPC reachability + gas balances
|
|
149
|
-
|
|
150
|
-
# SMA setup
|
|
151
|
-
sailor account predict # compute deterministic SMA address before deploying
|
|
152
|
-
sailor onboard --new-sma # deploy SMA and optionally attach a mandate
|
|
153
|
-
|
|
154
|
-
# Mandate lifecycle
|
|
155
|
-
sailor mandate simulate # probe a permission off-chain (no gas) before registering
|
|
156
|
-
sailor mandate sign # sign the mandate — reconciles against live on-chain state
|
|
157
|
-
sailor mandate deploy # deploy a Foundry-compiled permission contract
|
|
158
|
-
sailor mandate attach # register a deployed permission on an SMA (or a comma-separated list, in one signature)
|
|
159
|
-
|
|
160
|
-
# Agent operation
|
|
161
|
-
sailor run --once # single tick — confirm it works before automating
|
|
162
|
-
sailor run # start the agent (continuous)
|
|
163
|
-
sailor keys export-ci # copy encrypted agent wallet to ci-keystore.json for CI
|
|
164
|
-
|
|
165
|
-
# Unattended execution
|
|
166
|
-
sailor service install # run as a local OS daemon (launchd/systemd/Task Scheduler), restarts on crash
|
|
167
|
-
sailor service status # whether the service is installed and running
|
|
168
|
-
sailor service logs -f # follow the agent log (.sail/agent.log)
|
|
169
|
-
sailor trigger github # fire the agent's GitHub Actions workflow on demand
|
|
170
|
-
|
|
171
|
-
# Dashboard
|
|
172
|
-
sailor ui start # prints the per-project dashboard URL
|
|
173
|
-
sailor ui start --expose tailscale # also expose it on your tailnet over HTTPS (see Dashboard section)
|
|
174
|
-
|
|
175
|
-
# Maintenance
|
|
176
|
-
sailor update # re-sync skills, AGENTS.md, and tooling files after a CLI upgrade
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
`sailor run` writes reverted transactions to stderr as `reverted: <txHash> (gas used: N)`; successful dispatches are appended to `.sail/activity.jsonl`.
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
## Templates
|
|
184
|
-
|
|
185
|
-
`sailor init` scaffolds a new agent project from a template. By default it
|
|
186
|
-
writes into the **current directory**; pass a name to create a subdirectory.
|
|
187
|
-
|
|
188
|
-
```bash
|
|
189
|
-
sailor init # scaffold into cwd
|
|
190
|
-
sailor init my-agent # create ./my-agent/ and scaffold there
|
|
191
|
-
sailor init --template default # explicit (same as default)
|
|
192
|
-
sailor init my-agent --template <name> # named subdirectory + specific template
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Available templates
|
|
196
|
-
|
|
197
|
-
| Template | Description |
|
|
198
|
-
|---|---|
|
|
199
|
-
| `default` | Neutral agent starter. Includes a blank agent loop, Foundry workspace for permission contracts, GitHub Actions cron job, and the operator guide (`AGENTS.md`). For a complete worked example see `examples/dca/`. **Default.** |
|
|
200
|
-
|
|
201
|
-
### What makes a valid template
|
|
202
|
-
|
|
203
|
-
A valid template is any directory under `templates/` that contains a
|
|
204
|
-
`package.json`. Solidity reference sources live under `examples/`
|
|
205
|
-
(`examples/permissions`, `examples/custom-mandate`, `examples/lifi-permissions`)
|
|
206
|
-
— they are not project scaffolds and never appear in the template list.
|
|
207
|
-
|
|
208
|
-
### Adding a template
|
|
209
|
-
|
|
210
|
-
1. Create a directory under `templates/<your-template-name>/`.
|
|
211
|
-
2. Add a `package.json` (the `name` field is patched to the project name on
|
|
212
|
-
init).
|
|
213
|
-
3. Add a `.sail/` workspace structure if the agent needs local state.
|
|
214
|
-
4. The template will appear automatically in `sailor init --template <name>`.
|
|
215
|
-
|
|
216
|
-
Template files are bundled into the published `sailor` npm package via the
|
|
217
|
-
`files` field in the root `package.json`.
|
|
218
|
-
|
|
219
|
-
---
|
|
220
|
-
|
|
221
|
-
## Dashboard (`sailor ui`)
|
|
222
|
-
|
|
223
|
-
The Sailor dashboard is a local React app. It shows live account state, mandate
|
|
224
|
-
health, signer balances, and recent activity — all read from the project's
|
|
225
|
-
`.sail/` directory with no hosted backend.
|
|
226
|
-
|
|
227
|
-
Each project gets its own deterministic port in the 3333–3999 range (derived
|
|
228
|
-
from the project path, so several projects can run dashboards side by side).
|
|
229
|
-
Use the URL the command prints, or read it from `.sail/runtime/ui.json` —
|
|
230
|
-
do not assume port 3333.
|
|
231
|
-
|
|
232
|
-
### Commands
|
|
233
|
-
|
|
234
|
-
```bash
|
|
235
|
-
sailor ui # start the dashboard (same as sailor ui start)
|
|
236
|
-
sailor ui start # start the dashboard and print its URL
|
|
237
|
-
sailor ui stop # stop the running dashboard
|
|
238
|
-
sailor ui status # show whether the dashboard is running + URL + pid
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### How it works
|
|
242
|
-
|
|
243
|
-
`sailor ui start` spawns a bundled Express server (`server.cjs`) that:
|
|
244
|
-
|
|
245
|
-
- Serves the pre-built React UI as static files on `/`
|
|
246
|
-
- Exposes a local API on `/api` that reads `.sail/` state from the current
|
|
247
|
-
working directory
|
|
248
|
-
|
|
249
|
-
The server PID is written to `.sail/runtime/ui.json` on start. `sailor ui stop`
|
|
250
|
-
reads that file, sends `SIGTERM` to the server process, and removes the file.
|
|
251
|
-
This means you can start the dashboard in one terminal and stop it from another.
|
|
252
|
-
|
|
253
|
-
### Running in the background
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
# macOS / Linux
|
|
257
|
-
sailor ui start &
|
|
258
|
-
sailor ui status # ● running http://localhost:<port> (pid 12345)
|
|
259
|
-
sailor ui stop # Stopped Sailor UI (pid 12345).
|
|
260
|
-
|
|
261
|
-
# Windows (PowerShell)
|
|
262
|
-
Start-Job { sailor ui start }
|
|
263
|
-
sailor ui status
|
|
264
|
-
sailor ui stop
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### Remote access over your tailnet (HTTPS) — optional
|
|
268
|
-
|
|
269
|
-
The dashboard is local-only by default. To reach it from another device (e.g. a
|
|
270
|
-
remote operator box), expose it over your [Tailscale](https://tailscale.com)
|
|
271
|
-
tailnet on HTTPS:
|
|
272
|
-
|
|
273
|
-
```bash
|
|
274
|
-
sailor ui start --expose tailscale
|
|
275
|
-
# → Sailor UI started at http://localhost:<port>
|
|
276
|
-
# → Exposed on your tailnet at https://<node>.<tailnet>.ts.net/
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
It uses `tailscale serve` (tailnet-private), **never `funnel`** — only devices on
|
|
280
|
-
your tailnet can reach it, not the public internet. `sailor ui stop` tears the
|
|
281
|
-
tailnet proxy down along with the local server.
|
|
282
|
-
|
|
283
|
-
Requirements:
|
|
284
|
-
|
|
285
|
-
- `tailscale` installed and logged in (`tailscale up`).
|
|
286
|
-
- Tailscale **Serve** enabled for your tailnet, plus **HTTPS certificates**
|
|
287
|
-
(admin console → DNS → Enable HTTPS). If Serve is disabled, the command prints
|
|
288
|
-
the enable link instead of reporting success.
|
|
289
|
-
|
|
290
|
-
When exposed, the tailnet origin is added to the dashboard's CORS allowlist
|
|
291
|
-
automatically. To allow additional origins (e.g. a custom HTTPS host in front of
|
|
292
|
-
the station), set a comma-separated list — the local origin is always allowed:
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
SAILOR_CORS_ORIGINS=https://hermes.example.ts.net,https://another.host
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
By default the UI server binds `127.0.0.1` (local only). To reach it from another
|
|
299
|
-
device **without** Tailscale — e.g. behind your own reverse proxy on a domain — bind
|
|
300
|
-
all interfaces and throttle the key-management endpoints:
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
SAILOR_HOST=0.0.0.0 # bind all interfaces (default 127.0.0.1)
|
|
304
|
-
SAILOR_TRUST_PROXY=1 # hops to your proxy (or an IP allowlist), so rate limits key on the real client IP
|
|
305
|
-
SAILOR_RATE_LIMIT_PER_MIN=100 # cap /api/signer + /api/onboard/generate-key (default 100)
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
Behind a reverse proxy, set `SAILOR_TRUST_PROXY` (usually `1`) — otherwise the rate
|
|
309
|
-
limiter sees only the proxy's IP and applies one shared bucket to all clients.
|
|
310
|
-
|
|
311
|
-
The key-management endpoints are **unauthenticated** — only expose them behind your
|
|
312
|
-
own auth (reverse-proxy basic-auth, or a private tailnet), never the open internet.
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
## Agent-driven onboarding & custom mandates
|
|
317
|
-
|
|
318
|
-
On any of the six supported chains, an agent can drive the whole setup through
|
|
319
|
-
a browser **signing station**. The station is a local HTTP + WebSocket daemon
|
|
320
|
-
that bridges the CLI and the owner's wallet: the agent never holds the owner
|
|
321
|
-
key — it pushes signing requests, the owner approves them in the browser, and
|
|
322
|
-
the agent submits the transactions it's allowed to.
|
|
53
|
+
The recommended path is assistant-driven: open the scaffolded folder in Claude Code, Cursor, Codex, or any AI coding assistant and say **"start"** — the scaffold's `AGENTS.md` and skills walk the assistant through everything below. The direct-CLI version of the same journey:
|
|
323
54
|
|
|
324
55
|
```bash
|
|
325
|
-
sailor
|
|
326
|
-
sailor station start & # signing daemon (serves the UI)
|
|
327
|
-
# owner opens the printed URL once and connects their wallet
|
|
328
|
-
sailor owner connect # detect & persist the owner
|
|
329
|
-
sailor scan # discover the owner's Safes + state
|
|
330
|
-
sailor onboard --new-sma # create an SMA + (optionally) attach a mandate
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
Agents author their own permission contracts and deploy them from the scaffolded
|
|
334
|
-
Foundry workspace (`mandates/`, with `@sail/interfaces/IPermission.sol` vendored
|
|
335
|
-
under `.sail/contracts/`):
|
|
336
|
-
|
|
337
|
-
```bash
|
|
338
|
-
forge build
|
|
339
|
-
sailor mandate deploy --contract MyMandate \
|
|
340
|
-
--args '["0xPermissionSigner", ["0xTarget"]]' \
|
|
341
|
-
--attach --sma 0xSafe
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
`deploy` emits a contract-creation signing request (the owner signs it in the
|
|
345
|
-
browser); the deployed address is read from the receipt and tracked in
|
|
346
|
-
`.sail/state/mandates.json`. `attach` reads the signer nonce, has the owner sign
|
|
347
|
-
a `RegisterPermission` EIP-712 message, then the agent submits
|
|
348
|
-
`kernel.registerPermission` with the exact registration fee. Every command takes
|
|
349
|
-
`--json` for headless agent use; set `SAIL_PASSPHRASE` to unlock the manager key
|
|
350
|
-
non-interactively.
|
|
351
|
-
|
|
352
|
-
`sailor mandate sign` reconciles against the live on-chain `getPermissions()` call
|
|
353
|
-
before building the mandate payload — permissions revoked on-chain are excluded even
|
|
354
|
-
if they remain in the local `.sail/state/mandates.json` (which is an append-only
|
|
355
|
-
historical record and is never modified by the reconciliation).
|
|
356
|
-
|
|
357
|
-
### GitHub Actions CI
|
|
358
|
-
|
|
359
|
-
The scaffolded `.github/workflows/agent-tick.yml` runs `sailor run --once` on a
|
|
360
|
-
cron schedule using `npm ci` (no pnpm required). Setup:
|
|
361
|
-
|
|
362
|
-
1. `sailor keys export-ci` — copies the encrypted agent wallet to `ci-keystore.json`
|
|
363
|
-
in the project root and allowlists it in `.gitignore`. The geth v3 keystore is
|
|
364
|
-
safe to commit; the raw private key is never exposed.
|
|
365
|
-
2. Commit `ci-keystore.json`, `.sail/account.json`, and `.sail/mandate.json`.
|
|
366
|
-
3. Add two repository secrets (Settings → Secrets → Actions):
|
|
367
|
-
- `SAIL_PASSPHRASE` — the passphrase that encrypts the agent wallet
|
|
368
|
-
- `RPC_URL` — your RPC endpoint
|
|
369
|
-
|
|
370
|
-
The workflow copies `ci-keystore.json` to `.sail/keys/manager.json`, then calls
|
|
371
|
-
`npx sailor run --once` with `SAIL_PASSPHRASE` set so the key is unlocked
|
|
372
|
-
non-interactively. No private key ever appears in the workflow file or in secrets.
|
|
373
|
-
|
|
374
|
-
---
|
|
56
|
+
npx sailor init my-agent && cd my-agent && npm install
|
|
375
57
|
|
|
376
|
-
|
|
58
|
+
# 1. Generate the agent's encrypted signing key (geth keystore v3 on disk)
|
|
59
|
+
sailor keys generate --type agent-wallet
|
|
377
60
|
|
|
378
|
-
|
|
61
|
+
# 2. Connect your wallet as owner, then deploy the SMA (a Safe) on-chain
|
|
62
|
+
sailor owner connect
|
|
63
|
+
sailor onboard --new-sma
|
|
379
64
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
```ts
|
|
387
|
-
import type { Agent, AgentContext, Dispatch } from '@sail.money/sailor/sdk'
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
The SDK is also published separately as `@sail.money/sdk` for projects that consume it independently of the CLI.
|
|
65
|
+
# 3. Give the agent a mandate — register + configure a shared permission
|
|
66
|
+
# template (swap, transfer, deposit, ...). The skills flow drives this
|
|
67
|
+
# conversationally; directly, it is register then configure:
|
|
68
|
+
sailor mandate attach --address <templateAddress> --sma <yourSMA>
|
|
69
|
+
sailor mandate configure --address <templateAddress> --template SwapPermission --args-file swap-config.json
|
|
391
70
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
Published to the public npm registry under the `@sail.money` scope.
|
|
395
|
-
|
|
396
|
-
| Trigger | Package | Version | dist-tag |
|
|
397
|
-
|---|---|---|---|
|
|
398
|
-
| Tag push (`v*`) | `@sail.money/sailor` | `1.2.0` | `latest` |
|
|
399
|
-
| Manual dispatch | `@dev.sail.money/sailor` | `1.2.0-42` | `dev` |
|
|
400
|
-
|
|
401
|
-
```bash
|
|
402
|
-
npm install @sail.money/sailor # latest stable (tag push)
|
|
71
|
+
# 4. Run the agent loop (or --once for a single tick)
|
|
72
|
+
sailor run --once
|
|
403
73
|
```
|
|
404
74
|
|
|
405
|
-
|
|
75
|
+
**See an action get blocked.** The fail-closed guarantee is testable before anything is at risk — probe the mandate off-chain with `sailor mandate simulate` (an `eth_call`; spends no gas, signs nothing):
|
|
406
76
|
|
|
407
77
|
```bash
|
|
408
|
-
|
|
78
|
+
sailor mandate simulate --address <templateAddress> \
|
|
79
|
+
--target <someContractOutsideYourMandate> \
|
|
80
|
+
--calldata 0xa9059cbb... --expect fail
|
|
409
81
|
```
|
|
410
82
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
### GitHub Packages (`publish.yml`)
|
|
83
|
+
Each probed call prints a verdict — `PASS`, `FAIL`, or `REVERT` — which is the permission contract's real `evaluate()` decision, exactly what the kernel consults on a live dispatch. A call outside your mandate shows `FAIL` (and `--expect fail` exits non-zero on a mismatch, so you can wire it into CI). At runtime the same protection reads: `sailor run` skips any planned call no registered permission accepts — logged to the console (`skipped: no registered permission authorizes call to <target>`) and to `.sail/activity.jsonl` as `dispatch_denied` — and if a transaction ever reaches the kernel outside its bounds, the kernel reverts it. Deny by default, at every layer.
|
|
414
84
|
|
|
415
|
-
|
|
85
|
+
Longer walkthrough, including revocation: [docs/getting-started.md](./docs/getting-started.md).
|
|
416
86
|
|
|
417
|
-
|
|
418
|
-
|---|---|---|
|
|
419
|
-
| Merge to `main` | `@sail-money/sailor` | `latest` |
|
|
420
|
-
| Manual dispatch | `@sail-money/sailor-dev` | `dev` |
|
|
421
|
-
|
|
422
|
-
Both builds require an alias since the package scope differs from `@sail.money`:
|
|
423
|
-
|
|
424
|
-
```bash
|
|
425
|
-
npm install "@sail.money/sailor@npm:@sail-money/sailor@latest" --registry https://npm.pkg.github.com
|
|
426
|
-
npm install "@sail.money/sailor@npm:@sail-money/sailor-dev@dev" --registry https://npm.pkg.github.com
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
Or pin in `package.json`:
|
|
430
|
-
|
|
431
|
-
```json
|
|
432
|
-
"dependencies": {
|
|
433
|
-
"@sail.money/sailor": "npm:@sail-money/sailor@latest"
|
|
434
|
-
}
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
```json
|
|
438
|
-
"dependencies": {
|
|
439
|
-
"@sail.money/sailor": "npm:@sail-money/sailor-dev@dev"
|
|
440
|
-
}
|
|
441
|
-
```
|
|
87
|
+
## How the assistant is guided (skills)
|
|
442
88
|
|
|
443
|
-
|
|
89
|
+
The scaffold follows the open [Agent Skills](https://agentskills.io) standard: a slim, always-loaded `AGENTS.md` carries the project map and hard invariants, while detailed procedures live in on-demand skills under `.agents/skills/` — onboarding, transactions, mandate authoring, shared-template configuration (one skill per template), automation, and more. Shared templates are registered and configured *through* the skills because the safe order of operations (register → configure → simulate → verify) is encoded there once, instead of re-derived by every assistant. Skills are plain markdown; assistants that don't scan skills follow the routing table in `AGENTS.md` to the same files. See [docs/templates-and-skills.md](./docs/templates-and-skills.md).
|
|
444
90
|
|
|
445
|
-
|
|
91
|
+
## Documentation
|
|
446
92
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
| Trigger | Tag |
|
|
93
|
+
| Doc | What's in it |
|
|
450
94
|
|---|---|
|
|
451
|
-
|
|
|
452
|
-
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
```bash
|
|
459
|
-
docker run -d --name agent -P -v "${PWD}:/workspace" sailmoney/sailor
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
- `-d` — detached, runs in the background
|
|
463
|
-
- `--name agent` — container name used in all `docker exec` calls
|
|
464
|
-
- `-P` — maps container ports (UI: 3334, station: 3141) to random host ports
|
|
465
|
-
- `-v "${PWD}:/workspace"` — mounts the current project into the container
|
|
466
|
-
|
|
467
|
-
#### Running sailor commands
|
|
468
|
-
|
|
469
|
-
All sailor commands run via `docker exec`:
|
|
470
|
-
|
|
471
|
-
```bash
|
|
472
|
-
docker exec agent sailor --version
|
|
473
|
-
docker exec agent sailor init
|
|
474
|
-
docker exec agent sailor ui start
|
|
475
|
-
docker exec agent sailor run --once
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
Project files are on your **local filesystem** — read and write them directly from local paths. Only `sailor` commands need the `docker exec` prefix; the volume mount makes files accessible to both sides.
|
|
479
|
-
|
|
480
|
-
#### Opening the dashboard
|
|
481
|
-
|
|
482
|
-
The UI always binds to port **3334 inside the container**, but the host-side port depends on how `-P` mapped it. Resolve it before opening the browser:
|
|
483
|
-
|
|
484
|
-
```bash
|
|
485
|
-
docker port agent 3334
|
|
486
|
-
# → 0.0.0.0:49201 (open http://localhost:49201 in the browser)
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
#### Stopping
|
|
490
|
-
|
|
491
|
-
```bash
|
|
492
|
-
docker stop agent # stop the container
|
|
493
|
-
docker start agent # restart it later (project files and state are on the host)
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
---
|
|
95
|
+
| [docs/getting-started.md](./docs/getting-started.md) | Long-form quickstart: install → first SMA → first mandate → first run → revocation |
|
|
96
|
+
| [docs/cli-reference.md](./docs/cli-reference.md) | The full `sailor` command surface, grouped by workflow |
|
|
97
|
+
| [docs/sdk-usage.md](./docs/sdk-usage.md) | `SailorClient` basics and every SDK subpath export, with examples |
|
|
98
|
+
| [docs/docker.md](./docs/docker.md) | Image, volumes, key handling, dashboard access, headless operation |
|
|
99
|
+
| [docs/templates-and-skills.md](./docs/templates-and-skills.md) | The shared-template catalog and how skills drive configuration and use |
|
|
100
|
+
| [docs/architecture.md](./docs/architecture.md) | The Sailor ↔ Sail Protocol boundary: what's onchain vs what this toolkit does |
|
|
497
101
|
|
|
498
102
|
## Security model
|
|
499
103
|
|
|
500
|
-
- The agent signs dispatches; the kernel evaluates the named permission on every call
|
|
501
|
-
- The Owner key controls the Safe and is never read by Sailor
|
|
502
|
-
- The manager key is encrypted on disk
|
|
503
|
-
- The session can be paused instantly
|
|
504
|
-
- All addresses
|
|
505
|
-
|
|
506
|
-
---
|
|
507
|
-
|
|
508
|
-
## State of the project
|
|
509
|
-
|
|
510
|
-
Sailor is functional and published as [`@sail.money/sailor`](https://www.npmjs.com/package/@sail.money/sailor) on npm (v1.2.0). The SDK, CLI, keystore, mandate flows, agent runner, and dashboard are implemented and have been exercised end to end.
|
|
104
|
+
- The agent signs dispatches; the **kernel evaluates the named permission on every call**. A permission returning false, reverting, or exceeding its gas cap is a denial — fail-closed.
|
|
105
|
+
- The **Owner key controls the Safe and is never read by Sailor**. Mandate registration requires a deliberate signature from the permission signer in the browser signing station.
|
|
106
|
+
- The **manager (agent) key is encrypted on disk** (geth keystore v3: scrypt + aes-128-ctr) and never transmitted.
|
|
107
|
+
- The session can be **paused instantly** (`sailor session pause` or the dashboard) — revoking dispatch rights without touching Safe custody.
|
|
108
|
+
- All addresses are EIP-55 normalized before any on-chain call or state write.
|
|
511
109
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
Shared permission templates (swap, swap-no-oracle, borrow, deposit, withdraw, transfer, approve-and-call-batch) are deployed and verified against the current kernel on every chain; they're populated as `knownTemplates` for all eleven chains in `packages/sdk/src/deployments.ts` (`standaloneTemplates` stays empty — it's the EIP-1167 clone-implementation registry, and these are shared multi-tenant templates).
|
|
515
|
-
|
|
516
|
-
---
|
|
110
|
+
Vulnerability reports: see [SECURITY.md](./SECURITY.md) (off-chain toolkit) — smart-contract issues go to the [protocol's policy](https://github.com/sail-money/protocol/blob/main/SECURITY.md).
|
|
517
111
|
|
|
518
112
|
## Deployments
|
|
519
113
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
### Core addresses (identical on all 11 chains)
|
|
523
|
-
|
|
524
|
-
| Contract | Address |
|
|
525
|
-
|---|---|
|
|
526
|
-
| SailKernel | `0x38b508756c976e876EFF05a29E731A4d348BA6ED` |
|
|
527
|
-
| SailGovernance | `0x4315B37cA4A315A7042af1Fcb37F8436f4D24356` |
|
|
528
|
-
| TimelockController | `0xC1E5F9A581D4100Aa949f80204540a33aD97A7b6` |
|
|
529
|
-
| MandateFactory | `0x6d2C802ffa0d9A8Ed69A5Bf22c1b63ccB566B8Fc` |
|
|
530
|
-
| StandardFeePolicy | `0x1087312447C8a2BfA15EB9cE23590E3502DBA04b` |
|
|
531
|
-
| SafeModuleEnabler | `0x7897Cb53a4be4a2eaAf46D60573C4Fd83b33fE1F` |
|
|
532
|
-
| Deployer | `0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6` |
|
|
533
|
-
| Treasury | `0x7b37F85575F1568a37dBA342BC5FE6d393F0872f` |
|
|
114
|
+
The SDK bundles verified deployments for **11 chains** — mainnets: Ethereum (1), Base (8453), Arbitrum (42161), Optimism (10), Unichain (130), BSC (56), World Chain (480), HyperEVM (999), MegaETH (4326); testnets: Base Sepolia (84532), Ethereum Sepolia (11155111). Every core contract sits at the same address on every chain via CREATE2 (SailKernel: `0x38b508756c976e876EFF05a29E731A4d348BA6ED`), and the seven shared permission templates (swap, swap-no-oracle, borrow, deposit, withdraw, transfer, approve-and-call-batch) are deployed and registered as `knownTemplates` on all of them. Query it yourself: `sailor chains` or `getSailDeployment(chainId)` from the SDK; the canonical record is the protocol repo's [deployments/addresses.md](https://github.com/sail-money/protocol/blob/main/deployments/addresses.md).
|
|
534
115
|
|
|
535
|
-
These
|
|
536
|
-
|
|
537
|
-
### Supported chains
|
|
538
|
-
|
|
539
|
-
| Chain | Chain ID |
|
|
540
|
-
|---|---|
|
|
541
|
-
| Ethereum | 1 |
|
|
542
|
-
| Base | 8453 |
|
|
543
|
-
| Arbitrum | 42161 |
|
|
544
|
-
| Optimism | 10 |
|
|
545
|
-
| Unichain | 130 |
|
|
546
|
-
| BSC | 56 |
|
|
547
|
-
| World Chain | 480 |
|
|
548
|
-
| HyperEVM | 999 |
|
|
549
|
-
| MegaETH | 4326 |
|
|
550
|
-
| Base Sepolia | 84532 |
|
|
551
|
-
| Eth Sepolia | 11155111 |
|
|
552
|
-
|
|
553
|
-
---
|
|
116
|
+
These deployments are under an ongoing external **security review** by [Octane](https://octane.security) and are not final — do not use them with funds you are not prepared to lose.
|
|
554
117
|
|
|
555
118
|
## Contributing
|
|
556
119
|
|
|
557
|
-
Sailor
|
|
558
|
-
|
|
559
|
-
---
|
|
120
|
+
Sailor will be continuously enhanced through community participation and feedback — contributions, issue reports, and design discussions are actively welcomed. Start with [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
560
121
|
|
|
561
122
|
## License
|
|
562
123
|
|
|
563
|
-
MIT
|
|
124
|
+
[MIT](./LICENSE) © Agentic Finance Inc.
|