@bnbagent/studio-cli 0.0.13-alpha.8 → 0.0.14-alpha.1

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 (29) hide show
  1. package/README.md +8 -0
  2. package/dist/bag.js +3556 -1565
  3. package/dist/{chunk-NTDWVEW2.js → chunk-QVYWAJEK.js} +228 -72
  4. package/dist/{deployCli-ZESBUWQB.js → deployCli-F3AOM5UO.js} +1 -2
  5. package/package.json +2 -2
  6. package/recipes/agent/code/{{PKG}}/deliveryPolicy.ts.tmpl +43 -0
  7. package/recipes/agent/code/{{PKG}}/readToolCatalog.ts.tmpl +102 -0
  8. package/recipes/agent/code/{{PKG}}/signing.ts.tmpl +7 -2
  9. package/recipes/agent/recipe.toml +4 -3
  10. package/recipes/runtimes/agentcore/code/{{PKG}}/dualMain.ts.tmpl +6 -2
  11. package/recipes/runtimes/agentcore/code/{{PKG}}/mcpMain.ts.tmpl +173 -134
  12. package/recipes/runtimes/agentcore/code/{{PKG}}/model.ts.tmpl +7 -0
  13. package/recipes/runtimes/agentcore/code/{{PKG}}/sellerCore.ts.tmpl +31 -46
  14. package/recipes/runtimes/agentcore/code/{{PKG}}/tools.ts.tmpl +19 -48
  15. package/recipes/runtimes/agentcore/code/{{PKG}}/unifiedMain.ts.tmpl +2 -1
  16. package/recipes/runtimes/azure-foundry/code/{{PKG}}/mcpMain.ts.tmpl +173 -134
  17. package/recipes/runtimes/azure-foundry/code/{{PKG}}/model.ts.tmpl +7 -0
  18. package/recipes/runtimes/azure-foundry/code/{{PKG}}/sellerCore.ts.tmpl +31 -46
  19. package/recipes/runtimes/azure-foundry/code/{{PKG}}/tools.ts.tmpl +19 -48
  20. package/recipes/runtimes/azure-foundry/code/{{PKG}}/unifiedMain.ts.tmpl +2 -1
  21. package/recipes/wallet/recipe.toml +3 -2
  22. package/skills/bnbagent-studio.md +12 -1
  23. package/skills/references/bnbagent-studio-operating.md +1 -0
  24. package/skills/references/bnbagent-studio-scaffolding-agent.md +11 -34
  25. package/skills/references/bnbagent-studio-selling-via-b402.md +3 -3
  26. package/skills/references/bnbagent-studio-using-altana-wallet.md +6 -1
  27. package/skills/references/bnbagent-studio-using-twak-wallet.md +24 -76
  28. package/dist/_twak-4XF4H5PL.js +0 -25
  29. package/dist/chunk-RO726HJG.js +0 -175
@@ -30,6 +30,7 @@ import * as cr from "@bnbagent/studio-runtime/tools";
30
30
  import { loadStudioToml } from "@bnbagent/studio-runtime/config";
31
31
  import { tool, type ToolSet } from "ai";
32
32
  import { z } from "zod";
33
+ import { READ_TOOL_CATALOG } from "./readToolCatalog.js";
33
34
 
