@dev.sail.money/sailor 0.1.0-local → 1.0.0-39

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.
Files changed (153) hide show
  1. package/AGENTS.md +139 -140
  2. package/LICENSE +21 -21
  3. package/README.md +428 -430
  4. package/docs/PERMISSION_MODEL.md +93 -93
  5. package/examples/permissions/BoundedApproveAndCallBatch.sol +179 -179
  6. package/examples/permissions/BoundedBet_Limitless_Base.sol +97 -97
  7. package/examples/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +94 -94
  8. package/examples/permissions/BoundedPerp_GMXv2_Arbitrum.sol +154 -154
  9. package/examples/permissions/BoundedStake_Venice_Base.sol +85 -85
  10. package/examples/permissions/BoundedSupply_AaveV3_Arbitrum.sol +82 -82
  11. package/examples/permissions/BoundedSwap_UniswapV3_Base.sol +116 -116
  12. package/examples/permissions/BoundedSwap_UniswapV4_Unichain.sol +150 -150
  13. package/examples/permissions/BoundedTransfer_ERC20_Ethereum.sol +73 -73
  14. package/examples/permissions/BoundedVault_ERC4626_Base.sol +97 -97
  15. package/examples/permissions/README.md +79 -79
  16. package/examples/permissions/SailCalldata.sol +118 -118
  17. package/examples/permissions/foundry.toml +10 -10
  18. package/examples/permissions/interfaces/IBatchPermission.sol +38 -38
  19. package/examples/permissions/interfaces/IPermission.sol +18 -18
  20. package/package.json +44 -45
  21. package/packages/cli/README.md +34 -34
  22. package/packages/cli/dist/index.cjs +734 -705
  23. package/packages/cli/dist/server.cjs +627 -538
  24. package/packages/sdk/README.md +65 -65
  25. package/packages/sdk/dist/intelligence.d.ts +1 -1
  26. package/packages/sdk/dist/intelligence.js +1 -1
  27. package/packages/sdk/package.json +80 -80
  28. package/packages/ui/dist/assets/{add-BxpXfVWe.js → add-Gzf62xlX.js} +1 -1
  29. package/packages/ui/dist/assets/{all-wallets-BKTn_sWK.js → all-wallets-O-pI4o8v.js} +1 -1
  30. package/packages/ui/dist/assets/{app-store-CfuKbwxR.js → app-store-CeSLaOaQ.js} +1 -1
  31. package/packages/ui/dist/assets/{apple-BKSBbNYg.js → apple-FGNyQM-D.js} +1 -1
  32. package/packages/ui/dist/assets/{arrow-bottom-D4bG6gZi.js → arrow-bottom-C1fusORF.js} +1 -1
  33. package/packages/ui/dist/assets/{arrow-bottom-circle-BNTs1p0T.js → arrow-bottom-circle-AvK1VEpN.js} +1 -1
  34. package/packages/ui/dist/assets/{arrow-left-2uee3vYv.js → arrow-left-Bu-hq4Ep.js} +1 -1
  35. package/packages/ui/dist/assets/{arrow-right-BktjMV6h.js → arrow-right-XbZESmct.js} +1 -1
  36. package/packages/ui/dist/assets/{arrow-top-Izu28fX4.js → arrow-top-DvkVHbhX.js} +1 -1
  37. package/packages/ui/dist/assets/{bank-USBaAyFM.js → bank-DTThWRvC.js} +1 -1
  38. package/packages/ui/dist/assets/{basic-C_9KjTEH.js → basic-B9AMgqFE.js} +1 -1
  39. package/packages/ui/dist/assets/{browser-DAEMAKV7.js → browser-Bhnivm4i.js} +1 -1
  40. package/packages/ui/dist/assets/{card-DT8yDkKN.js → card-DjIlyU55.js} +1 -1
  41. package/packages/ui/dist/assets/{ccip-CkqfGSxX.js → ccip-DPAiKntc.js} +1 -1
  42. package/packages/ui/dist/assets/{checkmark-CsgdEXFj.js → checkmark-DSVYfoVl.js} +1 -1
  43. package/packages/ui/dist/assets/{checkmark-bold-D2gjOQo2.js → checkmark-bold-BFkw_Q5g.js} +1 -1
  44. package/packages/ui/dist/assets/{chevron-bottom-tprFynYV.js → chevron-bottom-CyCgyOwY.js} +1 -1
  45. package/packages/ui/dist/assets/{chevron-left-D2Zj1gNB.js → chevron-left-DTuO2WLr.js} +1 -1
  46. package/packages/ui/dist/assets/{chevron-right-D1rRuAVe.js → chevron-right-DwB5FZj8.js} +1 -1
  47. package/packages/ui/dist/assets/{chevron-top-24dL1mbL.js → chevron-top-DKukdWvg.js} +1 -1
  48. package/packages/ui/dist/assets/{chrome-store-Vy-5niYX.js → chrome-store-Csz4L9Ls.js} +1 -1
  49. package/packages/ui/dist/assets/{clock-qBjLnVdJ.js → clock-Bg6488Gw.js} +1 -1
  50. package/packages/ui/dist/assets/{close-DARDwgcu.js → close-BxAJGBxP.js} +1 -1
  51. package/packages/ui/dist/assets/{coinPlaceholder-BvpIbPlD.js → coinPlaceholder-CCJVgW9w.js} +1 -1
  52. package/packages/ui/dist/assets/{compass-BMTO0ayt.js → compass-CSQSZaqJ.js} +1 -1
  53. package/packages/ui/dist/assets/{copy-PaXeRHza.js → copy-CqlzXVB-.js} +1 -1
  54. package/packages/ui/dist/assets/{core-BFnStQd-.js → core-ClvdTrpG.js} +3 -3
  55. package/packages/ui/dist/assets/cursor-CKKwWhGQ.js +3 -0
  56. package/packages/ui/dist/assets/{cursor-transparent-BEMdi-8q.js → cursor-transparent-C1VOGz11.js} +1 -1
  57. package/packages/ui/dist/assets/{desktop-CfuLLThw.js → desktop-QiLednKV.js} +1 -1
  58. package/packages/ui/dist/assets/{disconnect-DhwgJMiR.js → disconnect-Bx2TgkML.js} +1 -1
  59. package/packages/ui/dist/assets/{discord-po8qoN1s.js → discord-6MWX5Rbb.js} +1 -1
  60. package/packages/ui/dist/assets/{etherscan-BEsz0_yx.js → etherscan-CodIrmJK.js} +1 -1
  61. package/packages/ui/dist/assets/{events-Bz33Unzu.js → events-DOEm-LTy.js} +1 -1
  62. package/packages/ui/dist/assets/{exclamation-triangle-7CjTAGOQ.js → exclamation-triangle-Dwr5oCsh.js} +1 -1
  63. package/packages/ui/dist/assets/{extension-CmxjEWEt.js → extension-C-SoZx1s.js} +1 -1
  64. package/packages/ui/dist/assets/{external-link-CmQ--bNS.js → external-link-BiDYH90C.js} +1 -1
  65. package/packages/ui/dist/assets/{facebook-CIBn9b65.js → facebook-Bm27AlfS.js} +1 -1
  66. package/packages/ui/dist/assets/{fallback-DATyrQlb.js → fallback-Bwpmpy13.js} +1 -1
  67. package/packages/ui/dist/assets/{farcaster-OJ3Jasxg.js → farcaster-CSW-SjzS.js} +1 -1
  68. package/packages/ui/dist/assets/{filters-D4x09zeL.js → filters-j3dR7AJK.js} +1 -1
  69. package/packages/ui/dist/assets/{github-ZlIuMArp.js → github-CQMTSSgW.js} +1 -1
  70. package/packages/ui/dist/assets/{google-Gwg85sfv.js → google-BBIVBfAd.js} +1 -1
  71. package/packages/ui/dist/assets/{help-circle-D1uOWYcX.js → help-circle-CEvTLelF.js} +1 -1
  72. package/packages/ui/dist/assets/{id-C0-5UdYk.js → id-CYRVgSgN.js} +1 -1
  73. package/packages/ui/dist/assets/{image-D_DUsv8-.js → image-Cm9Ep5G0.js} +1 -1
  74. package/packages/ui/dist/assets/{index-DdbJhIdl.js → index-4wdo7Ga_.js} +3 -3
  75. package/packages/ui/dist/assets/{index-CrYzBWfD.js → index-BrP8m1ZI.js} +1 -1
  76. package/packages/ui/dist/assets/index-C2PQCECq.css +1 -0
  77. package/packages/ui/dist/assets/{index-DiojfeVM.js → index-DZ07nuwB.js} +1 -1
  78. package/packages/ui/dist/assets/{index-BCzex_R6.js → index-De_P6mNS.js} +1 -1
  79. package/packages/ui/dist/assets/index-DrQ9A8dp.js +1775 -0
  80. package/packages/ui/dist/assets/{index-izd7vu_r.js → index-Z55BVE94.js} +1 -1
  81. package/packages/ui/dist/assets/{index.es-DdkHhQAj.js → index.es-DnT9Uzwt.js} +4 -4
  82. package/packages/ui/dist/assets/{info-CiRd_kEG.js → info-DdYqiFMu.js} +1 -1
  83. package/packages/ui/dist/assets/{info-circle-ypxjqarK.js → info-circle-DkD9oY-S.js} +1 -1
  84. package/packages/ui/dist/assets/{lightbulb-B-pxLxd8.js → lightbulb-7Q3AhpSP.js} +1 -1
  85. package/packages/ui/dist/assets/{mail-BYmicuVZ.js → mail-CPagdnfp.js} +1 -1
  86. package/packages/ui/dist/assets/{metamask-sdk-Ccl6DG7Q.js → metamask-sdk-CQ4tzR6A.js} +1 -1
  87. package/packages/ui/dist/assets/{mobile-CtP5PqVT.js → mobile-01GVSpey.js} +1 -1
  88. package/packages/ui/dist/assets/{more-6C2733we.js → more-BPXPYrvy.js} +1 -1
  89. package/packages/ui/dist/assets/{network-placeholder-CdhxMzqd.js → network-placeholder-CII8WrTF.js} +1 -1
  90. package/packages/ui/dist/assets/{nftPlaceholder-DVmTWEAY.js → nftPlaceholder-DG5rjRzx.js} +1 -1
  91. package/packages/ui/dist/assets/{off-DNYLughs.js → off-eemo7R2q.js} +1 -1
  92. package/packages/ui/dist/assets/{parseSignature-Dq2B5Bu3.js → parseSignature-CaRSntRi.js} +1 -1
  93. package/packages/ui/dist/assets/{play-store-D7Qut5ta.js → play-store-SIqMwLur.js} +1 -1
  94. package/packages/ui/dist/assets/{plus-kqMyjt3q.js → plus-DemTM2Nx.js} +1 -1
  95. package/packages/ui/dist/assets/{qr-code-DiUCWRbz.js → qr-code-BjolKhQv.js} +1 -1
  96. package/packages/ui/dist/assets/{recycle-horizontal-Boe3XiS-.js → recycle-horizontal-BluxSqWj.js} +1 -1
  97. package/packages/ui/dist/assets/{refresh-CrBgBQYO.js → refresh-Cto5auO0.js} +1 -1
  98. package/packages/ui/dist/assets/{reown-logo-CFZCCHSx.js → reown-logo-lrWmaeNj.js} +1 -1
  99. package/packages/ui/dist/assets/{search-ChTDrghU.js → search-SNmrxLL7.js} +1 -1
  100. package/packages/ui/dist/assets/{secp256k1-DAV5Q_FR.js → secp256k1-SI0Bxirn.js} +1 -1
  101. package/packages/ui/dist/assets/{send-DLFbBFe1.js → send-Do8kdKTu.js} +1 -1
  102. package/packages/ui/dist/assets/{swapHorizontal-BEs3emfG.js → swapHorizontal-HBP1koQV.js} +1 -1
  103. package/packages/ui/dist/assets/{swapHorizontalBold-CC-Hfa7W.js → swapHorizontalBold-B9g1LqXn.js} +1 -1
  104. package/packages/ui/dist/assets/{swapHorizontalMedium-BmR0H8DC.js → swapHorizontalMedium-C8JebI_2.js} +1 -1
  105. package/packages/ui/dist/assets/{swapHorizontalRoundedBold-BdP5NGIH.js → swapHorizontalRoundedBold-37eEYoAp.js} +1 -1
  106. package/packages/ui/dist/assets/{swapVertical-CPrGEJPY.js → swapVertical-DmacpIGs.js} +1 -1
  107. package/packages/ui/dist/assets/{telegram-CxNoZ80Q.js → telegram-Dq_CUch4.js} +1 -1
  108. package/packages/ui/dist/assets/{three-dots-BRa6SBpL.js → three-dots-DbkqGUCU.js} +1 -1
  109. package/packages/ui/dist/assets/{twitch-BC338bG5.js → twitch-iG0Ncwwy.js} +1 -1
  110. package/packages/ui/dist/assets/{twitterIcon-BGZmt2i9.js → twitterIcon-CNbKQx87.js} +1 -1
  111. package/packages/ui/dist/assets/{verify-CEstW0zw.js → verify-BfXT7L3L.js} +1 -1
  112. package/packages/ui/dist/assets/{verify-filled-OkZb0weU.js → verify-filled-BxqxA6xc.js} +1 -1
  113. package/packages/ui/dist/assets/{w3m-modal-pS09ECwE.js → w3m-modal-DeDYqwYJ.js} +1 -1
  114. package/packages/ui/dist/assets/{wallet-BXVKCgC9.js → wallet-BXsUR9Tj.js} +1 -1
  115. package/packages/ui/dist/assets/{wallet-placeholder-C_kNhB1c.js → wallet-placeholder-bbWbfkZu.js} +1 -1
  116. package/packages/ui/dist/assets/{walletconnect-CRKIuUHH.js → walletconnect-WsTWE17z.js} +1 -1
  117. package/packages/ui/dist/assets/{warning-circle-DB2NnwlJ.js → warning-circle-cNSUigh6.js} +1 -1
  118. package/packages/ui/dist/assets/{x-DT4RmwL5.js → x-gNtNGE0N.js} +1 -1
  119. package/packages/ui/dist/index.html +14 -14
  120. package/scripts/check-docs.mjs +262 -262
  121. package/scripts/check-init.mjs +108 -108
  122. package/templates/custom-mandate/.sail/contracts/interfaces/IPermission.sol +18 -18
  123. package/templates/custom-mandate/README.md +116 -116
  124. package/templates/custom-mandate/foundry.toml +8 -8
  125. package/templates/custom-mandate/mandates/BoundedCallPermission.sol +41 -41
  126. package/templates/custom-mandate/mandates/README.md +16 -16
  127. package/templates/custom-mandate/mandates/SailCalldata.sol +118 -118
  128. package/templates/default/.cursor/rules +25 -25
  129. package/templates/default/.env.example +20 -20
  130. package/templates/default/.github/workflows/agent-tick.yml +33 -33
  131. package/templates/default/.sail/README.md +13 -13
  132. package/templates/default/.sail/config.json +10 -10
  133. package/templates/default/AGENTS.md +171 -171
  134. package/templates/default/CLAUDE.md +2 -2
  135. package/templates/default/README.md +16 -16
  136. package/templates/default/_gitignore +13 -13
  137. package/templates/default/docs/PERMISSION_MODEL.md +93 -93
  138. package/templates/default/examples/dca/README.md +16 -16
  139. package/templates/default/examples/dca/agent.ts +174 -174
  140. package/templates/default/examples/dca/mandate.ts +45 -45
  141. package/templates/default/package.json +17 -17
  142. package/templates/default/src/agent.ts +37 -37
  143. package/templates/default/src/config.ts +24 -24
  144. package/templates/default/src/mandate.ts +22 -22
  145. package/templates/default/tsconfig.json +17 -17
  146. package/templates/default/ui/README.md +3 -3
  147. package/templates/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +84 -84
  148. package/templates/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +97 -97
  149. package/templates/lifi-permissions/README.md +53 -53
  150. package/packages/ui/dist/assets/cursor-BDvw-B17.js +0 -3
  151. package/packages/ui/dist/assets/index-BUhrHLpY.js +0 -1775
  152. package/packages/ui/dist/assets/index-Cq02kQmy.css +0 -1
  153. package/scripts/postinstall.js +0 -81
