@dev.sail.money/sailor 1.3.0-95 → 1.3.0-98
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 +3 -0
- package/package.json +2 -3
- package/packages/cli/dist/index.cjs +168 -76
- package/packages/cli/dist/server.cjs +57 -63
- package/packages/sdk/dist/abis/SailGovernance.d.ts +6 -5
- package/packages/sdk/dist/abis/SailGovernance.d.ts.map +1 -1
- package/packages/sdk/dist/abis/SailGovernance.js +6 -5
- package/packages/sdk/dist/abis/SailGovernance.js.map +1 -1
- package/packages/sdk/dist/fees.d.ts +58 -10
- package/packages/sdk/dist/fees.d.ts.map +1 -1
- package/packages/sdk/dist/fees.js +73 -41
- package/packages/sdk/dist/fees.js.map +1 -1
- package/packages/sdk/dist/index.d.ts +2 -1
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +1 -1
- package/packages/sdk/dist/index.js.map +1 -1
- package/packages/sdk/dist/intelligence.d.ts +7 -2
- package/packages/sdk/dist/intelligence.d.ts.map +1 -1
- package/packages/sdk/dist/intelligence.js +2 -2
- package/packages/sdk/dist/intelligence.js.map +1 -1
- package/packages/sdk/dist/signing.d.ts +14 -0
- package/packages/sdk/dist/signing.d.ts.map +1 -1
- package/packages/ui/dist/assets/{add-CLs0-B0p.js → add-BX5reKtK.js} +1 -1
- package/packages/ui/dist/assets/{all-wallets-CDOk28sj.js → all-wallets-IZ3PlVF-.js} +1 -1
- package/packages/ui/dist/assets/{app-store-DVzpi1qN.js → app-store-ARgRdMdF.js} +1 -1
- package/packages/ui/dist/assets/{apple-C9U9iH1l.js → apple-VCaqsI9w.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-DjQ4jGMe.js → arrow-bottom-Cwptw8fW.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-circle-jxial9Si.js → arrow-bottom-circle-h5vFiZ2I.js} +1 -1
- package/packages/ui/dist/assets/{arrow-left-BjAyI8D1.js → arrow-left-bM1TRcV9.js} +1 -1
- package/packages/ui/dist/assets/{arrow-right-BlFO4Tcx.js → arrow-right-BYd_N4Jr.js} +1 -1
- package/packages/ui/dist/assets/{arrow-top-DJ3oh3DH.js → arrow-top-CLUnwVE2.js} +1 -1
- package/packages/ui/dist/assets/{bank-B98it1qN.js → bank-6c28yOM9.js} +1 -1
- package/packages/ui/dist/assets/{basic-DsgeyPNu.js → basic-CJnbTfSd.js} +1 -1
- package/packages/ui/dist/assets/{browser-j4vCeHwE.js → browser-CDKlxM3D.js} +1 -1
- package/packages/ui/dist/assets/{card-CzxbMvEd.js → card-DQdED02q.js} +1 -1
- package/packages/ui/dist/assets/{ccip-U9yiu_EK.js → ccip-BL7RIPfY.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-D5sWBbk3.js → checkmark-JoRNVoFV.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-bold-BW6w3KCC.js → checkmark-bold-B6bGHVIs.js} +1 -1
- package/packages/ui/dist/assets/{chevron-bottom-BbHhmTQq.js → chevron-bottom-BMCelIEu.js} +1 -1
- package/packages/ui/dist/assets/{chevron-left-D8BDH4Wo.js → chevron-left-ryPLhHCc.js} +1 -1
- package/packages/ui/dist/assets/{chevron-right-BQuQk5zc.js → chevron-right-CdDNRv7f.js} +1 -1
- package/packages/ui/dist/assets/{chevron-top-1oeSXkx4.js → chevron-top-BxWIjjGk.js} +1 -1
- package/packages/ui/dist/assets/{chrome-store-B1OMtzC-.js → chrome-store-D-fiJ9qJ.js} +1 -1
- package/packages/ui/dist/assets/{clock-e0HueehS.js → clock-xCPkzwjj.js} +1 -1
- package/packages/ui/dist/assets/{close-Cy1ytr26.js → close-BkqmPpWG.js} +1 -1
- package/packages/ui/dist/assets/{coinPlaceholder-DqJu3ZPV.js → coinPlaceholder-PIvN9oq_.js} +1 -1
- package/packages/ui/dist/assets/{compass-XDz_N2Hg.js → compass-CW5kWcxW.js} +1 -1
- package/packages/ui/dist/assets/{copy-DmDo3Nob.js → copy-DUZlAQJJ.js} +1 -1
- package/packages/ui/dist/assets/{core-DbkMGSYW.js → core-von2c1sc.js} +3 -3
- package/packages/ui/dist/assets/cursor-BzRVY7BD.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-DF2aA10D.js → cursor-transparent-BUAMB0G1.js} +1 -1
- package/packages/ui/dist/assets/{desktop-CVydOWLn.js → desktop-BxdlwV8P.js} +1 -1
- package/packages/ui/dist/assets/{disconnect-BuN2Whnz.js → disconnect-GelNh3mn.js} +1 -1
- package/packages/ui/dist/assets/{discord-DMNPvTB2.js → discord-N0jnxkzC.js} +1 -1
- package/packages/ui/dist/assets/{etherscan-CacW-93f.js → etherscan-B41u7wF4.js} +1 -1
- package/packages/ui/dist/assets/{events-CZkVDFih.js → events-C9icG2YB.js} +1 -1
- package/packages/ui/dist/assets/{exclamation-triangle-B26hIvqO.js → exclamation-triangle-BWJC56FC.js} +1 -1
- package/packages/ui/dist/assets/{extension-B7rI0gv7.js → extension-G6I6oogw.js} +1 -1
- package/packages/ui/dist/assets/{external-link-CX8skCbH.js → external-link-BPaGQf4a.js} +1 -1
- package/packages/ui/dist/assets/{facebook-BDqbE6kl.js → facebook-47twy32b.js} +1 -1
- package/packages/ui/dist/assets/{fallback-DWQYKf3l.js → fallback-BTfJeGjh.js} +1 -1
- package/packages/ui/dist/assets/{farcaster-zQ3oQzZ8.js → farcaster-DYqnqCqs.js} +1 -1
- package/packages/ui/dist/assets/{filters-DCglZYsM.js → filters-dF6xeJnE.js} +1 -1
- package/packages/ui/dist/assets/{github-BH-BYjss.js → github-DbW4Ihz2.js} +1 -1
- package/packages/ui/dist/assets/{google-DYFWxZbC.js → google-TKm7G8LF.js} +1 -1
- package/packages/ui/dist/assets/{help-circle-BXH_DtZ_.js → help-circle-CY3qTmsG.js} +1 -1
- package/packages/ui/dist/assets/{id-Dr2yTeX1.js → id-JpHW4q14.js} +1 -1
- package/packages/ui/dist/assets/{image-DeJey1Eg.js → image-Dip2fG98.js} +1 -1
- package/packages/ui/dist/assets/{index-BP-UuQ8g.js → index-BGJ_8fMk.js} +1 -1
- package/packages/ui/dist/assets/{index-C55-Ne92.js → index-Bq3PAopp.js} +1 -1
- package/packages/ui/dist/assets/{index-BksbyFjf.js → index-C4_cA5XW.js} +1 -1
- package/packages/ui/dist/assets/{index-uSdXE5b_.js → index-CaDN0gL4.js} +1 -1
- package/packages/ui/dist/assets/index-DLElIcBr.js +1789 -0
- package/packages/ui/dist/assets/index-lhNfD4jA.css +1 -0
- package/packages/ui/dist/assets/{index-DVjAiPHI.js → index-q0mGElxZ.js} +3 -3
- package/packages/ui/dist/assets/{index.es-dZlNPpfR.js → index.es-BaCKS_tW.js} +4 -4
- package/packages/ui/dist/assets/{info-B91pD5Rw.js → info-B1enFsqh.js} +1 -1
- package/packages/ui/dist/assets/{info-circle-CySl3_on.js → info-circle-D4j3FISs.js} +1 -1
- package/packages/ui/dist/assets/{lightbulb-wwG8LQLo.js → lightbulb-DZbKr-vS.js} +1 -1
- package/packages/ui/dist/assets/{mail-D617YZ8y.js → mail-D-TO_uVQ.js} +1 -1
- package/packages/ui/dist/assets/{metamask-sdk-RbLbxUgF.js → metamask-sdk-DljW3QD1.js} +1 -1
- package/packages/ui/dist/assets/{mobile-CD9KlA0m.js → mobile-Bkmwzav2.js} +1 -1
- package/packages/ui/dist/assets/{more-BQ_rpPXo.js → more-D1_I_jiB.js} +1 -1
- package/packages/ui/dist/assets/{network-placeholder-BA7nl9e6.js → network-placeholder-DUaFjoXh.js} +1 -1
- package/packages/ui/dist/assets/{nftPlaceholder-D1EaaeDn.js → nftPlaceholder-Cc0iUryh.js} +1 -1
- package/packages/ui/dist/assets/{off-DnGG35_w.js → off-BvX71sse.js} +1 -1
- package/packages/ui/dist/assets/{parseSignature-E29x8poM.js → parseSignature-BAS-wKoj.js} +1 -1
- package/packages/ui/dist/assets/{play-store-C5u2FvYB.js → play-store-XzLbtbTd.js} +1 -1
- package/packages/ui/dist/assets/{plus-CM4xJkvI.js → plus-B77_RmYR.js} +1 -1
- package/packages/ui/dist/assets/{qr-code-kM3FUIdR.js → qr-code-BNeIhB1d.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-DWrRWIBM.js → recycle-horizontal-B9sX-yty.js} +1 -1
- package/packages/ui/dist/assets/{refresh-CztbjK2d.js → refresh-BWRygnjm.js} +1 -1
- package/packages/ui/dist/assets/{reown-logo-DUHEIodF.js → reown-logo-DCAEsGFm.js} +1 -1
- package/packages/ui/dist/assets/{search-BJtb4mn1.js → search-ZXIqrawS.js} +1 -1
- package/packages/ui/dist/assets/{secp256k1-BjrTZpQx.js → secp256k1-Doz05h4g.js} +1 -1
- package/packages/ui/dist/assets/{send-B3_kavG1.js → send-BQcO0jNC.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontal-BrF9POiv.js → swapHorizontal-4yZEzz2K.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalBold-Dgf8OjXj.js → swapHorizontalBold-DxBKu3sl.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalMedium-C6wX0JZj.js → swapHorizontalMedium-DAQYJ2JK.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-DTAVw6oF.js → swapHorizontalRoundedBold-CUlZzFJ6.js} +1 -1
- package/packages/ui/dist/assets/{swapVertical-KGlTFNoi.js → swapVertical-CjWHAaDM.js} +1 -1
- package/packages/ui/dist/assets/{telegram-DnLrK-4y.js → telegram-JBeabiJP.js} +1 -1
- package/packages/ui/dist/assets/{three-dots-C6_oMJfw.js → three-dots-D3R8OjSx.js} +1 -1
- package/packages/ui/dist/assets/{twitch-DvPqPD4f.js → twitch-1f9z7xVO.js} +1 -1
- package/packages/ui/dist/assets/{twitterIcon-BZdk82Am.js → twitterIcon-BW7n2xnp.js} +1 -1
- package/packages/ui/dist/assets/{verify-CbESD5G0.js → verify-Cs5owI38.js} +1 -1
- package/packages/ui/dist/assets/{verify-filled-BRjTrLxw.js → verify-filled-Ci5sx5qS.js} +1 -1
- package/packages/ui/dist/assets/{w3m-modal-D9b2TGHc.js → w3m-modal-DnWtss8u.js} +1 -1
- package/packages/ui/dist/assets/{wallet-B87E5UId.js → wallet-MaGNqaW-.js} +1 -1
- package/packages/ui/dist/assets/{wallet-placeholder-DmssSbYf.js → wallet-placeholder-kTOy12_L.js} +1 -1
- package/packages/ui/dist/assets/{walletconnect-CZkLKWMZ.js → walletconnect-CyuP92jg.js} +1 -1
- package/packages/ui/dist/assets/{warning-circle-BPTpHB1P.js → warning-circle-BImUCdpG.js} +1 -1
- package/packages/ui/dist/assets/{x-D_dEtEDU.js → x-II45JHpV.js} +1 -1
- package/packages/ui/dist/index.html +2 -2
- package/scripts/check-docs.mjs +1 -1
- package/templates/default/.agents/skills/sail-mandates/SKILL.md +12 -0
- package/templates/default/.agents/skills/sail-onboarding/SKILL.md +33 -34
- package/templates/default/.agents/skills/sail-overview/SKILL.md +100 -0
- package/templates/default/.agents/skills/sail-project-info/SKILL.md +2 -0
- package/templates/default/.agents/skills/sail-sailor/SKILL.md +190 -0
- package/templates/default/.agents/skills/sail-setup/SKILL.md +38 -0
- package/templates/default/.gitlab-ci.yml +58 -0
- package/templates/default/AGENTS.md +12 -87
- package/packages/cli/dist/mcp.cjs +0 -15534
- package/packages/ui/dist/assets/cursor-DRFqL8nZ.js +0 -3
- package/packages/ui/dist/assets/index-D6_Zei-R.js +0 -1790
- package/packages/ui/dist/assets/index-DZ2C2rHq.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{F as l}from"./core-
|
|
1
|
+
import{F as l}from"./core-von2c1sc.js";import"./index-DLElIcBr.js";import"./events-C9icG2YB.js";import"./index.es-BaCKS_tW.js";import"./fallback-BTfJeGjh.js";const o=l`<svg fill="none" viewBox="0 0 96 67">
|
|
2
2
|
<path
|
|
3
3
|
fill="currentColor"
|
|
4
4
|
d="M25.32 18.8a32.56 32.56 0 0 1 45.36 0l1.5 1.47c.63.62.63 1.61 0 2.22l-5.15 5.05c-.31.3-.82.3-1.14 0l-2.07-2.03a22.71 22.71 0 0 0-31.64 0l-2.22 2.18c-.31.3-.82.3-1.14 0l-5.15-5.05a1.55 1.55 0 0 1 0-2.22l1.65-1.62Zm56.02 10.44 4.59 4.5c.63.6.63 1.6 0 2.21l-20.7 20.26c-.62.61-1.63.61-2.26 0L48.28 41.83a.4.4 0 0 0-.56 0L33.03 56.21c-.63.61-1.64.61-2.27 0L10.07 35.95a1.55 1.55 0 0 1 0-2.22l4.59-4.5a1.63 1.63 0 0 1 2.27 0L31.6 43.63a.4.4 0 0 0 .57 0l14.69-14.38a1.63 1.63 0 0 1 2.26 0l14.69 14.38a.4.4 0 0 0 .57 0l14.68-14.38a1.63 1.63 0 0 1 2.27 0Z"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{F as r}from"./core-
|
|
1
|
+
import{F as r}from"./core-von2c1sc.js";import"./index-DLElIcBr.js";import"./events-C9icG2YB.js";import"./index.es-BaCKS_tW.js";import"./fallback-BTfJeGjh.js";const a=r`<svg fill="none" viewBox="0 0 20 20">
|
|
2
2
|
<path
|
|
3
3
|
fill="currentColor"
|
|
4
4
|
d="M11 6.67a1 1 0 1 0-2 0v2.66a1 1 0 0 0 2 0V6.67ZM10 14.5a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5Z"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{F as l}from"./core-
|
|
1
|
+
import{F as l}from"./core-von2c1sc.js";import"./index-DLElIcBr.js";import"./events-C9icG2YB.js";import"./index.es-BaCKS_tW.js";import"./fallback-BTfJeGjh.js";const a=l`<svg fill="none" viewBox="0 0 41 40">
|
|
2
2
|
<g clip-path="url(#a)">
|
|
3
3
|
<path fill="#000" d="M.8 0h40v40H.8z" />
|
|
4
4
|
<path
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="theme-color" content="#040b16" />
|
|
7
7
|
<title>Sail - Unlocking Personalized Money</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DLElIcBr.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-lhNfD4jA.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/scripts/check-docs.mjs
CHANGED
|
@@ -253,7 +253,7 @@ function main() {
|
|
|
253
253
|
const line = lineRaw.trim();
|
|
254
254
|
|
|
255
255
|
// ── CLI: `sailor <word1> [<word2>]` ──────────────────────────────────
|
|
256
|
-
for (const m of line.matchAll(
|
|
256
|
+
for (const m of line.matchAll(/(?<![\/@])\bsailor\s+([a-z][\w-]*)(?:\s+([a-z][\w-]*))?/g)) {
|
|
257
257
|
const [, w1, w2] = m;
|
|
258
258
|
const two = w2 ? `${w1} ${w2}` : null;
|
|
259
259
|
if (cli.leaves.has(w1) || (two && cli.leaves.has(two))) continue; // top-level leaf
|
|
@@ -94,6 +94,18 @@ Only now is the permission live. The owner (mandate signer) signs in the browser
|
|
|
94
94
|
|
|
95
95
|
When a strategy needs several permissions (e.g. a bounded-approve alongside the protocol permission), attach them all at once by passing a comma-separated list of addresses — the registration approvals collapse to a **single** browser signature via the kernel's `registerPermissions`. The earlier per-contract deploy approvals (Gate 5) are separate and unavoidable. A single permission attaches exactly as before with `--address <one>`.
|
|
96
96
|
|
|
97
|
+
## Registration fee
|
|
98
|
+
|
|
99
|
+
Registering a permission charges a **per-permission fee**, paid on-chain by the agent wallet at the moment of registration. It is a public protocol parameter — `permissionRegistrationFee()` on `SailGovernance` — read **live from the chain**, never hardcoded: it is `0` on the current deploy and higher in production, and the same flow surfaces whichever value the connected chain returns.
|
|
100
|
+
|
|
101
|
+
- **A mandate is a SET of permissions, so a mandate of N permissions costs `N × fee`.** Three permissions at `0.00001 ETH` each cost `0.00003 ETH` total.
|
|
102
|
+
- **When it's charged:** once per permission, on registration (the `attach` / `deploy-clone` step). Already-registered permissions are not re-charged when you re-run `sailor mandate sign`. Revoking does not refund.
|
|
103
|
+
- **Disclosure before signing:** `sailor mandate prepare` reads the live fee and records it in the draft, and `sailor mandate sign` prints `Registration fee: <total> ETH (<N> permissions × <fee> ETH)` before you confirm. The browser sign-time screen shows the same total.
|
|
104
|
+
- **Preflight:** before requesting the owner's signature, the agent wallet's ETH balance is checked against the total fee; an underfunded wallet fails early with `Insufficient ETH for the <X> ETH registration fee` instead of an on-chain revert. **Fund the agent wallet before attaching.**
|
|
105
|
+
- **Recorded:** each `permission_registered` activity entry carries the fee actually paid (`fee` in wei, `feeEth` formatted), so Recent Activity shows the real cost.
|
|
106
|
+
|
|
107
|
+
The fee is read via `readPermissionRegistrationFee()` in `packages/sdk/src/fees.ts` and applied as `fee × N` — the same number used for disclosure, the preflight, the tx `value`, and the activity record.
|
|
108
|
+
|
|
97
109
|
## Maintenance
|
|
98
110
|
|
|
99
111
|
- `sailor mandate revoke --address <P> --sma <SMA> --json` (or `--all`) — owner signs `RevokePermissions` in the browser (BLOCKS); agent submits. Revocations are recorded to the activity log; `state/mandates.json` keeps the historical record.
|
|
@@ -5,47 +5,46 @@ description: Walks the agent through setting up a new Sailor project or resuming
|
|
|
5
5
|
|
|
6
6
|
# Sail onboarding
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## First contact
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
On the user's first message (or after `sailor init` completes), present the full onboarding overview below — do NOT launch the UI yet. The goal is for the user to understand every stage before committing.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- `"docker"` — sailor runs in a container. Read `containerName` from the same config. Prefix every command:
|
|
14
|
-
`docker exec <containerName> sailor <command>`
|
|
15
|
-
Project files are on your **local filesystem** (mounted at `/workspace` inside the container) — read and write them normally from local paths. Do NOT use `docker exec` to read files; the volume mount makes them directly accessible.
|
|
16
|
-
|
|
17
|
-
### Starting the Docker container
|
|
18
|
-
|
|
19
|
-
If the container is not running, start it from the project root:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
docker run -d --name agent -P -v "${PWD}:/workspace" sailmoney/sailor
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
- `-d` — detached, runs in the background
|
|
26
|
-
- `--name agent` — names the container; use a different name with `-e SAILOR_CONTAINER_NAME=<name>` if needed
|
|
27
|
-
- `-P` — publishes all exposed ports to random available host ports (UI: 3334, station: 3141)
|
|
28
|
-
- `-v "${PWD}:/workspace"` — mounts the current project directory into the container
|
|
12
|
+
---
|
|
29
13
|
|
|
30
|
-
|
|
14
|
+
> **Sail Protocol** is infrastructure for onchain Separately Managed Accounts (SMAs) run by AI agents. You keep full custody; the agent acts only within cryptographically-bound permissions you approve and can always revoke. It cannot exceed them.
|
|
15
|
+
>
|
|
16
|
+
> Here is the complete path. Read it before we begin — each stage requires something from you.
|
|
17
|
+
>
|
|
18
|
+
> ---
|
|
19
|
+
>
|
|
20
|
+
> **Stage 1 — Deploy your SMA and create your agent wallet**
|
|
21
|
+
> We open a browser interface where you connect your owner wallet (MetaMask or any WalletConnect wallet), choose your chain, and deploy your SMA — a smart contract account you own. We also create a separate agent wallet: a signing key the agent uses to submit transactions on your behalf. Both wallets need gas. The owner wallet signs the deployment; the agent wallet pays for everything after that.
|
|
22
|
+
>
|
|
23
|
+
> **Stage 2 — Define your strategy**
|
|
24
|
+
> You tell me what you want the agent to do: which protocol, which tokens, what conditions, what limits. I help you separate the constraints that must be enforced on-chain (amount caps, venue allowlists, slippage floors) from the ones that live in agent logic (cadence, schedule, timing). Nothing is deployed yet — this is design.
|
|
25
|
+
>
|
|
26
|
+
> **Stage 3 — Build, test, and sign your mandate**
|
|
27
|
+
> I write the Solidity permission contracts that encode the strategy bounds from Stage 2. You review them. We run Foundry tests against your actual strategy parameters (must-pass and must-fail cases). We deploy the contracts on-chain and simulate them before you sign anything. You authorize the permission set in the browser — one signature. After this, the agent can act autonomously within those bounds.
|
|
28
|
+
>
|
|
29
|
+
> **Stage 4 — Run your agent**
|
|
30
|
+
> We run the agent locally first (`sailor run --once`) to confirm a full tick works. Then we automate it — GitHub Actions, a self-hosted runner, a local daemon, or Docker — matched to your latency needs and infrastructure comfort.
|
|
31
|
+
>
|
|
32
|
+
> **Stage 5 — Extend**
|
|
33
|
+
> Once the agent is live, I offer to add run and transaction notifications (Telegram, email) and a strategy-specific dashboard. This is optional, but I will offer it — you opt out explicitly if you don't want it.
|
|
34
|
+
>
|
|
35
|
+
> ---
|
|
36
|
+
>
|
|
37
|
+
> Ready to begin? Say **start** and I'll open the setup interface in your browser for Stage 1.
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
docker port agent 3334
|
|
34
|
-
# → 0.0.0.0:49201 (use 49201, not 3334, in the browser URL)
|
|
35
|
-
```
|
|
39
|
+
---
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
After the user says "start" (or "ready" or any affirmative), THEN run `sailor ui start` — the explanation and the UI launch are two separate beats. Do not skip the explanation. If the user's first message is an npm install command, run it, then present the overview immediately after.
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
docker exec agent sailor --version
|
|
41
|
-
docker exec agent sailor init
|
|
42
|
-
docker exec agent sailor ui start
|
|
43
|
-
docker exec agent sailor station start --json &
|
|
44
|
-
```
|
|
43
|
+
## Running sailor commands
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
Before running any command, check how sailor is installed — see **sail-sailor** for the full guide (local vs Docker, `installMode` detection, `docker exec` prefix, `--json` flag, `SAIL_PASSPHRASE`).
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
Short version: read `.sail/config.json → installMode`. If `"docker"`, prefix every command with `docker exec <containerName>`. If `"local"` or absent, run `sailor <command>` directly.
|
|
49
48
|
|
|
50
49
|
Stage machine keyed off `.sail/`. Read the state, enter at the right stage, never re-run completed stages.
|
|
51
50
|
|
|
@@ -104,7 +103,7 @@ If `deploy-chain` refuses with an address mismatch, the SMA was deployed against
|
|
|
104
103
|
## Gas requirements
|
|
105
104
|
|
|
106
105
|
- Owner wallet: SMA deployment, mandate signing (EIP-712), any additional-chain deployment.
|
|
107
|
-
- Agent wallet: `mandate deploy`, `mandate attach`, `mandate revoke`, and every dispatch submission once the agent runs, plus permission registration fees on fee-charging chains.
|
|
106
|
+
- Agent wallet: `mandate deploy`, `mandate attach`, `mandate revoke`, and every dispatch submission once the agent runs, plus permission registration fees on fee-charging chains. The registration fee is a **per-permission flat charge** (`permissionRegistrationFee()` on `SailGovernance`, read live — currently `0` on this deploy). A mandate of N permissions costs `N × fee` on top of gas; fund the agent wallet for the full amount before attaching. The fee is disclosed at sign time (`Registration fee: X ETH`) and recorded in the activity log. An underfunded agent wallet fails early with `Insufficient ETH for the X ETH registration fee` rather than reverting on-chain.
|
|
108
107
|
|
|
109
108
|
`sailor doctor` — read-only preflight: kernel dispatch model, permission health, RPC reachability, gas balances in both wallets. Do not proceed to Stage 3 with a failing doctor.
|
|
110
109
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sail-overview
|
|
3
|
+
description: Read this first on every Sailor task. Determines the current project state — installed version, which stage the user is at, what's done and what's next. Also covers the Sail model, the skill router, and the safety invariants. Use on first contact or whenever the user asks "where am I?" or "what's the status?".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sail overview
|
|
7
|
+
|
|
8
|
+
Sail Protocol runs onchain Separately Managed Accounts (SMAs) operated by AI agents. The **owner keeps custody**; the agent acts only within cryptographically-bound permissions (the **mandate**) the owner approves and can always revoke. The agent cannot exceed them.
|
|
9
|
+
|
|
10
|
+
**Voice:** serious, precise, confident — no hype, no emojis, no exclamation marks. Explain *why*, not just *what* (the user is moving real funds). Use user-facing terms: SMA, mandate, permissions, agent wallet, owner. Assume crypto-native; teach the Sail-specific model. Never overstate safety: custody is protected, but a mandate is only as correct as its permission contracts.
|
|
11
|
+
|
|
12
|
+
## Step 1 — Read the current project state (do this before anything else)
|
|
13
|
+
|
|
14
|
+
Do not ask the user where they are. Read it.
|
|
15
|
+
|
|
16
|
+
### Version
|
|
17
|
+
|
|
18
|
+
Check `package.json` in the project root for the installed version:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
node -e "console.log(require('./package.json').dependencies?.['@sail.money/sailor'] ?? require('./package.json').devDependencies?.['@sail.money/sailor'] ?? 'not found')"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or run `sailor --version` (if globally installed) or `npx @sail.money/sailor --version`.
|
|
25
|
+
|
|
26
|
+
Report the version to the user. If it is behind the latest (check with `npm show @sail.money/sailor dist-tags.latest`), surface that — stale versions may be missing commands.
|
|
27
|
+
|
|
28
|
+
### Stage detection — read `.sail/` in this order
|
|
29
|
+
|
|
30
|
+
| What you find | Stage | What it means |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| No `.sail/` directory | **Not initialized** | Run `sail-setup` |
|
|
33
|
+
| `.sail/config.json` exists, `chainId` is `null` | **Stage 0** | Project initialized, chain not chosen yet |
|
|
34
|
+
| No `.sail/account.json` | **Stage 1** | SMA not deployed — go to `sail-onboarding` |
|
|
35
|
+
| `account.json` exists, `state/mandates.json` absent or empty | **Stage 2 / 3** | SMA live, no permissions — strategy + mandate needed |
|
|
36
|
+
| `state/mandates.json` has entries, no `.sail/mandate.json` | **Stage 3** | Permissions deployed but mandate not signed yet |
|
|
37
|
+
| `.sail/mandate.json` exists, `activity.jsonl` absent or no `dispatch_executed` entries | **Stage 4** | Mandate signed, agent not yet run |
|
|
38
|
+
| `activity.jsonl` contains `dispatch_executed` entries | **Stage 4 complete** | Agent is running — check whether Stage 5 has been offered |
|
|
39
|
+
| Stage 4 complete + user has confirmed Stage 5 (or explicitly declined) | **Done** | All stages complete |
|
|
40
|
+
|
|
41
|
+
### What to report to the user
|
|
42
|
+
|
|
43
|
+
After reading the state, give the user a concise status summary before doing anything else:
|
|
44
|
+
|
|
45
|
+
> **Project:** `<name from config.json>`
|
|
46
|
+
> **Version:** `@sail.money/sailor <version>` _(update available: X.Y.Z)_ ← only if behind
|
|
47
|
+
> **Chain:** `<chainId>` / `<chainName>` (or "not chosen yet")
|
|
48
|
+
> **Current stage:** Stage N — `<stage name>`
|
|
49
|
+
> **Completed:** ✓ Stage 1, ✓ Stage 2, … (list done stages)
|
|
50
|
+
> **Next:** `<one sentence on what comes next>`
|
|
51
|
+
|
|
52
|
+
Then lead directly into the next action — do not wait for the user to ask.
|
|
53
|
+
|
|
54
|
+
## The 5-stage flow
|
|
55
|
+
|
|
56
|
+
1. Deploy the SMA + create the agent wallet
|
|
57
|
+
2. Define the strategy
|
|
58
|
+
3. Build, test, and sign the mandate
|
|
59
|
+
4. Run the agent (locally or scheduled)
|
|
60
|
+
5. Extend — notifications + a custom dashboard (offer by default once live; opt-out only)
|
|
61
|
+
|
|
62
|
+
Drive to completion. Track progress by reading `.sail/` — never ask. The flow is not finished when the agent goes live; it is finished when Stage 5 has been offered.
|
|
63
|
+
|
|
64
|
+
## `.sail/` file reference
|
|
65
|
+
|
|
66
|
+
| File | Tells you |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `config.json` | name, `chainId` (null until chosen), `installMode`, contract addresses |
|
|
69
|
+
| `account.json` | active SMA: safe, owner, manager (agent wallet), chainId, saltNonce, deployedChains |
|
|
70
|
+
| `mandate.json` | the signed mandate the runner executes against — absent = not signed yet |
|
|
71
|
+
| `keys/` | encrypted geth-v3 keystores (agent wallet, mandate signer) — never read or print contents |
|
|
72
|
+
| `state/mandates.json` | append-only record of every permission deployed/attached from this project |
|
|
73
|
+
| `runtime/` | live process state: `ui.json` (dashboard pid/port), `server.json` (signing station url/pid) |
|
|
74
|
+
| `activity.jsonl` | unified activity log — agent dispatches and owner signing decisions, one JSON per line |
|
|
75
|
+
| `.env.local` | RPC_URL / CHAIN_ID / per-chain RPC vars / SAIL_PASSPHRASE — never commit or print |
|
|
76
|
+
|
|
77
|
+
## Which skill when
|
|
78
|
+
|
|
79
|
+
| Need | Skill |
|
|
80
|
+
|---|---|
|
|
81
|
+
| Install / readiness / first-time setup | **sail-setup** |
|
|
82
|
+
| How to invoke sailor (local vs Docker, installMode, sailor update) | **sail-sailor** |
|
|
83
|
+
| Deploy SMA, agent wallet, resume setup, run a CLI command | **sail-onboarding** |
|
|
84
|
+
| Read project / account / chain / env state | **sail-project-info** |
|
|
85
|
+
| Start/stop the dashboard or signing station | **sail-servers** |
|
|
86
|
+
| Design / author / test / deploy permission contracts | **sail-mandates** |
|
|
87
|
+
| Build dispatches, run the agent, debug a transaction | **sail-transactions** |
|
|
88
|
+
| Run the agent unattended (cron, runner, daemon) | **sail-automation** |
|
|
89
|
+
| Notifications + custom dashboard (once live) | **sail-extend** |
|
|
90
|
+
|
|
91
|
+
## Invariants — apply every turn
|
|
92
|
+
|
|
93
|
+
- Never authorize (attach) a permission before **both** `forge test` and `sailor mandate simulate` pass.
|
|
94
|
+
- Never describe, mention, or present code in `src/` or `examples/` as the user's strategy — treat strategy definition as a blank slate; ask what they want.
|
|
95
|
+
- Owner signing is **browser-only** — never put an owner key in the terminal.
|
|
96
|
+
- Detect the dispatch model on-chain (`detectKernelCapabilities`) — do not hardcode it.
|
|
97
|
+
- During setup, ask before anything that costs gas. Once the mandate is signed, the mandate is the
|
|
98
|
+
authorization — do not ask per-dispatch.
|
|
99
|
+
- Never commit or print `SAIL_PASSPHRASE` or private keys.
|
|
100
|
+
- ERC-20 `approve()` is **not** covered by supply/swap/deposit permissions — cover every approve explicitly (see sail-mandates).
|
|
@@ -28,3 +28,5 @@ Every command here is read-only and supports `--json` for machine reading. Prefe
|
|
|
28
28
|
- "Is anything running?" — `.sail/runtime/ui.json` (dashboard), `.sail/runtime/server.json` (signing station), agent pid via `sailor status`.
|
|
29
29
|
|
|
30
30
|
Run `sailor doctor` before any operation that spends gas — it is the cheapest way to catch a dead RPC, an unfunded wallet, or a kernel mismatch first.
|
|
31
|
+
|
|
32
|
+
- "What is the permission registration fee?" — `permissionRegistrationFee()` on `SailGovernance` (read live; currently `0` on this deploy). `sailor mandate sign` and `sailor mandate prepare` print the fee before signing. Each `permission_registered` entry in the activity log includes `fee` (wei) and `feeEth` (formatted), so Recent Activity shows the real cost paid per registration.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sail-sailor
|
|
3
|
+
description: How to invoke the Sailor CLI in any environment — local install, global install, npx, or Docker. Covers installMode detection, the correct scoped package name, docker exec prefix, starting the container, the --json flag, SAIL_PASSPHRASE, and sailor update. Read this before running any sailor command if you are unsure how the project is installed.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sail sailor — invoking the CLI
|
|
7
|
+
|
|
8
|
+
Every skill in this project runs `sailor` commands. This skill explains how to invoke them correctly regardless of how Sailor is installed.
|
|
9
|
+
|
|
10
|
+
## Step 1 — Detect the install mode
|
|
11
|
+
|
|
12
|
+
Before running any command, read `.sail/config.json → installMode`:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node -e "const c=require('./.sail/config.json'); console.log(c.installMode ?? 'local')"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| `installMode` | How to run sailor |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `"local"` (or field absent) | `sailor <command>` — the CLI is on the PATH |
|
|
21
|
+
| `"docker"` | `docker exec <containerName> sailor <command>` — sailor runs inside the container |
|
|
22
|
+
|
|
23
|
+
For docker mode, also read `containerName` from the same config (defaults to `"agent"` if absent).
|
|
24
|
+
|
|
25
|
+
## Plugin mode vs. project mode
|
|
26
|
+
|
|
27
|
+
If you are operating Sailor through the **Claude agent plugin**, sailor is bundled inside the plugin — no separate install is needed. The plugin provides the skills directly; for running CLI commands within a project, the project-level install applies.
|
|
28
|
+
|
|
29
|
+
If you are operating a **standalone project** (no plugin), sailor must be available to run commands. Use project-level installation.
|
|
30
|
+
|
|
31
|
+
## Local installation
|
|
32
|
+
|
|
33
|
+
Sailor is published as **`@sail.money/sailor`** — always use the scoped name. The bare `sailor` on npm is a different, unrelated package.
|
|
34
|
+
|
|
35
|
+
### Project-level (recommended)
|
|
36
|
+
|
|
37
|
+
`sailor init` adds `@sail.money/sailor` to `package.json` automatically. After `npm install`, invoke it via:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx sailor <command>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This is the preferred approach because:
|
|
44
|
+
- The version is **pinned** in `package.json` — reproducible across machines and CI
|
|
45
|
+
- `sailor update` bumps the version and re-syncs agent files (skills, `AGENTS.md`) atomically
|
|
46
|
+
- Multiple projects can run different versions side by side without conflict
|
|
47
|
+
|
|
48
|
+
### Global install (for bootstrapping only)
|
|
49
|
+
|
|
50
|
+
Use a global install only when sailor needs to run **before a project exists** (e.g. to run `sailor init` in a fresh folder) or for one-off diagnostics outside a project:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install -g @sail.money/sailor
|
|
54
|
+
sailor init # creates the project; package.json now pins the version
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Once the project is initialized, the project-level dep takes over — you do not need the global install again.
|
|
58
|
+
|
|
59
|
+
### On-the-fly via npx (no install at all)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx @sail.money/sailor@latest <command>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Useful for `sailor init` in a fresh folder without any prior install. Slower on first run (downloads each time unless cached).
|
|
66
|
+
|
|
67
|
+
### Dev / pre-release versions
|
|
68
|
+
|
|
69
|
+
**Only install the dev build if the user explicitly asks for it.** Default to the stable release for all installs.
|
|
70
|
+
|
|
71
|
+
The development build is published under a separate scope (`@dev.sail.money/sailor`). Install it using an npm alias so all skills, imports, and `npx sailor` commands work transparently — nothing in the project needs to know it is a dev build:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install "@sail.money/sailor@npm:@dev.sail.money/sailor@dev"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
After this, `npx sailor --version` resolves the dev build, and every skill in this project runs as normal. To go back to stable:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npm install @sail.money/sailor@latest
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If a documented command reports `unknown command`, the installed version is stale — run `sailor update` or reinstall.
|
|
84
|
+
|
|
85
|
+
## Docker installation
|
|
86
|
+
|
|
87
|
+
### Starting the container
|
|
88
|
+
|
|
89
|
+
Run from the project root:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
docker run -d --name agent -P -v "${PWD}:/workspace" sailmoney/sailor
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
| Flag | Meaning |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `-d` | Detached — runs in the background |
|
|
98
|
+
| `--name agent` | Container name used in all `docker exec` calls |
|
|
99
|
+
| `-P` | Maps container ports (UI: 3334, signing station: 3141) to random host ports |
|
|
100
|
+
| `-v "${PWD}:/workspace"` | Mounts the current project directory into the container |
|
|
101
|
+
|
|
102
|
+
Use a different container name with `--name <name>` and set `containerName` in `.sail/config.json` to match.
|
|
103
|
+
|
|
104
|
+
### Running commands
|
|
105
|
+
|
|
106
|
+
Prefix every sailor command with `docker exec <containerName>`:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
docker exec agent sailor --version
|
|
110
|
+
docker exec agent sailor doctor
|
|
111
|
+
docker exec agent sailor run --once
|
|
112
|
+
docker exec agent sailor ui start
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
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 all files accessible from both sides.
|
|
116
|
+
|
|
117
|
+
### Opening the dashboard (Docker)
|
|
118
|
+
|
|
119
|
+
The UI binds to port **3334 inside the container**, but the host port depends on how `-P` mapped it. Always resolve it before giving the user a URL:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
docker port agent 3334
|
|
123
|
+
# → 0.0.0.0:49201 (open http://localhost:49201)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Stop / restart
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
docker stop agent # stop the container
|
|
130
|
+
docker start agent # restart it (project files are on the host — nothing is lost)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Flags that work on every command
|
|
134
|
+
|
|
135
|
+
| Flag | Effect |
|
|
136
|
+
|---|---|
|
|
137
|
+
| `--json` | Machine-readable JSON output — prefer this; parse, don't scrape |
|
|
138
|
+
| `--help` | Usage and flags for that command |
|
|
139
|
+
|
|
140
|
+
Set `SAIL_PASSPHRASE` in `.sail/.env.local` to unlock the agent wallet non-interactively (CI, headless runs, Docker). Never commit or print this value.
|
|
141
|
+
|
|
142
|
+
## Key CLI commands at a glance
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Diagnostics
|
|
146
|
+
sailor --version # installed version
|
|
147
|
+
sailor doctor # kernel health, RPC reachability, gas balances
|
|
148
|
+
sailor chains # supported chains and kernel addresses
|
|
149
|
+
sailor capabilities # what you can build on the current chain
|
|
150
|
+
|
|
151
|
+
# Account
|
|
152
|
+
sailor account predict # compute deterministic SMA address before deploying
|
|
153
|
+
sailor scan # discover owner's Safes and Sail SMAs
|
|
154
|
+
|
|
155
|
+
# Mandate lifecycle
|
|
156
|
+
sailor mandate simulate # probe a permission off-chain before authorizing
|
|
157
|
+
sailor mandate deploy # deploy a permission contract (owner signs in browser)
|
|
158
|
+
sailor mandate attach # register a deployed permission on an SMA
|
|
159
|
+
sailor mandate sign # build and sign the mandate payload
|
|
160
|
+
sailor mandate list # list permissions deployed from this project
|
|
161
|
+
|
|
162
|
+
# Agent
|
|
163
|
+
sailor run --once # single tick — confirm before automating
|
|
164
|
+
sailor run # continuous agent loop
|
|
165
|
+
sailor keys export-ci # copy encrypted wallet to ci-keystore.json for CI
|
|
166
|
+
|
|
167
|
+
# Unattended execution
|
|
168
|
+
sailor service install # install as OS daemon (launchd / systemd / Task Scheduler)
|
|
169
|
+
sailor service status # daemon status
|
|
170
|
+
sailor service logs -f # follow the agent log
|
|
171
|
+
|
|
172
|
+
# Dashboard
|
|
173
|
+
sailor ui start # start dashboard, print URL
|
|
174
|
+
sailor ui stop # stop dashboard
|
|
175
|
+
sailor ui status # running status + URL + pid
|
|
176
|
+
|
|
177
|
+
# Maintenance
|
|
178
|
+
sailor update # re-sync skills, AGENTS.md, and tooling files after a CLI upgrade
|
|
179
|
+
sailor trigger github # fire the GitHub Actions agent workflow on demand
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Keeping the CLI up to date
|
|
183
|
+
|
|
184
|
+
After upgrading `@sail.money/sailor` in `package.json`, run:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
sailor update
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
This re-syncs the agent tooling files — skills, `AGENTS.md`, `Dockerfile` — without touching user code (`src/`, `mandates/`), keys, or runtime state (`.sail/keys/`, `.sail/state/`, `.sail/activity.jsonl`).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sail-setup
|
|
3
|
+
description: First-time environment readiness for Sailor — check the essential toolchain (Node, npm, the sailor CLI), confirm the target folder, then run `sailor init`. Use when the user wants to start a Sailor project or build a DeFi strategy Sailor can run, or when there is no `.sail/` in the current folder. Proceed through setup without step-by-step permission; the only required confirmation is the target directory. Hands off to sail-overview + sail-onboarding.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sail setup
|
|
7
|
+
|
|
8
|
+
When the user wants to start a Sailor project — or a DeFi strategy Sailor can run — **proceed through setup; do not ask step-by-step permission.** Only two things need an explicit OK: the **target folder** (step 4) and **installing any system-level tool** (step 3).
|
|
9
|
+
|
|
10
|
+
## 1. Detect environment
|
|
11
|
+
- OS + shell (Windows/macOS/Linux; pwsh/bash/zsh).
|
|
12
|
+
- If `.sail/` already exists here, the project is initialized — skip to **sail-onboarding** (resume); do not re-init.
|
|
13
|
+
|
|
14
|
+
## 2. Check the toolchain
|
|
15
|
+
**Essential (needed now):** `node -v` (≥ 18), `npm -v`, `npx @sail.money/sailor --version` (scoped name only — bare `npx sailor` is a different package).
|
|
16
|
+
|
|
17
|
+
**Use-case tools — probe and note, but do NOT install at setup; each is handled when its stage arrives:**
|
|
18
|
+
| Tool | Needed only for | Handled in |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| Foundry (`forge --version`) | authoring/building Solidity permission contracts | sail-mandates (Stage 3) |
|
|
21
|
+
| git + GitHub CLI (`git --version`, `gh --version`) | publishing to GitHub / GitHub Actions runs | sail-automation (only if that path is chosen) |
|
|
22
|
+
| Docker (`docker --version`) | running sailor in a container instead of locally | only if docker install mode is picked |
|
|
23
|
+
|
|
24
|
+
Report what's missing among these, but don't block setup or install them now — surface them when the matching stage comes up.
|
|
25
|
+
|
|
26
|
+
## 3. Install missing tools — confirm before anything system-level
|
|
27
|
+
- sailor itself: run via `npx @sail.money/sailor` (no install), a global `npm i -g @sail.money/sailor`, or docker (`SAILOR_INSTALL_MODE=docker`).
|
|
28
|
+
- **Node, Docker, Foundry, git: ask before installing.** Foundry: `curl -L https://foundry.paradigm.xyz | bash` then `foundryup` (see sail-mandates).
|
|
29
|
+
|
|
30
|
+
## 4. Confirm the target folder, then init
|
|
31
|
+
**The one confirmation that matters.** `sailor init` scaffolds into the **current folder of this session** — state its absolute path and confirm it is the right place before running, because it writes scaffold files (`package.json`, `AGENTS.md`, `foundry.toml`, `.sail/`, …) and would overwrite any existing files with those names. Once confirmed, run it — no further step-gating:
|
|
32
|
+
- `sailor init` — standalone
|
|
33
|
+
- `sailor init --no-skills` — under the Sailor plugin (the plugin already provides the skills)
|
|
34
|
+
|
|
35
|
+
RPC readiness: `RPC_URL` + `CHAIN_ID` live in `.sail/.env.local` (the chain is chosen in onboarding Stage 1; `SAIL_PASSPHRASE` only for headless/CI).
|
|
36
|
+
|
|
37
|
+
## 5. Hand off
|
|
38
|
+
Read **sail-overview** for the operating model, then **sail-onboarding** to deploy the SMA and continue.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
# WHEN does your agent run? Two mechanisms — you almost certainly need to tune
|
|
3
|
+
# the first one for your strategy.
|
|
4
|
+
#
|
|
5
|
+
# 1. Scheduled pipelines — a heartbeat / backstop. Schedules are NOT defined
|
|
6
|
+
# in this file; create them in GitLab UI → CI/CD → Schedules (or via API).
|
|
7
|
+
# GitLab schedules can drift and be skipped under load, so they are the
|
|
8
|
+
# wrong PRIMARY driver for anything latency-sensitive. Tune cadence:
|
|
9
|
+
# • LP / perps / liquidations → minutes — but don't rely on schedules;
|
|
10
|
+
# use a pipeline trigger (#2). Schedules are only a safety net here.
|
|
11
|
+
# • DCA / periodic rebalance → daily.
|
|
12
|
+
# • treasury / slow rebalances → hourly to daily.
|
|
13
|
+
# When creating the schedule, "0 * * * *" (hourly) is a GENERIC PLACEHOLDER
|
|
14
|
+
# — change it to match your strategy.
|
|
15
|
+
#
|
|
16
|
+
# 2. Pipeline triggers — an on-demand trigger. Anything that can make an HTTP
|
|
17
|
+
# call can wake this job instantly (a price band, an on-chain event, a
|
|
18
|
+
# webhook). Fire it from the CLI: sailor trigger gitlab
|
|
19
|
+
# This is how you get low-latency reaction that schedules cannot give you.
|
|
20
|
+
# Pass an optional REASON variable to label the run in the logs:
|
|
21
|
+
# curl -X POST "$CI_API_V4_URL/projects/$CI_PROJECT_ID/trigger/pipeline" \
|
|
22
|
+
# --form "token=<TRIGGER_TOKEN>" \
|
|
23
|
+
# --form "ref=main" \
|
|
24
|
+
# --form "variables[REASON]=price alert"
|
|
25
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
stages:
|
|
28
|
+
- tick
|
|
29
|
+
|
|
30
|
+
agent-tick:
|
|
31
|
+
stage: tick
|
|
32
|
+
image: node:20
|
|
33
|
+
|
|
34
|
+
# Only run on schedules, pipeline triggers, and manual web runs.
|
|
35
|
+
# Push pipelines are excluded — the agent tick is not a build/test step.
|
|
36
|
+
rules:
|
|
37
|
+
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
|
38
|
+
- if: '$CI_PIPELINE_SOURCE == "trigger"'
|
|
39
|
+
- if: '$CI_PIPELINE_SOURCE == "web"'
|
|
40
|
+
|
|
41
|
+
script:
|
|
42
|
+
- mkdir -p .sail/keys
|
|
43
|
+
- cp ci-keystore.json .sail/keys/manager.json
|
|
44
|
+
- npm ci
|
|
45
|
+
- |
|
|
46
|
+
export CHAIN_ID="${CHAIN_ID:-8453}"
|
|
47
|
+
export SAIL_RUN_REASON="${REASON:-$CI_PIPELINE_SOURCE}"
|
|
48
|
+
npx sailor run --once
|
|
49
|
+
|
|
50
|
+
# Required CI/CD variables (Settings → CI/CD → Variables):
|
|
51
|
+
# RPC_URL — your chain RPC endpoint [masked]
|
|
52
|
+
# SAIL_PASSPHRASE — keystore decryption passphrase [masked]
|
|
53
|
+
#
|
|
54
|
+
# Optional CI/CD variables (override defaults):
|
|
55
|
+
# CHAIN_ID — chain ID if not Base (default: 8453)
|
|
56
|
+
#
|
|
57
|
+
# Trigger variables (passed per-run via API or sailor trigger gitlab):
|
|
58
|
+
# REASON — why this run fired (recorded in SAIL_RUN_REASON)
|