34
35
  /**
35
36
  * The project-wide default network (`[network].default`) — tool calls that
@@ -46,51 +47,34 @@ function defaultNetwork(): string {
46
47
  }
47
48
  }
48
49
 
49
- const networkArg = z
50
- .string()
51
- .optional()
52
- .describe("studio network name (defaults to the project's [network].default)");
53
-
54
50
  export const LLM_READ_TOOLS: ToolSet = {
55
51
  // --- Wallet & chain basics ---
56
52
  wallet_info: tool({
57
- description:
58
- "Describe the agent's active wallet (address, kind, key location).",
59
- inputSchema: z.object({}),
53
+ description: READ_TOOL_CATALOG.wallet_info.description,
54
+ inputSchema: z.object(READ_TOOL_CATALOG.wallet_info.inputSchema),
60
55
  execute: async () => cr.walletInfo(),
61
56
  }),
62
57
  balance_native: tool({
63
- description:
64
- "Native BNB balance of an address (defaults to the agent's own wallet).",
65
- inputSchema: z.object({
66
- address: z.string().optional().describe("0x address; omit for own wallet"),
67
- network: networkArg,
68
- }),
58
+ description: READ_TOOL_CATALOG.balance_native.description,
59
+ inputSchema: z.object(READ_TOOL_CATALOG.balance_native.inputSchema),
69
60
  execute: async ({ address, network }) =>
70
61
  cr.balanceNative(address ?? null, network ?? defaultNetwork()),
71
62
  }),
72
63
  balance_u: tool({
73
64
  // requires [u_token] in studio.toml
74
- description:
75
- "$U (payment token) balance of an address (defaults to the agent's own wallet).",
76
- inputSchema: z.object({
77
- address: z.string().optional().describe("0x address; omit for own wallet"),
78
- network: networkArg,
79
- }),
65
+ description: READ_TOOL_CATALOG.balance_u.description,
66
+ inputSchema: z.object(READ_TOOL_CATALOG.balance_u.inputSchema),
80
67
  execute: async ({ address, network }) =>
81
68
  cr.balanceU(address ?? null, network ?? defaultNetwork()),
82
69
  }),
83
70
  network_info: tool({
84
- description: "Chain id / RPC / token info for a studio network.",
85
- inputSchema: z.object({ network: networkArg }),
71
+ description: READ_TOOL_CATALOG.network_info.description,
72
+ inputSchema: z.object(READ_TOOL_CATALOG.network_info.inputSchema),
86
73
  execute: async ({ network }) => cr.networkInfo(network ?? defaultNetwork()),
87
74
  }),
88
75
  tx_status: tool({
89
- description: "Status + receipt summary of a transaction hash.",
90
- inputSchema: z.object({
91
- tx_hash: z.string().describe("0x transaction hash"),
92
- network: networkArg,
93
- }),
76
+ description: READ_TOOL_CATALOG.tx_status.description,
77
+ inputSchema: z.object(READ_TOOL_CATALOG.tx_status.inputSchema),
94
78
  execute: async ({ tx_hash, network }) =>
95
79
  cr.txStatus(tx_hash, network ?? defaultNetwork()),
96
80
  }),
@@ -106,21 +90,15 @@ export const LLM_READ_TOOLS: ToolSet = {
106
90
  // --- ERC-8004 identity (read-only lookups the LLM may want for context) ---
107
91
  agent_info: tool({
108
92
  // requires [erc8004] in studio.toml
109
- description: "ERC-8004 identity record for an agent id.",
110
- inputSchema: z.object({
111
- agent_id: z.number().int().describe("ERC-8004 agent id"),
112
- network: networkArg,
113
- }),
93
+ description: READ_TOOL_CATALOG.agent_info.description,
94
+ inputSchema: z.object(READ_TOOL_CATALOG.agent_info.inputSchema),
114
95
  execute: async ({ agent_id, network }) =>
115
96
  cr.agentInfo(agent_id, network ?? defaultNetwork()),
116
97
  }),
117
98
  agent_by_address: tool({
118
99
  // requires [erc8004] in studio.toml
119
- description: "Look up an ERC-8004 agent registration by wallet address.",
120
- inputSchema: z.object({
121
- address: z.string().describe("0x wallet address"),
122
- network: networkArg,
123
- }),
100
+ description: READ_TOOL_CATALOG.agent_by_address.description,
101
+ inputSchema: z.object(READ_TOOL_CATALOG.agent_by_address.inputSchema),
124
102
  execute: async ({ address, network }) =>
125
103
  cr.agentByAddress(address, network ?? defaultNetwork()),
126
104
  }),
@@ -128,22 +106,15 @@ export const LLM_READ_TOOLS: ToolSet = {
128
106
  // --- ERC-8183 jobs (READ-ONLY status/list — writes live in signing.ts) ---
129
107
  job_status: tool({
130
108
  // requires [erc8183] in studio.toml
131
- description: "Read-only ERC-8183 job summary (status, budget, deliverable URL).",
132
- inputSchema: z.object({
133
- job_id: z.number().int().describe("on-chain job id"),
134
- network: networkArg,
135
- }),
109
+ description: READ_TOOL_CATALOG.job_status.description,
110
+ inputSchema: z.object(READ_TOOL_CATALOG.job_status.inputSchema),
136
111
  execute: async ({ job_id, network }) =>
137
112
  cr.jobStatus(job_id, network ?? defaultNetwork()),
138
113
  }),
139
114
  job_list: tool({
140
115
  // requires [erc8183] in studio.toml
141
- description: "List recent ERC-8183 jobs (optionally only this agent's).",
142
- inputSchema: z.object({
143
- limit: z.number().int().optional(),
144
- mine: z.boolean().optional().describe("only jobs assigned to this agent"),
145
- network: networkArg,
146
- }),
116
+ description: READ_TOOL_CATALOG.job_list.description,
117
+ inputSchema: z.object(READ_TOOL_CATALOG.job_list.inputSchema),
147
118
  execute: async ({ limit, mine, network }) =>
148
119
  cr.jobList({ limit, mine, network: network ?? defaultNetwork() }),
149
120
  }),
@@ -225,7 +225,8 @@ export function buildRunWork(): RunWork {
225
225
 
226
226
  function hasErc8183Rail(cfg: TomlTable): boolean {
227
227
  const payments = asTable(cfg.payments);
228
- return asTable(payments?.erc8183) !== null;
228
+ const rail = asTable(payments?.erc8183);
229
+ return rail !== null && rail.enabled !== false;
229
230
  }
230
231
 
231
232
  function asTable(value: unknown): TomlTable | null {
@@ -11,8 +11,9 @@ node = ["@altananetwork/sdk@0.7.1"]
11
11
  node = ["@turnkey/sdk-server@8.1.0", "@turnkey/viem@0.14.34"]
12
12
 
13
13
  [env]
14
- # kind='twak': the twak CLI reads the unlock password from the environment —
15
- # it never goes on a command line.
14
+ # kind='twak': Studio generates this unlock password. Runtime operations read
15
+ # it from the environment; upstream twak requires it briefly on the one-time
16
+ # wallet-create child argv, which Studio never prints.
16
17
  TWAK_WALLET_PASSWORD = "unlocks ~/.twak/wallet.json (twak kind); set in .studio/.env.local"
17
18
  # kind='turnkey': P-256 API credential; the signing key never leaves Turnkey's enclave.
18
19
  TURNKEY_API_PRIVATE_KEY = "Turnkey P-256 API private key (turnkey kind); set in .studio/.env.local"
@@ -9,6 +9,16 @@ description: The single entry point for bnbagent-studio - a TypeScript CLI (`bag
9
9
 
10
10
  Invoked as `/bnbagent-studio <ask>`? Treat `<ask>` as the user's intent and route it through the decision tree below, exactly like a natural-language ask.
11
11
 
12
+ ## Runtime preflight
13
+
14
+ This skill requires `bag` **0.0.13 or newer**. Before following any workflow,
15
+ run the read-only command `bag --version`. If `bag` is missing or older, stop
16
+ and ask the user to run `npm install -g @bnbagent/studio-cli@latest`, then
17
+ repeat the version check. Never install or upgrade a global executable without
18
+ the user's approval.
19
+
20
+ <!-- bag-compatibility: >=0.0.13 -->
21
+
12
22
  ## The single seller runtime model (the invariants)
13
23
 
14
24
  One deployed runtime, one signer: a single valuable Agent serves the selected faces (A2A `src/unifiedMain.ts` on `:9000`, MCP `src/mcpMain.ts` on `:8000/mcp`, or A2A-native `src/dualMain.ts` on `:9000` with tunneled `/mcp`), holds the key, and signs in-process. The ERC-8183 rail exposes exactly two bounded operations - **`negotiate`** (rule-based price clamp + EIP-191 sign; **no LLM touches money**) and **`notify_funded`** (verify the funded job → produce the deliverable → submit on-chain; A2A acks then delivers in the background, MCP delivers synchronously in the tool call). The optional x402 rail adds an anonymous HTTP request at `/x402`; positive prices settle through B402 before work, while explicit zero is FREE passthrough and bypasses the facilitator. It does not expose a general signing tool. Read-only chain tools remain available. ALL signing is fixed entrypoint code in `app/agent/src/signing.ts` or the runtime's bounded x402 payment handler, never an LLM-callable tool. The encrypted keystore lives at the workspace root `.studio/wallets/`, outside the deploy codeLocation, and is injected only via the selected provider's delegated secret channel. `settle` is manual (`bag erc8183 settle`). Full layout and lifecycle details live in the references below - read them before acting.
@@ -22,6 +32,7 @@ One deployed runtime, one signer: a single valuable Agent serves the selected fa
22
32
  | Create a brand new single seller project from zero | `references/bnbagent-studio-scaffolding-agent.md` |
23
33
  | Add wallet / the single seller runtime to an existing TypeScript agent | `references/bnbagent-studio-adding-to-project.md` |
24
34
  | Run / debug / dev / doctor / RPC / balance / incident triage | `references/bnbagent-studio-operating.md` |
35
+ | Report a CLI problem or share product feedback | Run `bag feedback`, review the local JSON bundle before attaching it, and read `references/bnbagent-studio-operating.md`; Studio never uploads or submits it automatically |
25
36
  | Implement what the Agent sells, tune pricing, publish over A2A and/or MCP, defend disputes (seller flow) | `references/bnbagent-studio-selling-via-8183.md` |
26
37
  | Sell one paid or FREE HTTP request through the selected B402-backed x402 or MPP rail (pricing choice; paid merchant application, RSA key, credentials, IP allowlist, activation) | `references/bnbagent-studio-selling-via-b402.md` |
27
38
  | Deploy / redeploy / status / logs / destroy | Run `bag deploy` and explicitly choose a provider. Non-interactive deploy requires `--provider bnb\|aws\|azure --yes` (and `--allow-multiple` when keeping another provider active). Read `references/bnbagent-studio-use-bnb-trial.md`, `references/bnbagent-studio-use-aws-agentcore.md`, or `references/bnbagent-studio-use-azure-foundry.md` for the selected provider. `bag deploy status` lists every recorded provider; multi-deployment logs/verify/destroy require `--provider`. |
@@ -54,7 +65,7 @@ Treat ERC-8183 amounts as decimal strings at CLI/config boundaries and `bigint`
54
65
 
55
66
  ## CLI groups at a glance
56
67
 
57
- `init`, `scan`, `recipe`, `skills`, `wallet`, `erc8004`, `erc8183`, `x402`, `mpp`, `agents`, `config`, `env`, `dev`, `doctor`, `audit`, `deploy`, `platform`, `llm`, `bundle`, `budget` - see `bag --help` for details. `bag deploy [--provider bnb\|aws\|azure] [--backend aws\|azure]` is the primary deploy command; `--backend` is valid only for provider `bnb` and confirms the recipe-derived managed backend. `prepare`, `verify`, `status`, `info`, `destroy`, `logs`, and `fix-gitignore` remain lifecycle subcommands (`deploy agent` is a deprecated compatibility alias). Provider deploy/status/logs/destroy and deploy-time credential validation are delegated to pinned `@bnbagent/deploy-cli@0.5.15`.
68
+ `init`, `scan`, `recipe`, `skills`, `wallet`, `erc8004`, `erc8183`, `x402`, `mpp`, `agents`, `config`, `env`, `dev`, `doctor`, `feedback`, `audit`, `deploy`, `platform`, `llm`, `bundle`, `budget` - see `bag --help` for details. `bag deploy [--provider bnb\|aws\|azure] [--backend aws\|azure]` is the primary deploy command; `--backend` is valid only for provider `bnb` and confirms the recipe-derived managed backend. `prepare`, `verify`, `status`, `info`, `destroy`, `logs`, and `fix-gitignore` remain lifecycle subcommands (`deploy agent` is a deprecated compatibility alias). Provider deploy/status/logs/destroy and deploy-time credential validation are delegated to pinned `@bnbagent/deploy-cli@0.5.15`.
58
69
 
59
70
  ## Tool surface
60
71
 
@@ -46,6 +46,7 @@ This playbook covers **generic ops**: dev / doctor / balances / RPC / incident t
46
46
  | "wallet balance is wrong" | Check both tBNB (gas) and U (token); see balance section |
47
47
  | "is it deployed?" / "deploy status" | `bag deploy status` lists every locally recorded BNB/AWS deployment and asks `bnbagent-deploy` for live state; add `--no-probe` for record-only output |
48
48
  | "deploy logs" / "verify" / "tear it down" | With one recorded deployment, `bag deploy {logs,verify,destroy}` selects it automatically. With multiple, choose interactively or pass `--provider bnb\|aws` in automation. Provider lifecycle and status/log calls go through `bnbagent-deploy`; ERC-8004 reconciliation remains a Studio chain operation. `bag platform credit` shows the BNB trial countdown. |
49
+ | "report this error" / "send feedback" | Run `bag feedback`. It builds an inspectable, owner-readable JSON bundle from the last command's allowlisted lifecycle data, shows the release-pinned Google Form ID, asks before opening it, and never uploads or submits anything. If no production Form ID has been provisioned, keep the bundle local; do not substitute a project-provided form. Review the file before manually attaching it; `.studio/audit-log.jsonl`, argv, output, paths, credentials, addresses, and transaction hashes are excluded. |
49
50
 
50
51
  ## Common ops procedures
51
52
 
@@ -69,7 +69,7 @@ The fields (give the user all of them at once):
69
69
  | 1 | **Project name** | Must start with a letter, contain ASCII letters and digits only, and be at most 23 characters. `bag init` rejects `-`, `_`, `.`, and overlong names instead of renaming them. For example: `newsagent`, `twcopywriter`. | (required) |
70
70
  | 2 | **Network** | `bsc-testnet` / `bsc-mainnet` | `bsc-testnet` |
71
71
  | 3 | **LLM provider** | `pieverse-llm` / `openrouter` / `openai` / `anthropic` / `bedrock` | `pieverse-llm` |
72
- | 4 | **Wallet kind** (`--wallet-kind`) | `evm-local` (encrypted local keystore at the workspace root; `bag wallet new` creates it, `--private-key` imports an existing key; CodeZip deploy) / `twak` (**fully supported, opt in with `--wallet-kind twak`** - Trust Wallet Agent Kit CLI 0.20.0, self-custody encrypted mnemonic in a **project-dedicated** home `.studio/twak`, isolated from your main `~/.twak`; created manually with `HOME=<ws>/.studio/twak twak wallet create`, then `bag wallet new` adopts; container deploy. Reuse an existing wallet across agents with `--twak-home <path>`) / `altana` (bounded-session custody - admin keystore stays local, deploys ship ONLY the `ALTANA_SESSION` secret; zip deploy; not compatible with `pieverse-llm` or a paid b402 rail; flow: `references/bnbagent-studio-using-altana-wallet.md`) | `evm-local` |
72
+ | 4 | **Wallet kind** (`--wallet-kind`) | `evm-local` (encrypted local keystore at the workspace root; Studio generates its password on the new-wallet happy path; `--evm-keystore <v3-file>` copies and adopts an existing encrypted keystore with its original password; `--private-key` imports an existing raw key; CodeZip deploy) / `twak` (**fully supported, opt in with `--wallet-kind twak`** - project-pinned Trust Wallet CLI 0.20.0, self-custody encrypted mnemonic in a **project-dedicated** home `.studio/twak`, isolated from the main `~/.twak`; `bag wallet twak-init` performs credential init/verification, password generation, wallet creation/adoption, and address anchoring without the upstream wizard; container deploy. Reuse an existing wallet across agents with `--twak-home <path>`) / `altana` (bounded-session custody - admin keystore stays local, deploys ship ONLY the `ALTANA_SESSION` secret; zip deploy; not compatible with `pieverse-llm` or a paid b402 rail; flow: `references/bnbagent-studio-using-altana-wallet.md`) | `evm-local` |
73
73
  | 5 | **Storage** | `local` (offline only) / `ipfs` / `s3` / `azure-blob`. Self-hosted deploys use BYOS credentials; managed-platform deploys receive an operator-owned storage endpoint and scoped token through the sealed runtime-secret channel. | `local` |
74
74
  | 6 | **Protocol faces** (`--protocols`) | any non-empty subset of `A2A`, `MCP`, `X402` | `A2A,X402` (`A2A` for Altana) |
75
75
  | 7 | **LLM model** | provider catalogue; for `pieverse-llm` the default `auto/free` runs at $0/token | `auto/free` |
@@ -136,9 +136,11 @@ Build a TodoWrite list. The shape depends on the `wallet kind`. The canonical 8-
136
136
  >
137
137
  > If Bun is missing at deploy time, **PAUSE** and have the USER install it (Bun 1.3+, or set `BNBAGENT_DEPLOY_COMMAND`). Likewise for `bag dev --container` only: the npm `@aws/agentcore` CLI must be present and must win on PATH over the incompatible `bedrock-agentcore-starter-toolkit` shim - global tools on the user's machine, so the user installs them, not you.
138
138
 
139
- > **Onboarding note.** On a human TTY, `bag init` runs steps 3, 4 and 6 automatically (it prompts once for the wallet password, runs `bag wallet new`, zero-deposit-activates Pieverse, and prints faucet URLs). **You (Claude Code) drive `bag init` non-interactively**, so that auto-flow does NOT fire - keep steps 3/4/6 below. Pass `--no-onboard` to `bag init` to make this explicit and deterministic regardless of how the shell wires stdin.
139
+ > **Onboarding note.** On a human TTY, `bag init` runs steps 3, 4 and 6 automatically (a new evm-local wallet gets a CSPRNG password without prompting; `--evm-keystore` instead asks for the existing file's original password; then Studio runs `bag wallet new`, zero-deposit-activates Pieverse, and prints faucet URLs). **You (Claude Code) drive `bag init` non-interactively**, so that auto-flow does NOT fire - keep steps 3/4/6 below. Pass `--no-onboard` to `bag init` to make this explicit and deterministic regardless of how the shell wires stdin.
140
140
 
141
141
  1. `bag init <name> --llm-provider <p> --network <n> --storage-provider <s> --wallet-kind <k> [--protocols <comma-list>] [--rails <8183|b402|both>] [--erc8183-price <base-units>] [--b402-price <usd>] --no-onboard` - scaffold the current workspace. **`<name>` must start with a letter, use ASCII letters and digits only, and be at most 23 characters.** `bag init` rejects `-`, `_`, `.`, and overlong names instead of renaming them. Pass `--wallet-kind evm-local` (default) or `--wallet-kind twak` (twak is fully supported - pass the flag to opt in), and `--storage-provider local` (default) or `ipfs`, per the Stage-1 choices; for twak, add `--twak-home <path>` ONLY if the user wants to reuse an existing wallet (otherwise omit - a project-dedicated `.studio/twak` is the safe default). Omit `--protocols` and `--rails` for the default A2A + X402 faces with both ERC-8183 and B402 rails (all wallet kinds, altana included — its paid B402 payout lands at the admin address). Pass either flag when the user chose another face/rail combination (`--protocol <one>` is only a legacy alias), add `--model <m>` only if the user overrode the provider default, and `--enable-auto-topup` / `--no-auto-topup` only if they made an explicit choice (otherwise omit - consent stays deferred). Pass `--erc8183-price 0` only when the user explicitly chose FREE; omitting the flag preserves the paid 0.1 U default. The canonical stack supports FREE; if a custom deployment is selected, set all three `ERC8183_COMMERCE_ADDRESS`, `ERC8183_ROUTER_ADDRESS`, and `ERC8183_POLICY_ADDRESS` values from that same stack. For B402, pass `--b402-price 0` only after the user explicitly accepts an unrestricted anonymous FREE `/x402` endpoint. FREE bypasses B402 verify/settle and needs no merchant credentials; a positive price keeps the `$0.01` default and requires the paid onboarding playbook. **Destination:** while the trial campaign runs, bare `bag init` (no `--destination`) defaults to `platform` - so pass `--destination self` **explicitly** whenever the user chose their own AWS, otherwise studio.toml silently records `platform` and the confirmation block you echoed no longer matches what was written. Omit `--destination` only when the user actually wants the `platform` 48h testnet trial (the campaign default) - do NOT treat that default as a mistake or re-confirm it; it is the intended behavior while the campaign is open. (Bare init also resolves to `self` once the campaign ends, or when `--network bsc-mainnet` / a non-agentcore `--runtime` is passed.) On the `platform` path `bag init` hard-forces `bsc-testnet`, pins `--runtime agentcore` + packages an artifact (a zip for the default evm-local and altana wallets, a container for twak). For evm-local a wallet key will later leave your machine, so pair it with a throwaway `bag wallet new`; for altana only the bounded session ships - do NOT create a new wallet (full flow: `docs/guides/platform-deploy.md`). Defaults `--runtime agentcore` (the only advertised runtime; the Preview `azure-foundry` runtime remains explicitly selectable but is outside this playbook; there is no `--framework` flag because the AI SDK model/tools story is part of the runtime templates). Creates `<name>/` workspace root + `<name>/app/agent/` (the single sub-project: A2A emits `src/unifiedMain.ts` (the express + A2A entrypoint, one code set for both deploy clouds) + `src/sellerCore.ts` (the protocol-neutral core; executor inherits it) + `src/executor.ts` + `src/agentCard.ts`; MCP emits `src/mcpMain.ts`; both include `src/signing.ts` + `src/tools.ts` + `src/model.ts` + their own `studio.toml` + `package.json` + `tsconfig.json`) + `<name>/agentcore/` (`agentcore.json` + `aws-targets.json`, self-rendered - no agentcore CLI needed at init). The workspace root holds the `agentcore/` deploy descriptor, the `.studio/wallets/` keystore, a thin `package.json` + `pnpm-workspace.yaml`, README, and `.gitignore`. (v1 is seller-only - no `--role`.)
142
+
143
+ To reuse an encrypted evm-local wallet at scaffold time, add `--wallet-kind evm-local --evm-keystore /secure/path/wallet.json`. The input must be Web3 Secret Storage v3. Studio copies it to the private workspace wallet directory and, on a TTY, verifies it using its original password; it never generates a replacement password. For an already-created project that points at a shared wallet directory, set the original password locally and run `bag wallet new --keystore-dir /secure/path/wallets`; the directory and anchor are persisted for later commands.
142
144
  > **Current storage choices:** `--storage-provider` accepts `local`, `ipfs`, `s3`, and `azure-blob`. The latter three are BYOS only for self-hosted deployment; a managed-platform deployment replaces the writer with its injected API endpoint/token.
143
145
  >
144
146
  > **Altana + custom contracts:** Altana sessions remain bound to the canonical ERC-8183 targets. Use `evm-local` for a custom Commerce/Router/Policy stack; doctor and deploy readiness reject this unsupported combination when the ERC-8183 rail is active.
@@ -148,44 +150,19 @@ Build a TodoWrite list. The shape depends on the `wallet kind`. The canonical 8-
148
150
  pnpm install # npm install works too - tooling is the user's choice
149
151
  ```
150
152
  The sub-project's `package.json` carries its deps: `@bnbagent/studio-runtime` (the runtime lib, pinned to the scaffolding CLI's exact version - NOT the CLI itself) + `@bnbagent/sdk` + `ai` (the AI SDK) plus the **protocol-specific** group - A2A adds `@a2a-js/sdk` + `express`, MCP adds `@modelcontextprotocol/sdk` instead (an A2A-only deploy never ships the MCP SDK, and an MCP-only deploy never ships the A2A one). For local dev against unreleased libs, `bag init` vendors local `.tgz` tarballs and points the manifest at them automatically.
151
- 3. **Set the wallet password** - the USER does this, NOT you.
152
-
153
- 🔒 **SECURITY - never route the wallet password through the chat.** It encrypts the key material that is the Agent's sole signing key. Do **NOT** ask the user to type it into the chat, and do **NOT** run any command with the password on the command line (`bag env set <PW_VAR> <literal>`, `twak wallet create --password <literal>`, …) - it would land in the session transcript, be sent to the model API, and hit shell history / `ps`.
154
-
155
- Tell the user to set it **themselves, in their own terminal**, so it never reaches you. The env var depends on the wallet kind:
156
- - **twak** → `TWAK_WALLET_PASSWORD` (the twak CLI reads it itself)
157
- - **evm-local** → `WALLET_PASSWORD`
158
-
159
- ```bash
160
- # In YOUR OWN terminal (not via the agent): open .studio/.env.local and
161
- # set the line for your wallet kind:
162
- # TWAK_WALLET_PASSWORD=<a strong password you choose> # twak
163
- # WALLET_PASSWORD=<a strong password you choose> # evm-local
164
- # Save it. Do not paste the password into this chat.
165
- ```
166
-
167
- `bag` auto-loads `.studio/.env.local` (resolved via the project root), so once the line is set you do NOT need to `source` it or `cd` anywhere special - `bag wallet new` / `bag llm activate` will read it. Wait for the user to confirm they've set it before continuing.
153
+ 3. **Keep all wallet secrets out of chat.** Never ask for, read, echo, or log a wallet password, NaaS Access ID/HMAC secret, mnemonic, or private key. Studio generates new-wallet passwords with the OS cryptographic random source and stores them in `.studio/.env.local` (0600). There is no weak-random fallback.
168
154
 
169
155
  4. **Create / adopt the wallet** - depends on the wallet kind:
170
- - **twak** (fully supported - opt in with `--wallet-kind twak`): `bag init` writes `[wallet].twak_home = "../../.studio/twak"` - a **project-dedicated** wallet isolated from your main `~/.twak`, so a deploy never pushes the main wallet's key material to Secrets Manager. Setting it up is a ONE-TIME job: the user runs the interactive 3-step `twak setup` wizard themselves in their own terminal, then `bag wallet twak-init` creates the wallet (so the password never goes into a command line). Start with the wizard:
171
-
172
- ```bash
173
- HOME=<workspace>/.studio/twak twak setup
174
- ```
175
156
 
176
- **Tell the user exactly what to pick at each wizard step** - it is not obvious and a wrong pick is dangerous:
177
- - **Step 1 (API credentials):** paste Access ID + HMAC secret from https://portal.trustwallet.com/dashboard/apps; WalletConnect Project ID → leave blank, ENTER.
178
- - **Step 2 (wire up harnesses): SELECT NONE, press ENTER** (don't press SPACE/`a`) - never wire twak's signing MCP into Claude Code / Cursor / etc.; studio keeps signing in fixed code, not MCP.
179
- - **Step 3 (wallet): pick `3) Skip for now`**, then create the wallet with the standalone command below. (`1) Create a new agent wallet` persists the password via the OS keychain, which fails on keychain-less environments - "OS keychain cannot persist passwords here … headless / Docker" - and studio unlocks via `TWAK_WALLET_PASSWORD` env anyway. NEVER pick `2) Use WalletConnect` = your main wallet.)
157
+ - **twak**: the generated project pins `@trustwallet/cli@0.20.0`; no global CLI install is needed. `bag init` on a human TTY delegates the full happy path to Studio. For a `--no-onboard` or agent-driven scaffold, ask the user to create a NaaS app at https://portal.trustwallet.com/dashboard/apps and run this command in their terminal, where Studio can collect both values through hidden prompts:
180
158
 
181
159
  ```bash
182
- cd app/agent && bag wallet twak-init # hidden prompt
183
- printf %s "$PW" | bag wallet twak-init --password-stdin # CI / scripts
160
+ cd app/agent && bag wallet twak-init
184
161
  ```
185
162
 
186
- Use UPPER + lower + digit; put that same password in `.studio/.env.local` as `TWAK_WALLET_PASSWORD`. `twak-init` passes `--no-keychain`, which keeps the password out of the OS keychain (no macOS prompt); studio unlocks via the env. (If a macOS prompt _loops_ on a manual `twak` run, do NOT "Reset Default Keychain" - `pkill -9 -f twak`, then re-run with `--no-keychain`.) It also adopts the address into `studio.toml` and echoes it - confirm it's the intended wallet before funding/deploy, and there is no separate `bag wallet new` step. The manual equivalent is `HOME=<workspace>/.studio/twak twak wallet create --password <StrongPw> --no-keychain` followed by `bag wallet new`. Full detail: the `bnbagent-studio-using-twak-wallet.md` reference (in the router skill's `references/` directory). To reuse an EXISTING wallet across agents, scaffold with `bag init --twak-home <path-to-its-home>` instead. Reusing your main `~/.twak` is opt-in only (`--twak-home ~`) and discouraged. Full detail: the `bnbagent-studio-using-twak-wallet.md` reference (in the router skill's `references/` directory).
163
+ Do not run or explain the upstream `twak setup` wizard. `twak-init` uses the project-pinned binary, runs `twak init --json`, verifies an authenticated read, generates and persists `TWAK_WALLET_PASSWORD`, creates/adopts the project-dedicated no-keychain wallet, and anchors the address. No separate `bag wallet new` step exists. For CI, the user may place `TWAK_ACCESS_ID` + `TWAK_HMAC_SECRET` in `.studio/.env.local` themselves; never route them through chat. Reuse an existing wallet only with explicit `--twak-home <home-style-path>`; `--twak-home ~` is a discouraged opt-in to the main wallet. Load `bnbagent-studio-using-twak-wallet.md` for the exact security and deploy contract.
187
164
 
188
- - **evm-local** (default): `bag wallet new` creates the encrypted keystore. To import an existing key, the user pastes it and you immediately run `bag wallet new --private-key <pk>` (the key is written only into the keystore, nowhere else on disk).
165
+ - **evm-local** (default): the new-wallet TTY happy path generates `WALLET_PASSWORD` with the OS CSPRNG, persists it privately, then creates the encrypted keystore in-process. After `--no-onboard`, run `(cd app/agent && bag wallet new --generate-password)` for the same non-interactive safe path. It refuses to replace an existing or anchored wallet. For an existing encrypted v3 file, prefer `bag init ... --wallet-kind evm-local --evm-keystore <path>` and use the file's original password; Studio copies and verifies the file without re-encrypting it. To import a raw key, use the hidden `bag wallet new --private-key` prompt or stdin; never pass the key inline.
189
166
 
190
167
  5. **Fund the wallet - OPTIONAL; do NOT block on it.** The default `auto/free` LLM model runs at $0 and AgentCore deploy consumes no wallet balance, so a brand-new seller can scaffold, run `bag dev`, and deploy with an empty wallet. `bag doctor` and `bag deploy` only **WARN** (never block) on zero balance. Funding is needed later only for: a paid LLM model, on-chain settle, paying positive-price ERC-8183 job buys, or buying/smoking a PAID B402 request. A FREE ERC-8183 buy needs no U escrow or ERC-20 approval, but still needs the ERC-8183 state-changing calls and their gas/paymaster path. A FREE B402/x402 request needs neither token funding nor a facilitator call. When funding is needed, the wallet uses **TWO distinct U balances on TWO chains** (same wallet address, same private key, different chains):
191
168
  - **tBNB (gas)** on BSC testnet: message the official Telegram bot https://t.me/bnbchain_official_bot with `I would like to get tBNB to my wallet <address>` (up to 0.3 tBNB/day; replies with the tx hash). More options: https://docs.bnbchain.org/bnb-smart-chain/developers/faucet/
@@ -231,7 +208,7 @@ For each todo item:
231
208
 
232
209
  **Stop and ask the user** at:
233
210
 
234
- - Step 3 (password): the USER sets it **themselves, in their own terminal** - never through the chat or on a command line (see Step 3's security note). They edit `.studio/.env.local` and set `TWAK_WALLET_PASSWORD` (twak) or `WALLET_PASSWORD` (evm-local). `bag` auto-loads that file, so once it's set `bag wallet new` / `bag llm activate` pick it up - no `source`/`cd` needed. Wait for the user to confirm before continuing.
211
+ - Step 3 (wallet secrets): do not stop for a brand-new evm-local wallet; `bag wallet new --generate-password` uses the OS CSPRNG and writes the private local env file itself. Stop only when the selected flow requires an existing secret: an imported v3 keystore needs its original `WALLET_PASSWORD`, an existing TWAK wallet needs its original `TWAK_WALLET_PASSWORD`, and TWAK credential initialization needs the NaaS values. The USER enters those **themselves, in their own terminal**; never request or route them through chat, argv, or logs. Wait only for completion, not for the value.
235
212
  - Step 5 (funding): OPTIONAL - only stop here if the user explicitly wants a paid LLM model, on-chain settle, or to pay ERC-8183 buys now. Otherwise skip; the `auto/free` default needs no funds.
236
213
  - Step 6 (Pieverse activation): zero-deposit, so it just works - no funding precheck needed. If `bag llm activate` fails on connectivity, retry once.
237
214
  - Step 6b (deliverable storage): skip for `local` and for every managed-platform deploy. Self-hosted IPFS needs its write endpoint, S3 needs namespaced keys unless ambient identity is deliberately configured, and Azure Blob needs a write SAS/service principal unless ambient identity is deliberately configured. Do not ask for secret values in chat; have the user set them with `bag env set`. Self-hosted deploy readiness blocks incomplete storage configuration.
@@ -278,7 +255,7 @@ Edit (from workspace root):
278
255
 
279
256
  - **U is 18 decimals** (not 6 like USDC). The `@bnbagent/studio-runtime/networks` `toRaw`/`fromRaw` helpers handle this.
280
257
  - **`buy_workflow`'s `deadline_minutes`** is the seller's _submission_ window. The on-chain job lifetime is automatically `deadline_minutes + 24h dispute_window`.
281
- - **`bag init` runs wallet onboarding only on a human TTY** (evm-local: prompts for the password and runs `bag wallet new`; twak: adopts the existing twak wallet - never creates one, since `twak wallet create` puts the password on argv). When **Claude Code** runs `bag init` (non-interactively, via the shell tool) that auto-flow does NOT fire, so this skill drives Step 3/4 explicitly - use `--no-onboard` to make the behavior deterministic. This skill bridges the gap by collecting the wallet kind upfront and calling the right form.
258
+ - **`bag init` runs wallet onboarding only on a human TTY** (evm-local: generates and privately persists the password, then creates the keystore; twak: delegates credential init/verification, password generation, create/adopt, and address anchoring to `bag wallet twak-init`). When an agent runs `bag init` non-interactively, use `--no-onboard` for deterministic scaffolding, then follow Step 4 without collecting secrets in chat.
282
259
  - **The agent is the sole key-holder; the key material never enters the deploy package.** For **evm-local** the encrypted keystore lives at the **workspace root** `.studio/wallets/` (outside the `app/agent/` codeLocation, so no packaging path can bundle it); for **twak** the mnemonic lives at `~/.twak` (or `.studio/twak/`), never in the repo. Either way it is injected at deploy via AWS Secrets Manager (default `--secrets-mode secretsmanager`) - `WALLET_KEYSTORE_JSON` / `WALLET_PASSWORD` for evm-local, `TWAK_WALLET_JSON` / `TWAK_CREDENTIALS_JSON` / `TWAK_WALLET_PASSWORD` for twak - reconstructed at cold start, never in the package; the testnet-only `--secrets-mode envvars` fallback is refused on mainnet.
283
260
  - **AgentCore seller endpoints are never anonymous.** `bag deploy --provider aws` provisions the Cognito OAuth2 pool + buyer M2M client itself and prints the token URL / client id / scope to hand to buyers (`bag deploy provision-cognito` is deprecated - a deploy uses its own pool regardless). Locally, `bag dev` runs without Cognito env, so the card omits the scheme and is reachable without a token.
284
261
  - **ERC-8183 does NOT require ERC-8004** at the protocol level (commerce contract doesn't check the identity registry). Local two-agent dev can run end-to-end without ever touching 8004. Use 8004 only when you actually want discoverable identity.
@@ -85,11 +85,11 @@ B402 allowlists the merchant's **outbound** (egress) IPs, the addresses the agen
85
85
  curl ipinfo.io/ip
86
86
  ```
87
87
 
88
- 3. **Self-hosted AgentCore egress (self-deploys)**: operate a restricted B402 Relay on a host with a fixed public egress IP, such as a user-managed VPS, and submit that IP. Set the runtime `B402_BASE_URL` to the Relay base URL. The Relay exposes only `supported`, `verify`, and `settle`, fixes the upstream facilitator, and forwards the signed body and Tesla header allowlist without holding the merchant private key or automatically retrying a settlement transport failure. See the [self-hosted x402 gateway guide](https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/self-hosted-x402-gateway.md) for a TypeScript example.
88
+ 3. **Self-hosted AgentCore egress (self-deploys)**: operate a restricted B402 Relay on a host with a fixed public egress IP, such as a user-managed VPS, and submit that IP. Set the runtime `B402_BASE_URL` to the Relay base URL. The Relay exposes only `supported`, `verify`, and `settle`, fixes the upstream facilitator, and forwards the signed body and Tesla header allowlist without holding the merchant private key or automatically retrying a settlement transport failure. Review the public [BNB Agent Studio deployment guide](https://docs.bnbchain.org/developer-kit/bnbchain-studio/deployment/) for provider constraints; the Studio source checkout keeps the TypeScript gateway example at `docs/guides/self-hosted-x402-gateway.md`.
89
89
 
90
90
  As an alternative, use AWS-supported AgentCore VPC mode with a private subnet, NAT Gateway, and Elastic IP. Submit the Elastic IP and keep `B402_BASE_URL` pointed at the facilitator. Studio does not deploy or manage that AWS network.
91
91
 
92
- 4. **Self-hosted Azure Foundry egress (self-deploys)**: Foundry hosted-agent containers have floating egress just like AgentCore, so the agent must NOT call the facilitator directly. Run the envelope gateway on a Container Apps workload-profiles environment whose subnet has a NAT Gateway with a Standard static public IP, co-host a restricted B402 forwarder there (the AWS guide's Relay example works verbatim — the NAT Gateway replaces its fixed-IP host requirement), point the runtime `B402_BASE_URL` at that forwarder, and submit the NAT Gateway IP. The environment type and VNet cannot be changed after creation; the full recipe (subnet sizing, ingress caveats, minReplicas) is in the [Azure self-hosted x402 gateway guide](https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/self-hosted-x402-gateway-azure.md). Studio does not deploy or manage that Azure network.
92
+ 4. **Self-hosted Azure Foundry egress (self-deploys)**: Foundry hosted-agent containers have floating egress just like AgentCore, so the agent must NOT call the facilitator directly. Run the envelope gateway on a Container Apps workload-profiles environment whose subnet has a NAT Gateway with a Standard static public IP, co-host a restricted B402 forwarder there (the AWS guide's Relay example works verbatim — the NAT Gateway replaces its fixed-IP host requirement), point the runtime `B402_BASE_URL` at that forwarder, and submit the NAT Gateway IP. The environment type and VNet cannot be changed after creation. Review the public [BNB Agent Studio deployment guide](https://docs.bnbchain.org/developer-kit/bnbchain-studio/deployment/) for provider constraints; the Studio source checkout keeps the subnet, ingress, and `minReplicas` recipe at `docs/guides/self-hosted-x402-gateway-azure.md`. Studio does not deploy or manage that Azure network.
93
93
 
94
94
  Do not add the public inbound gateway IP, a transient build-runner IP, or guessed addresses. If the whitelist endpoint is unreachable, stop onboarding and confirm the platform environment with the operator.
95
95
 
@@ -154,7 +154,7 @@ bag deploy --provider bnb # managed platform
154
154
  bag deploy --provider aws # self-hosted AgentCore
155
155
  ```
156
156
 
157
- On the managed platform the deploy summary must say `x402 rail is ACTIVE` (or `ACTIVE in FREE mode`) and print the anonymous `/x402` URL. On a self-hosted AgentCore deploy it says `x402 rail is ACTIVE (self-hosted AgentCore)` or `ACTIVE in FREE mode (self-hosted AgentCore)` (self-hosted Azure Foundry prints the same summary with its own label): the rail runs in-process, but there is no anonymous URL. Operate your own HTTP front that relays envelope-v1 JSON through an authenticated AgentCore invocation. The default Bag self-deploy uses Cognito OAuth over raw HTTPS; AWS SDK/SigV4 is only for a runtime deliberately configured with IAM authorization. PAID also needs your own fixed-egress B402 Relay or equivalent network path. The complete gateway wrapper, response parser, Relay example, and direct-invocation fallback are in the [self-hosted x402 gateway guide](https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/self-hosted-x402-gateway.md). A dormant or forced-dormant summary means the rail was not activated; fix the named credential, runtime, network, or tunnel condition and redeploy.
157
+ On the managed platform the deploy summary must say `x402 rail is ACTIVE` (or `ACTIVE in FREE mode`) and print the anonymous `/x402` URL. On a self-hosted AgentCore deploy it says `x402 rail is ACTIVE (self-hosted AgentCore)` or `ACTIVE in FREE mode (self-hosted AgentCore)` (self-hosted Azure Foundry prints the same summary with its own label): the rail runs in-process, but there is no anonymous URL. Operate your own HTTP front that relays envelope-v1 JSON through an authenticated AgentCore invocation. The default Bag self-deploy uses Cognito OAuth over raw HTTPS; AWS SDK/SigV4 is only for a runtime deliberately configured with IAM authorization. PAID also needs your own fixed-egress B402 Relay or equivalent network path. Review the public [BNB Agent Studio deployment guide](https://docs.bnbchain.org/developer-kit/bnbchain-studio/deployment/) for provider constraints; the Studio source checkout keeps the complete gateway wrapper, response parser, Relay example, and direct-invocation fallback at `docs/guides/self-hosted-x402-gateway.md`. A dormant or forced-dormant summary means the rail was not activated; fix the named credential, runtime, network, or tunnel condition and redeploy.
158
158
 
159
159
  ## Hard rules
160
160
 
@@ -26,13 +26,18 @@ bag init <name> --wallet-kind altana --destination self --no-onboard
26
26
  # Edit <name>/.studio/.env.local and set WALLET_PASSWORD first.
27
27
  cd <name>/app/agent
28
28
  bag wallet new
29
- # fund the printed admin address with ~0.05 tBNB + U
29
+ # after GitHub login, request the configured tBNB + U grant for the admin
30
+ bag wallet fund
30
31
  bag wallet session grant
31
32
  bag wallet session status
32
33
  bag doctor
33
34
  bag dev
34
35
  ```
35
36
 
37
+ `bag wallet fund` always uses the Altana admin's encrypted keystore for an
38
+ EIP-191 ownership signature and sends funds to that same admin address. The
39
+ bounded runtime session is not involved in faucet claims.
40
+
36
41
  Interactive grant recommendations are 10 U/day, 30 days, register=yes. In a non-TTY, pass `--budget-u`, `--expiry-days`, optional `--no-register`, and `--yes`. Stdout from a successful grant is only the session public key.
37
42
 
38
43
  The grant persists the owner-only session, provisions a Commerce allowance no higher than its U-token cap, and approves the quote checker. Every relay-backed management write must return `CONFIRMED`; `PENDING` fails closed and preserves the session file. If either setup step fails after the paid grant, repair both with:
@@ -9,101 +9,49 @@ description: When the user's project has [wallet].kind = "twak" (a fully-support
9
9
 
10
10
  Procedure for setting up and operating the **twak** wallet kind (Trust Wallet Agent Kit CLI) in a bnbagent-studio project. twak is a **fully-supported** wallet kind - opt in at scaffold with `bag init <name> --wallet-kind twak` (`evm-local`, a local keystore, is the default). The wallet is a **self-custody, AES-256-GCM-encrypted mnemonic** the user controls (not a hosted service), living by default in a **project-dedicated** home `.studio/twak` (`[wallet].twak_home`), isolated from your main `~/.twak`. The default kind is `evm-local` (local keystore); re-scaffold with `--wallet-kind twak` to use twak.
11
11
 
12
- ## 1. Install the CLI
12
+ ## 1. CLI installation is project-managed
13
13
 
14
- Needs Node >=22:
14
+ `bag init --wallet-kind twak` pins `@trustwallet/cli@0.20.0` in the generated `app/agent/package.json`; the normal `pnpm install` installs it. Do **not** ask the user for a global installation and do not call the upstream CLI directly. Studio and the runtime resolve `app/agent/node_modules/.bin/twak`, and `bag doctor` / `bag deploy prepare` verify the project-pinned version floor.
15
15
 
16
- ```bash
17
- npm install -g @trustwallet/cli@0.20.0
18
- twak --version
19
- ```
20
-
21
- studio requires **>= 0.20.0** (the SDK forwards `--paymaster-url` on sponsored bsc-testnet writes - the flag first shipped in v0.20.0; older CLIs reject it with "unknown option"); `bag doctor` and `bag deploy prepare` verify the floor.
22
-
23
- ## 2. Create the wallet - one time, in YOUR terminal
24
-
25
- `bag wallet twak-init` drives creation for you (step 3) so you never type the password on a command line; the NaaS setup wizard below still has to be run by hand once, because it is interactive.
26
-
27
- **Every twak command is prefixed with the dedicated home.** Without `HOME=$DH`, twak uses your real `~/.twak` (your MAIN wallet) and macOS pops a login-keychain password prompt. Set it once:
28
-
29
- ```bash
30
- DH=<workspace>/.studio/twak # e.g. ~/proj/.studio/twak
31
- ```
16
+ ## 2. Studio-managed setup - no upstream wizard
32
17
 
33
- **1. Get Trust Wallet NaaS API credentials** (one time; account-level, NOT wallet-specific). Make an app at https://portal.trustwallet.com/dashboard/apps copy its Access ID + HMAC secret. (`twak wallet create` fails with "No API credentials found" without them.)
34
-
35
- **2. Run the setup wizard** - writes the credentials into the dedicated home:
18
+ The user creates a Trust Wallet NaaS app at https://portal.trustwallet.com/dashboard/apps, but must never paste the Access ID, HMAC secret, or wallet password into the AI chat. On a human TTY, `bag init` performs the setup automatically. To retry or complete a non-onboarded scaffold, run from `app/agent`:
36
19
 
37
20
  ```bash
38
- HOME="$DH" twak setup
21
+ bag wallet twak-init
39
22
  ```
40
23
 
41
- - **Step 1 (API credentials):** paste the Access ID + HMAC secret. WalletConnect Project ID → leave blank, ENTER.
42
- - **Step 2 ("which harnesses to wire up"): SELECT NONE - press ENTER** on the empty list (do NOT press SPACE or `a`). 🔒 This would register twak's signing MCP into Claude Code / Cursor / etc., handing wallet+signing power to your AI assistant (and any prompt-injection reaching it) - studio forbids that: signing is fixed `signing.ts` code, the LLM only receives read-only chain tools, and the deployed agent never calls twak via MCP.
43
- - **Step 3 (Wallet "Pick one"): choose `3) Skip for now`** (you create it in the next step). NOT `2) Use WalletConnect with my existing wallet` (binds your main/real wallet).
24
+ This one Studio command:
44
25
 
45
- **3. Create the wallet** (password UPPER + lower + digit, e.g. `Mypasswd01`; `mypasswd01` is rejected). **RECOMMENDED - let studio drive it so you never type the password on a command line** (it resolves the project home from studio.toml, so no `HOME=` juggling):
26
+ 1. Collects the NaaS Access ID and HMAC secret through hidden Studio prompts. It never starts `twak setup` or asks which AI harnesses to wire.
27
+ 2. Runs the project-pinned `twak init --json` with the two credentials in the child environment.
28
+ 3. Performs an authenticated `twak price BNB --chain bsc --json` read. Newly written credentials are removed if this verification fails; pre-existing credentials are never deleted.
29
+ 4. Generates `TWAK_WALLET_PASSWORD` from 32 bytes of the OS cryptographic random source and writes it to `.studio/.env.local` (0600). There is no weak-random fallback and the value is never printed.
30
+ 5. Creates the project-dedicated wallet with `--no-keychain --json`, tightens `.twak/` to 0700 and its credential/wallet files to 0600, reads the BSC address, and anchors it into `studio.toml`.
31
+ 6. Refuses to replace an anchored identity and never overwrites an existing wallet or credential file.
46
32
 
47
- ```bash
48
- bag wallet twak-init # interactive hidden prompt
49
- printf %s "$PW" | bag wallet twak-init --password-stdin # CI / scripts
50
- bag wallet twak-init --password-file pw.txt # file must be chmod 600
51
- ```
33
+ Upstream twak v0.20.0 requires `--password` during wallet creation, so the generated password is briefly present in that one child process's argv. It does not enter the user's shell history, Studio output, diagnostics, or AI transcript. Runtime signing reads it from the environment and does not put it on argv.
52
34
 
53
- It seeds this home's `credentials.json` from `~/.twak` when step 2 was run there, wraps `twak wallet create --password … --no-keychain` (twak requires the flag on its own argv, so the value reaches that short-lived child - it never lands in YOUR shell history), tightens `wallet.json` to mode 600, and adopts the address into studio.toml in one go - so step 5's `bag wallet new` is already done.
35
+ For non-interactive automation, the user can put `TWAK_ACCESS_ID` and `TWAK_HMAC_SECRET` in `.studio/.env.local` themselves before running `bag wallet twak-init`; Studio still generates the wallet password. The legacy `--password-stdin` and `--password-file <0600-file>` options remain explicit compatibility overrides, not the happy path.
54
36
 
55
- Manual alternative (you type the password on argv → `ps` / shell history; acceptable only for a throwaway hot wallet):
37
+ After setup:
56
38
 
57
39
  ```bash
58
- HOME="$DH" twak wallet create --password '<StrongPw>' --no-keychain
40
+ bag wallet show
41
+ bag llm activate
42
+ bag doctor
59
43
  ```
60
44
 
61
- `--no-keychain` keeps the password OUT of the OS keychain - it lives only in `TWAK_WALLET_PASSWORD` (step 4), so creation triggers **no macOS keychain prompt**. Expect: "Agent wallet created successfully / Wallet registered with backend / Generated addresses for 25 chains". (twak then prints "Restart your harness… / Try a sample query…" - that's for MCP users; ignore it, studio doesn't use twak's MCP.)
62
-
63
- > **Already have a wallet here?** If twak says `Wallet already exists. Back up … then delete it`, the wallet is already created - do **NOT** follow the literal "delete it". `wallet.json` is the ONLY copy of your AES-256-GCM encrypted mnemonic; deleting it without the mnemonic backed up loses the funds **forever**. Confirm it's yours (`HOME="$DH" twak wallet addresses`), skip create, and go straight to step 5 - `bag wallet new` just ADOPTS the existing address (idempotent, never destructive). Only recreate if you've safely backed up the mnemonic, and then `mv` `wallet.json` to a `.bak` rather than deleting.
64
-
65
- > **CI / scripts:** use `bag wallet twak-init --password-stdin` / `--password-file` above - it is the supported non-interactive path and works on headless runners (no keychain involved). Avoid the older `TWAK_NONINTERACTIVE=1 TWAK_SETUP_WALLET=create … twak setup` route: it has no `--no-keychain` equivalent, stores the password in the OS keychain, and aborts with `STORAGE_ERROR` on headless / Docker runners.
66
-
67
- **4. Put the unlock password in `.env.local`** - **YOU edit the file** (never through the chat, never `bag env set <literal>` - the password must not reach the assistant or argv). Same value as Step 3:
68
-
69
- ```
70
- # .studio/.env.local
71
- TWAK_WALLET_PASSWORD=<StrongPw>
72
- ```
73
-
74
- studio AND the deployed runtime unlock via this env - the keychain copy is local-only and never deploys, so this line is mandatory or deploy can't sign.
75
-
76
- **5. Anchor + activate** - back in a NORMAL shell (**no `HOME=` prefix**; studio resolves the home from `[wallet].twak_home` itself, and `bag wallet new` ADOPTS the address - it does not create a second wallet):
77
-
78
- ```bash
79
- cd <workspace>/app/agent
80
- bag wallet new # writes the NEW address into studio.toml [wallet].address - confirm it's the new wallet, not your main one
81
- bag llm activate # zero-deposit Pieverse key
82
- bag doctor # all PASS (zero balance is a WARN, fine)
83
- ```
84
-
85
- ### macOS keychain - bypassed by default
86
-
87
- With `--no-keychain` (step 3) the wallet password lives ONLY in `TWAK_WALLET_PASSWORD` (step 4) - twak never reads or writes the OS keychain, so both creation and signing trigger **no macOS password prompt**. studio and the deployed runtime unlock via that env, so nothing is lost by skipping the keychain.
88
-
89
- > **Safety net (you normally never see it):** for the rare case you create a wallet WITHOUT `--no-keychain`, `bag init` (and `bag wallet new`) also auto-creates an isolated, **empty-password** keychain under `$DH/Library/Keychains` - secret-free, scoped to `$DH` (your real login keychain untouched), never deployed. With `--no-keychain` twak doesn't touch any keychain at all.
90
-
91
- > ⚠️ **If you omitted `--no-keychain` and a macOS prompt LOOPS** (or a bare `twak setup` prompted against your **main** login keychain and rejects every password): **Do NOT click "Reset Default Keychain"** - it erases your Wi-Fi passwords, SSH passphrases, and saved app secrets. Quit it with `pkill -9 -f twak`, then recreate the wallet **disk-only**:
92
- >
93
- > ```bash
94
- > HOME="$DH" twak wallet create --password '<StrongPw>' --no-keychain
95
- > ```
96
- >
97
- > and rely on `TWAK_WALLET_PASSWORD` (step 4) to unlock - same end state, no keychain involved.
45
+ No separate `bag wallet new` step is required. An existing wallet is adopted only after Studio verifies its password and reads its address. If its password is not already in `.studio/.env.local`, the user enters it through a hidden Studio prompt; Studio never invents a replacement password for an existing wallet.
98
46
 
99
47
  ### Other wallet placements
100
48
 
101
- `bag init` always writes a project-dedicated `[wallet].twak_home`; the flow above is the default (a brand-new dedicated wallet). Alternatives:
49
+ The default is a new project-dedicated `.studio/twak` home, isolated from the user's main `~/.twak`. Alternatives are explicit:
102
50
 
103
- - **Reuse an existing wallet** across agents `bag init --twak-home <path>` (that wallet's HOME-style dir, containing `.twak/wallet.json`). Same flow: create with `--no-keychain`, unlock via `TWAK_WALLET_PASSWORD`.
104
- - **Your main `~/.twak`** (DISCOURAGED - real funds / bound identities) → opt-in only via `bag init --twak-home ~`, or "yes" to the warned prompt (default "no") when a machine wallet is detected. Recorded as `[wallet].twak_home = <$HOME>`.
51
+ - Reuse an existing wallet across agents with `bag init --twak-home <home-style-path>`; the path contains `.twak/wallet.json`.
52
+ - Reuse the main `~/.twak` only with `bag init --twak-home ~`. This is discouraged because deploy would ship that wallet material through the selected secrets channel.
105
53
 
106
- Each wallet is its own address its own ERC-8004 identity, Pieverse SIWE binding, and secret bundle; `bag doctor` / `bag deploy` resolve the right one via `[wallet].twak_home`.
54
+ Each wallet address has its own ERC-8004 identity, Pieverse SIWE binding, and secret bundle; `bag doctor` / `bag deploy` resolve the configured `[wallet].twak_home`.
107
55
 
108
56
  ## 3. Fund it - and keep it a HOT wallet
109
57
 
@@ -144,7 +92,7 @@ Pieverse attributes x402 topups to the **SIWE-bound payer address** (the paid ca
144
92
  | Custom ERC-8183 targets unavailable | upstream feature request | twak v0.20.0 has no Commerce/Router/Policy address option. Studio doctor/prepare and the SDK fail closed instead of silently executing on canonical contracts; use `evm-local` for a custom ERC-8183 deployment. |
145
93
  | No generic EIP-712 signing | P0 (won't fix) | `[wallet.signing]` is ignored; payments go through the delegated payer's own prechecks + `--max-payment`. Endpoints needing an `Authorization` header _and_ x402 are unavailable (e.g. `bag llm key new --initial-usd > 0` - use `--initial-usd 0` + topup + allocate instead, same end state). |
146
94
  | No wallet import | S-6 | Switching wallet kinds changes your address → re-run `bag 8004 register` (new on-chain identity). |
147
- | Programmatic wallet creation forces password onto argv | S-8 | Bridged by `bag wallet twak-init` (you supply it via stdin / 0600 file / hidden prompt; studio forwards it on the child's argv because twak requires the flag); the manual twak commands remain a fallback. |
95
+ | Programmatic wallet creation forces password onto argv | S-8 | Bridged by `bag wallet twak-init`: Studio generates 32 CSPRNG bytes, persists the value privately before creation, and forwards it only to the short-lived child because twak requires the flag. The value never enters user shell history or output. |
148
96
  | CLI has no daily/monthly caps | - | Studio's policy layer (`[budget].max_per_day_usd`, host allowlist, per-request caps) is the spend authority for both wallet kinds. |
149
97
  | `twak wallet balance --chain bsctestnet` rejects the chain | BUG-031 | Fails with `CHAIN_UNSUPPORTED` even though `wallet address` and `erc8183` accept `bsctestnet`. Use `bag wallet balance` (RPC-based, works on testnet), or raw RPC: `eth_getBalance` for tBNB and an `eth_call` of `balanceOf(address)` on the U token for token balance. |
150
98
  | `twak tx <hash> --chain bsctestnet` rejects the chain | BUG-032 | Same chain-registry gap on the readback path: transactions twak itself just mined on `bsctestnet` cannot be inspected with `twak tx`. Use public RPC (`eth_getTransactionByHash` / `eth_getTransactionReceipt`) or BscScan testnet instead. |
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- TWAK_CLI_MIN_VERSION,
4
- TWAK_CLI_VERSION,
5
- TWAK_NODE_MIN_MAJOR,
6
- twakCreateGuidance,
7
- twakDoubledHomeHint,
8
- twakHomeDir,
9
- twakInstalledVersion,
10
- twakVersionBelowFloor,
11
- twakWalletFile,
12
- whichTwak
13
- } from "./chunk-RO726HJG.js";
14
- export {
15
- TWAK_CLI_MIN_VERSION,
16
- TWAK_CLI_VERSION,
17
- TWAK_NODE_MIN_MAJOR,
18
- twakCreateGuidance,
19
- twakDoubledHomeHint,
20
- twakHomeDir,
21
- twakInstalledVersion,
22
- twakVersionBelowFloor,
23
- twakWalletFile,
24
- whichTwak
25
- };