package/AGENTS.md CHANGED
@@ -1,140 +1,139 @@
1
- # Sailor — Codebase Guide
2
-
3
- Sailor is the operator toolkit for Sail Protocol. It does **not** deploy the protocol or author
4
- permission templates — it targets already-deployed SailKernel instances and gives operators the
5
- tooling to create SMAs, register permission contracts, and run strategy agents.
6
-
7
- ## Repo structure
8
-
9
- | Package / path | Name | Role |
10
- |---|---|---|
11
- | `packages/sdk` | `@sail/sdk` | SailorClient, LocalKeyring, kernel ABIs, EIP-712 builders, deployment registry, per-chain address registry |
12
- | `packages/cli` | `sailor` | CLI: init, keys, account, mandate, onboard, station, ui, run, session, scan, status, owner, doctor, capabilities |
13
- | `packages/ui` | `sailor-ui` | Local dashboard + browser-driven onboarding wizard at localhost:3333 |
14
- | `templates/default` | — | Default agent starter: neutral blank scaffold + Foundry workspace + onboarding guide (AGENTS.md) |
15
- | `templates/custom-mandate` | — | Solidity reference: IPermission scaffold (not a project template) |
16
-
17
- ## Protocol roles
18
-
19
- The code uses internal identifiers that differ from user-facing terms:
20
-
21
- | User-facing term | Code identifier | Meaning |
22
- |---|---|---|
23
- | Owner | `owner` | Holds the Safe; custody anchor; never touches the agent runtime |
24
- | Mandate signer | `permissionSigner` | Authorizes permission registration via EIP-712 |
25
- | Agent wallet | `manager` | Signs dispatches; key at `.sail/keys/manager.json` |
26
-
27
- Use the user-facing terms in all CLI output, prompts, and errors. The code identifiers are internal.
28
-
29
- ## Dispatch model
30
-
31
- Active kernels vary by chain verified on-chain via `DISPATCH_TYPEHASH()`:
32
-
33
- | Chain | Kernel | Model | DISPATCH_TYPEHASH |
34
- |---|---|---|---|
35
- | Base 8453 | `0x6319d3dfDDe3804ba93D65752b00c52bFb05a1ab` | **selective** | `0xbe50c539...` |
36
- | Base Sepolia 84532 | `0xf1D0F4C9893612627409948BAa9d82a01a373799` | **selective** | `0xbe50c539...` |
37
- | Arbitrum 42161 | `0x2716B12832DED0EF5688519c5Fe069EFc0374E02` | **selective** | `0xbe50c539...` |
38
- | Unichain 130 | `0xD985029960a9B7C2E7E38e102C448b8b8539B156` | **selective** | `0xbe50c539...` |
39
-
40
- All four kernels are live and bootstrapped (genesis allowlist set, `createAccount` verified working, zero fees). Unichain (130) additionally has the full permission-template suite deployed and source-verified (7 shared + 12 standalone) — it is the only chain with templates so far; the other three have core only. `packages/sdk/src/deployments.ts` is the canonical source of truth for kernel addresses, templates, and metadata.
41
-
42
- **Always use `detectKernelCapabilities` for the real model** it reads the on-chain typehash and
43
- overrides the static label in `deployments.ts`. The static label is a fallback for offline use only.
44
-
45
- Type strings:
46
- ```
47
- conjunctive: Dispatch(address account,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)
48
- selective: Dispatch(address account,address permission,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)
49
-
50
- conjunctive RegisterPermission: RegisterPermission(address account,address permission,uint256 nonce)
51
- selective RegisterPermission: RegisterPermission(address account,address permission,uint256 nonce,uint256 deadline)
52
- ```
53
-
54
- `buildRegisterPermissionTypedData` accepts `hasDeadline` from `KernelCapabilities.registerPermissionHasDeadline`.
55
- Pass the detected value — never hardcode the type shape.
56
-
57
- ## Active addresses
58
-
59
- All four chain records in `packages/sdk/src/deployments.ts` are live no commented-out or pending
60
- addresses remain. This file is the source of truth this guide mirrors.
61
-
62
- - `packages/sdk/src/deployments.ts` — `SailDeployment` records; canonical source of truth
63
- - `packages/chains/src/index.ts` — `ChainConfig` per chainId; kept in sync with deployments
64
-
65
- ## Key files
66
-
67
- | File | What it owns |
68
- |---|---|
69
- | `packages/sdk/src/deployments.ts` | Active + PENDING addresses, `dispatchModel` per chain |
70
- | `packages/sdk/src/capabilities.ts` | On-chain typehash detection; capability cache |
71
- | `packages/sdk/src/eip712.ts` | `buildRegisterPermissionTypedData`, `REGISTER_PERMISSION_TYPES` |
72
- | `packages/cli/src/commands/onboard.ts` | SMA creation + permission registration flow |
73
- | `packages/cli/src/commands/mandate-contracts.ts` | Deploy / attach / revoke permission contracts |
74
- | `packages/cli/src/lib/mandates.ts` | `MandateStore` `.sail/state/mandates.json` source of truth |
75
- | `packages/ui/server.js` | Local API + WebSocket proxy; signing station relay |
76
-
77
- ## Build
78
-
79
- ```bash
80
- pnpm install
81
- pnpm build # builds all packages; dependency order: sdk → chains → cli → ui
82
- ```
83
-
84
- Build order matters — `cli` imports from `sdk` and `chains`.
85
-
86
- ## Test
87
-
88
- ```bash
89
- pnpm test # vitestno chain needed, ~1.3s
90
- pnpm test:ui # playwright — requires pnpm build first
91
- ```
92
-
93
- Test fixtures live in `packages/ui/test/fixtures/` — isolated directories with pre-canned `.sail/`
94
- state; no real RPC needed.
95
-
96
- ## RPC configuration
97
-
98
- RPC URLs are resolved by `packages/cli/src/lib/chain.ts` `getRpcUrl(chainId)` in this order (first match wins):
99
-
100
- 1. `.sail/.env.local` — chain-specific var (e.g. `BASE_RPC_URL`, `ARBITRUM_RPC_URL`)
101
- 2. `.sail/.env.local`generic `RPC_URL`
102
- 3. Shell environment — chain-specific var
103
- 4. Shell environment — generic `RPC_URL`
104
-
105
- Two valid patterns for `.sail/.env.local`:
106
-
107
- ```
108
- # Option A — single active chain
109
- RPC_URL=https://your-base-endpoint
110
- CHAIN_ID=8453
111
- ```
112
-
113
- ```
114
- # Option B — per-chain (multi-chain projects; omit RPC_URL if all chains have a specific var)
115
- CHAIN_ID=8453
116
- BASE_RPC_URL=https://your-base-endpoint
117
- ARBITRUM_RPC_URL=https://your-arbitrum-endpoint
118
- UNICHAIN_RPC_URL=https://your-unichain-endpoint
119
- ETH_MAINNET_RPC_URL=https://your-mainnet-endpoint
120
- BASE_SEPOLIA_RPC_URL=https://your-base-sepolia-endpoint
121
- SEPOLIA_RPC_URL=https://your-sepolia-endpoint
122
- ```
123
-
124
- Per-chain vars always take precedence for their specific chain, so multi-chain projects resolve each endpoint correctly. `sailor chains --verify` uses this to check every chain that has a configured RPC.
125
-
126
- ## Conventions
127
-
128
- - `SAIL_DIR` — env var pointing to the project's `.sail/` directory (used by the UI server)
129
- - `SAIL_PASSPHRASE` — unlocks `.sail/keys/manager.json` headlessly; read from `.sail/.env.local`
130
- - `SERVE_DIST=1` makes the UI server serve the built React app at `/`
131
- - All CLI commands support `--json` for machine-readable output
132
- - Addresses in `.sail/` files stored checksummed; bigints as decimal strings
133
-
134
- ## What NOT to do
135
-
136
- - Do not change active kernel/mandateFactory/governance addresses without confirming on-chain state
137
- - Do not use conjunctive EIP-712 type strings in new code
138
- - Do not add new root-level markdown files to this repo
139
- - Always run `pnpm build` before `pnpm test:ui`
140
- - Do not commit `SAIL_PASSPHRASE` or private keys
1
+ # Sailor — Codebase Guide
2
+
3
+ Sailor is the operator toolkit for Sail Protocol. It does **not** deploy the protocol or author
4
+ permission templates — it targets already-deployed SailKernel instances and gives operators the
5
+ tooling to create SMAs, register permission contracts, and run strategy agents.
6
+
7
+ ## Repo structure
8
+
9
+ | Package / path | Name | Role |
10
+ |---|---|---|
11
+ | `packages/sdk` | `@sail/sdk` | SailorClient, LocalKeyring, kernel ABIs, EIP-712 builders, deployment registry, per-chain address registry |
12
+ | `packages/cli` | `sailor` | CLI: init, keys, account, mandate, onboard, station, ui, run, session, scan, status, owner, doctor, capabilities |
13
+ | `packages/ui` | `sailor-ui` | Local dashboard + browser-driven onboarding wizard at localhost:3333 |
14
+ | `templates/default` | — | Default agent starter: neutral blank scaffold + Foundry workspace + onboarding guide (AGENTS.md) |
15
+ | `templates/custom-mandate` | — | Solidity reference: IPermission scaffold (not a project template) |
16
+
17
+ ## Protocol roles
18
+
19
+ The code uses internal identifiers that differ from user-facing terms:
20
+
21
+ | User-facing term | Code identifier | Meaning |
22
+ |---|---|---|
23
+ | Owner | `owner` | Holds the Safe; custody anchor; never touches the agent runtime |
24
+ | Mandate signer | `permissionSigner` | Authorizes permission registration via EIP-712 |
25
+ | Agent wallet | `manager` | Signs dispatches; key at `.sail/keys/manager.json` |
26
+
27
+ Use the user-facing terms in all CLI output, prompts, and errors. The code identifiers are internal.
28
+
29
+ ## Dispatch model
30
+
31
+ All six chains share the same kernel at the same CREATE2 address, verified on-chain via `DISPATCH_TYPEHASH()`:
32
+
33
+ | Kernel (all 6 chains) | Model | DISPATCH_TYPEHASH |
34
+ |---|---|---|
35
+ | `0x02ABC18B65A328de2e749F56ba79ACF2718a6659` | **selective** | `0xbe50c539...` |
36
+
37
+ Supported chains: Ethereum (1), Base (8453), Arbitrum (42161), Unichain (130), Base Sepolia (84532), Eth Sepolia (11155111).
38
+
39
+ All six kernels are live and bootstrapped (genesis allowlist set, `createAccount` verified working, zero fees). No templates are deployed against the current kernel on any chain yet — `knownTemplates` and `standaloneTemplates` are empty for all six entries. `packages/sdk/src/deployments.ts` is the canonical source of truth for kernel addresses, templates, and metadata.
40
+
41
+ **Always use `detectKernelCapabilities` for the real model** — it reads the on-chain typehash and
42
+ overrides the static label in `deployments.ts`. The static label is a fallback for offline use only.
43
+
44
+ Type strings:
45
+ ```
46
+ conjunctive: Dispatch(address account,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)
47
+ selective: Dispatch(address account,address permission,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)
48
+
49
+ conjunctive RegisterPermission: RegisterPermission(address account,address permission,uint256 nonce)
50
+ selective RegisterPermission: RegisterPermission(address account,address permission,uint256 nonce,uint256 deadline)
51
+ ```
52
+
53
+ `buildRegisterPermissionTypedData` accepts `hasDeadline` from `KernelCapabilities.registerPermissionHasDeadline`.
54
+ Pass the detected value — never hardcode the type shape.
55
+
56
+ ## Active addresses
57
+
58
+ All six chain records in `packages/sdk/src/deployments.ts` are live — no commented-out or pending
59
+ addresses remain. This file is the source of truth this guide mirrors.
60
+
61
+ - `packages/sdk/src/deployments.ts` — `SailDeployment` records; canonical source of truth
62
+ - `packages/sdk/src/chains.ts` — `ChainConfig` per chainId; canonical per-chain registry
63
+
64
+ ## Key files
65
+
66
+ | File | What it owns |
67
+ |---|---|
68
+ | `packages/sdk/src/deployments.ts` | Active + PENDING addresses, `dispatchModel` per chain |
69
+ | `packages/sdk/src/capabilities.ts` | On-chain typehash detection; capability cache |
70
+ | `packages/sdk/src/eip712.ts` | `buildRegisterPermissionTypedData`, `REGISTER_PERMISSION_TYPES` |
71
+ | `packages/cli/src/commands/onboard.ts` | SMA creation + permission registration flow |
72
+ | `packages/cli/src/commands/mandate-contracts.ts` | Deploy / attach / revoke permission contracts |
73
+ | `packages/cli/src/lib/mandates.ts` | `MandateStore` `.sail/state/mandates.json` source of truth |
74
+ | `packages/ui/server.js` | Local API + WebSocket proxy; signing station relay |
75
+
76
+ ## Build
77
+
78
+ ```bash
79
+ pnpm install
80
+ pnpm build # builds all packages; dependency order: sdk → cli → ui
81
+ ```
82
+
83
+ Build order matters — `cli` imports from `sdk`.
84
+
85
+ ## Test
86
+
87
+ ```bash
88
+ pnpm test # vitest — no chain needed, ~1.3s
89
+ pnpm test:ui # playwrightrequires pnpm build first
90
+ ```
91
+
92
+ Test fixtures live in `packages/ui/test/fixtures/` — isolated directories with pre-canned `.sail/`
93
+ state; no real RPC needed.
94
+
95
+ ## RPC configuration
96
+
97
+ RPC URLs are resolved by `packages/cli/src/lib/chain.ts` `getRpcUrl(chainId)` in this order (first match wins):
98
+
99
+ 1. `.sail/.env.local` — chain-specific var (e.g. `BASE_RPC_URL`, `ARBITRUM_RPC_URL`)
100
+ 2. `.sail/.env.local` — generic `RPC_URL`
101
+ 3. Shell environment chain-specific var
102
+ 4. Shell environment — generic `RPC_URL`
103
+
104
+ Two valid patterns for `.sail/.env.local`:
105
+
106
+ ```
107
+ # Option A — single active chain
108
+ RPC_URL=https://your-base-endpoint
109
+ CHAIN_ID=8453
110
+ ```
111
+
112
+ ```
113
+ # Option B — per-chain (multi-chain projects; omit RPC_URL if all chains have a specific var)
114
+ CHAIN_ID=8453
115
+ BASE_RPC_URL=https://your-base-endpoint
116
+ ARBITRUM_RPC_URL=https://your-arbitrum-endpoint
117
+ UNICHAIN_RPC_URL=https://your-unichain-endpoint
118
+ ETH_MAINNET_RPC_URL=https://your-mainnet-endpoint
119
+ BASE_SEPOLIA_RPC_URL=https://your-base-sepolia-endpoint
120
+ SEPOLIA_RPC_URL=https://your-sepolia-endpoint
121
+ ```
122
+
123
+ Per-chain vars always take precedence for their specific chain, so multi-chain projects resolve each endpoint correctly. `sailor chains --verify` uses this to check every chain that has a configured RPC.
124
+
125
+ ## Conventions
126
+
127
+ - `SAIL_DIR` — env var pointing to the project's `.sail/` directory (used by the UI server)
128
+ - `SAIL_PASSPHRASE` — unlocks `.sail/keys/manager.json` headlessly; read from `.sail/.env.local`
129
+ - `SERVE_DIST=1` — makes the UI server serve the built React app at `/`
130
+ - All CLI commands support `--json` for machine-readable output
131
+ - Addresses in `.sail/` files stored checksummed; bigints as decimal strings
132
+
133
+ ## What NOT to do
134
+
135
+ - Do not change active kernel/mandateFactory/governance addresses without confirming on-chain state
136
+ - Do not use conjunctive EIP-712 type strings in new code
137
+ - Do not add new root-level markdown files to this repo
138
+ - Always run `pnpm build` before `pnpm test:ui`
139
+ - Do not commit `SAIL_PASSPHRASE` or private keys
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Alejandro Dopico
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alejandro Dopico
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.