@otonix/cli 1.7.0 → 2.1.2

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/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # @otonix/cli
2
2
 
3
- Command-line tool for the [Otonix](https://otonix.tech) sovereign compute platform.
4
-
5
- Initialize, register, and manage autonomous AI agents from your terminal. Includes built-in access to the Bankr LLM Gateway for multi-model AI inference.
3
+ Otonix CLI deploy autonomous agent tokens on Base chain via Clanker v3.1 (LP Legacy).
6
4
 
7
5
  ## Install
8
6
 
@@ -10,278 +8,82 @@ Initialize, register, and manage autonomous AI agents from your terminal. Includ
10
8
  npm install -g @otonix/cli
11
9
  ```
12
10
 
13
- Or run directly:
11
+ Or run locally (dev):
14
12
 
15
13
  ```bash
16
- npx @otonix/cli <command>
14
+ bash cli/otonix.sh <command>
17
15
  ```
18
16
 
19
17
  ## Quick Start
20
18
 
21
19
  ```bash
22
- # 1. Generate an API key (requires dashboard token)
23
- otonix keygen my-vps-key
20
+ # 1. Generate a new Base creator wallet
21
+ otonix wallet generate
24
22
 
25
- # 2. Configure the CLI
26
- otonix init
23
+ # 2. Fund the wallet
24
+ # → Send ≥200 $OTX (agent activation)
25
+ # → Send ETH for gas
27
26
 
28
- # 3. Register your agent
29
- otonix register --name my-agent --model claude-opus-4-6
27
+ # 3. Create an agent (generates isolated Base wallet)
28
+ otonix agent:create --name "MyAgent"
30
29
 
31
- # 4. Start heartbeat loop
32
- otonix heartbeat:loop
30
+ # 4. Fund agent wallet with ~0.002 ETH (shown after create)
33
31
 
34
- # 5. Log actions
35
- otonix log "Trade executed BTC/USDC" --category trading
32
+ # 5. Deploy a token!
33
+ otonix launch token \
34
+ --agent MyAgent \
35
+ --name "CoolToken" \
36
+ --ticker "COOL" \
37
+ --description "My agent token"
36
38
  ```
37
39
 
38
40
  ## Commands
39
41
 
40
- ### Setup
41
-
42
- | Command | Description |
43
- |---------|-------------|
44
- | `otonix init` | Configure API key and endpoint interactively |
45
- | `otonix keygen <name>` | Generate a new API key (requires dashboard token) |
46
- | `otonix whoami` | Show current configuration |
47
-
48
- ### Agent Management
49
-
50
- | Command | Description |
51
- |---------|-------------|
52
- | `otonix register` | Register an agent on this VPS |
53
- | `otonix status` | Show current agent status |
54
- | `otonix heartbeat` | Send a single heartbeat ping |
55
- | `otonix heartbeat:loop` | Start continuous heartbeat (Ctrl+C to stop) |
56
- | `otonix log <message>` | Log an agent action |
57
- | `otonix actions` | Show agent action log |
58
-
59
- ### Infrastructure
60
-
61
- | Command | Description |
62
- |---------|-------------|
63
- | `otonix agents` | List all connected agents |
64
- | `otonix sandboxes` | List VPS sandboxes |
65
- | `otonix domains` | List registered domains |
66
-
67
- ### Credits
68
-
69
- | Command | Description |
70
- |---------|-------------|
71
- | `otonix credits [agentId]` | Show agent credit balance |
72
- | `otonix credits:transfer` | Transfer credits between agents |
73
- | `otonix credits:history [agentId]` | Show credit transaction history |
74
-
75
- ### Templates
76
-
77
- | Command | Description |
78
- |---------|-------------|
79
- | `otonix templates` | List all available agent templates |
80
- | `otonix templates:info <slug>` | Show template details by slug |
81
- | `otonix templates:deploy` | Deploy an agent from a template |
82
-
83
- ### Platform
84
-
85
- | Command | Description |
86
- |---------|-------------|
87
- | `otonix engine` | Show autonomic engine status |
88
- | `otonix marketplace` | List marketplace services |
89
- | `otonix x402` | Show x402 payment configuration |
90
-
91
- ### LLM Gateway (Bankr)
92
-
93
- Access multi-model AI inference directly from your terminal. Supports Claude, GPT, Gemini, Kimi, Qwen, and more via the [Bankr LLM Gateway](https://bankr.bot/llm).
94
-
95
- | Command | Description |
96
- |---------|-------------|
97
- | `otonix llm:init <key>` | Configure Bankr LLM Gateway API key |
98
- | `otonix llm:models` | List available AI models |
99
- | `otonix llm:chat <prompt>` | Send a chat completion request |
100
- | `otonix llm:usage` | Show LLM usage summary |
101
- | `otonix llm:health` | Check gateway health status |
102
-
103
- #### LLM Setup
104
-
105
- Get your Bankr API key from [bankr.bot/api](https://bankr.bot/api) (make sure LLM Gateway access is enabled):
42
+ ### Wallet
106
43
 
107
44
  ```bash
108
- otonix llm:init bk_YOUR_API_KEY
45
+ otonix wallet generate # Generate new Base creator wallet
46
+ otonix wallet import # Import wallet from private key
47
+ otonix wallet export # Show private key (careful!)
48
+ otonix wallet balance # Show ETH + $OTX balance
49
+ otonix wallet address # Show wallet address
109
50
  ```
110
51
 
111
- #### LLM Examples
52
+ ### Agents
112
53
 
113
54
  ```bash
114
- # List available models
115
- otonix llm:models
116
-
117
- # Chat with default model (claude-haiku-4.5)
118
- otonix llm:chat "What is sovereign compute?"
119
-
120
- # Chat with a specific model
121
- otonix llm:chat "Analyze BTC price action" --model gpt-5-mini
122
-
123
- # Check usage (last 7 days)
124
- otonix llm:usage --days 7
125
-
126
- # Check gateway health
127
- otonix llm:health
55
+ otonix agent:create --name MyAgent # Create isolated agent wallet (requires 200 $OTX)
56
+ otonix agent:info MyAgent # Show agent address + balances
57
+ otonix agent:list # List all agents
58
+ otonix agent:remove MyAgent # Remove agent from local config
128
59
  ```
129
60
 
130
- ## Command Options
131
-
132
- ### `otonix register`
133
-
134
- ```bash
135
- otonix register --name my-agent --model claude-opus-4-6 --wallet 0x... --interval 60
136
- ```
137
-
138
- | Option | Default | Description |
139
- |--------|---------|-------------|
140
- | `--name` | (interactive) | Agent name |
141
- | `--model` | `claude-opus-4-6` | AI model |
142
- | `--wallet` | — | Wallet address for payments |
143
- | `--interval` | `60` | Heartbeat interval in seconds |
144
-
145
- ### `otonix log`
61
+ ### Launch
146
62
 
147
63
  ```bash
148
- otonix log "Task completed" --category compute --details "Processed 1000 records"
64
+ otonix launch token \
65
+ --agent MyAgent \
66
+ --name "CoolToken" \
67
+ --ticker "COOL" \
68
+ --image "https://..." \ # Optional
69
+ --description "My token" \ # Optional
70
+ --mcap 10 \ # Initial market cap in ETH (default: 10)
71
+ --devbuy 0 # Dev buy in ETH (default: 0)
149
72
  ```
150
73
 
151
- | Option | Default | Description |
152
- |--------|---------|-------------|
153
- | `--category` | `system` | Action category |
154
- | `--details` | — | Additional details |
74
+ ## Config
155
75
 
156
- ### `otonix actions`
157
-
158
- ```bash
159
- otonix actions --limit 50
160
- ```
161
-
162
- | Option | Default | Description |
163
- |--------|---------|-------------|
164
- | `--limit` | `20` | Number of actions to show |
165
-
166
- ### `otonix credits:transfer`
167
-
168
- ```bash
169
- otonix credits:transfer --from <agentId> --to <agentId> --amount 10 --desc "Payment"
170
- ```
171
-
172
- | Option | Default | Description |
173
- |--------|---------|-------------|
174
- | `--from` | (interactive) | Source agent ID |
175
- | `--to` | (interactive) | Destination agent ID |
176
- | `--amount` | (interactive) | Amount in USDC |
177
- | `--desc` | — | Transfer description |
178
-
179
- ### `otonix templates:deploy`
180
-
181
- ```bash
182
- otonix templates:deploy --template trading-bot --name my-trader --vps 10.0.1.1 --wallet 0x...
183
- ```
184
-
185
- | Option | Default | Description |
186
- |--------|---------|-------------|
187
- | `--template` | (interactive) | Template slug |
188
- | `--name` | (interactive) | Agent name |
189
- | `--vps` | — | VPS IP address |
190
- | `--wallet` | — | Wallet address |
191
-
192
- ### `otonix llm:chat`
193
-
194
- ```bash
195
- otonix llm:chat "Your prompt here" --model claude-haiku-4.5
196
- ```
197
-
198
- | Option | Default | Description |
199
- |--------|---------|-------------|
200
- | `--model` | `claude-haiku-4.5` | AI model to use |
201
-
202
- ### `otonix llm:usage`
203
-
204
- ```bash
205
- otonix llm:usage --days 7
206
- ```
207
-
208
- | Option | Default | Description |
209
- |--------|---------|-------------|
210
- | `--days` | `30` | Number of days to show |
211
-
212
- ## Configuration
213
-
214
- Config is stored at `~/.otonix/config.json` with file permissions `600`.
215
-
216
- ```json
217
- {
218
- "apiKey": "otonix_xxxx",
219
- "endpoint": "https://app.otonix.tech",
220
- "agentId": "uuid-xxxx",
221
- "agentName": "my-agent",
222
- "bankrApiKey": "bk_xxxx"
223
- }
224
- ```
225
-
226
- ## Example Session
227
-
228
- ```
229
- $ otonix init
230
- Otonix CLI Setup
231
-
232
- Endpoint [https://app.otonix.tech]:
233
- API Key (otonix_xxx): otonix_a1b2c3d4e5f6...
234
-
235
- Config saved to /root/.otonix/config.json
236
- Authenticated successfully.
237
-
238
- $ otonix register --name sentinel-01
239
- Agent Registered:
240
- ID: e2998be4-b77c-495e-a535-a6e4ca9dc768
241
- Name: sentinel-01
242
- Model: claude-opus-4-6
243
- VPS IP: 10.0.1.1
244
- Tier: active
245
- Interval: 60s
246
-
247
- $ otonix llm:init bk_4GYZ...WXFKD
248
- Bankr LLM Gateway key saved.
249
- Gateway: https://llm.bankr.bot
250
- Key: bk_4GY...XFKD
251
-
252
- $ otonix llm:chat "What infrastructure should I monitor?"
253
- Model: claude-haiku-4.5
254
- Prompt: What infrastructure should I monitor?
255
-
256
- Thinking...
257
-
258
- Focus on CPU usage, memory consumption, disk I/O, network latency,
259
- and service uptime. Set up alerts for anomalies in each metric.
260
-
261
- Tokens: 24 in / 87 out
262
- Model: claude-haiku-4.5
263
-
264
- $ otonix heartbeat
265
- Heartbeat sent — sentinel-01 [active] tier:active credits:$50.00
266
-
267
- $ otonix engine
268
- Autonomic Engine Status:
269
- Running: yes
270
- Last Cycle: 45s ago
271
- Tier Updates: 0
272
- Heal Attempts: 0
273
- Renewals: 0/0
274
- Cherry Servers: configured
275
- Vercel Domains: configured
276
- ```
76
+ Stored at `~/.otonix/config.json`. Contains wallet and agent private keys — keep it safe.
277
77
 
278
- ## Links
78
+ ## Technical Details
279
79
 
280
- - [Platform](https://app.otonix.tech)
281
- - [Website](https://otonix.tech)
282
- - [SDK](https://www.npmjs.com/package/@otonix/sdk)
283
- - [GitHub](https://github.com/otonix-ai)
80
+ - **LP Protocol**: Clanker v4 (Uniswap v4, POOL_POSITIONS.Standard)
81
+ - **Paired Token**: WETH on Base (`0x4200000000000000000000000000000000000006`)
82
+ - **Fee split**: 80% creator (WETH) / 20% Otonix treasury
83
+ - **Chain**: Base Mainnet
284
84
 
285
- ## License
85
+ ## Requirements
286
86
 
287
- MIT
87
+ - Node.js ≥ 18
88
+ - ≥200 $OTX on creator wallet (Base)
89
+ - ETH in agent wallet for gas (~0.001–0.003 ETH per deploy)
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function agentCommand(program: Command): void;
@@ -0,0 +1,283 @@
1
+ import { confirm } from "@inquirer/prompts";
2
+ import ora from "ora";
3
+ import chalk from "chalk";
4
+ import { loadConfig, saveConfig, OTONIX_TREASURY } from "../lib/config.js";
5
+ import { generateWallet, getEthBalance, getOtxBalance, formatOtx, sendOtx, OTX_REQUIRED, publicClient, } from "../lib/chain.js";
6
+ import { header, row, success, failure, info, br, warn, mono } from "../lib/display.js";
7
+ export function agentCommand(program) {
8
+ program
9
+ .command("agent:create")
10
+ .description("Create a new autonomous agent with an isolated Base wallet")
11
+ .requiredOption("--name <name>", "Agent name (alphanumeric, no spaces)")
12
+ .action(async (opts) => {
13
+ header("Create Agent");
14
+ const name = opts.name.trim();
15
+ if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
16
+ failure("Agent name must be alphanumeric (a-z, 0-9, _, -)");
17
+ process.exit(1);
18
+ }
19
+ const cfg = loadConfig();
20
+ if (!cfg.wallet) {
21
+ failure("No wallet found. Run: otonix wallet generate first.");
22
+ process.exit(1);
23
+ }
24
+ if (cfg.agents[name]) {
25
+ const overwrite = await confirm({
26
+ message: `Agent "${name}" already exists. Replace it?`,
27
+ default: false,
28
+ });
29
+ if (!overwrite) {
30
+ info("Cancelled.");
31
+ return;
32
+ }
33
+ }
34
+ const spinner = ora("Generating isolated agent wallet on Base...").start();
35
+ await new Promise(r => setTimeout(r, 600));
36
+ const agent = generateWallet();
37
+ spinner.stop();
38
+ cfg.agents[name] = {
39
+ address: agent.address,
40
+ privateKey: agent.privateKey,
41
+ createdAt: new Date().toISOString(),
42
+ registered: false,
43
+ };
44
+ saveConfig(cfg);
45
+ success(`Agent "${name}" created!`);
46
+ br();
47
+ row("Agent name", name);
48
+ row("Agent address", agent.address);
49
+ row("Created at", new Date().toLocaleString());
50
+ row("Status", chalk.yellow("⊘ Not registered"));
51
+ br();
52
+ console.log(chalk.dim("Next — register this agent by sending 200 $OTX to:"));
53
+ console.log(" " + chalk.white(OTONIX_TREASURY));
54
+ br();
55
+ console.log(chalk.dim("Then register (auto-sends 200 $OTX):"));
56
+ console.log(" " + mono(`otonix agent:register --name ${name}`));
57
+ });
58
+ program
59
+ .command("agent:register")
60
+ .description("Register an agent — auto-sends 200 $OTX to Otonix treasury and activates it")
61
+ .requiredOption("--name <name>", "Agent name to register")
62
+ .action(async (opts) => {
63
+ header("Agent Registration");
64
+ const cfg = loadConfig();
65
+ const agent = cfg.agents[opts.name];
66
+ if (!agent) {
67
+ failure(`Agent "${opts.name}" not found. Run: otonix agent:create --name ${opts.name}`);
68
+ process.exit(1);
69
+ }
70
+ if (agent.registered) {
71
+ success(`Agent "${opts.name}" is already registered!`);
72
+ br();
73
+ row("Status", chalk.green("✓ Registered & Active"));
74
+ row("Tx hash", agent.registerTxHash ?? "—");
75
+ row("Registered at", agent.registeredAt ? new Date(agent.registeredAt).toLocaleString() : "—");
76
+ return;
77
+ }
78
+ if (!cfg.wallet) {
79
+ failure("No creator wallet found. Run: otonix wallet generate");
80
+ process.exit(1);
81
+ }
82
+ const balSpinner = ora("Checking creator wallet balance...").start();
83
+ let otxBal;
84
+ let ethBal;
85
+ try {
86
+ [otxBal, ethBal] = await Promise.all([
87
+ getOtxBalance(cfg.wallet.address),
88
+ getEthBalance(cfg.wallet.address),
89
+ ]);
90
+ }
91
+ catch {
92
+ balSpinner.stop();
93
+ failure("Failed to fetch balances. Check your connection.");
94
+ process.exit(1);
95
+ }
96
+ balSpinner.stop();
97
+ br();
98
+ row("Creator wallet", cfg.wallet.address);
99
+ row("$OTX balance", formatOtx(otxBal) + " OTX");
100
+ row("ETH balance", parseFloat(ethBal).toFixed(6) + " ETH (for gas)");
101
+ row("Registration fee", "200 $OTX → Otonix treasury");
102
+ row("Treasury", OTONIX_TREASURY);
103
+ br();
104
+ if (otxBal < OTX_REQUIRED) {
105
+ failure(`Insufficient $OTX. Need 200.000, have ${formatOtx(otxBal)}.`);
106
+ info("Buy $OTX at: https://dexscreener.com/base/0xF7E2a6226Ffe0693DD85406AC3A8917cbea5DC40");
107
+ process.exit(1);
108
+ }
109
+ if (parseFloat(ethBal) < 0.0001) {
110
+ failure("Insufficient ETH for gas. Send a small amount of ETH (Base) to your creator wallet.");
111
+ info("Creator wallet: " + cfg.wallet.address);
112
+ process.exit(1);
113
+ }
114
+ const confirmed = await confirm({
115
+ message: `Send 200 $OTX from your creator wallet to Otonix treasury to activate "${opts.name}"?`,
116
+ default: true,
117
+ });
118
+ if (!confirmed) {
119
+ info("Cancelled.");
120
+ return;
121
+ }
122
+ const sendSpinner = ora("Sending 200 $OTX to Otonix treasury...").start();
123
+ let txHash;
124
+ try {
125
+ txHash = await sendOtx(cfg.wallet.privateKey, OTONIX_TREASURY, OTX_REQUIRED);
126
+ }
127
+ catch (err) {
128
+ sendSpinner.stop();
129
+ const msg = err instanceof Error ? err.message : String(err);
130
+ failure("Failed to send $OTX: " + msg.slice(0, 120));
131
+ process.exit(1);
132
+ }
133
+ sendSpinner.text = `Waiting for confirmation... (${txHash.slice(0, 18)}...)`;
134
+ try {
135
+ const receipt = await publicClient.waitForTransactionReceipt({
136
+ hash: txHash,
137
+ timeout: 60_000,
138
+ });
139
+ sendSpinner.stop();
140
+ if (receipt.status !== "success") {
141
+ failure("Transaction failed on-chain.");
142
+ info("Tx: https://basescan.org/tx/" + txHash);
143
+ process.exit(1);
144
+ }
145
+ cfg.agents[opts.name].registered = true;
146
+ cfg.agents[opts.name].registerTxHash = txHash;
147
+ cfg.agents[opts.name].registeredAt = new Date().toISOString();
148
+ saveConfig(cfg);
149
+ br();
150
+ success(`Agent "${opts.name}" is now registered!`);
151
+ br();
152
+ row("Agent name", opts.name);
153
+ row("Status", chalk.green("✓ Registered & Active"));
154
+ row("OTX sent", "200.000 OTX");
155
+ row("Tx hash", txHash);
156
+ row("Basescan", "https://basescan.org/tx/" + txHash);
157
+ br();
158
+ console.log(chalk.dim("You can now deploy tokens. Fund the agent with ETH first:"));
159
+ console.log(" " + chalk.dim("Agent address:") + " " + chalk.white(agent.address));
160
+ br();
161
+ console.log(chalk.dim("Then deploy:"));
162
+ console.log(" " + mono(`otonix launch token --agent ${opts.name} --name "MyToken" --ticker "MTK" --image "https://..." --description "..."`));
163
+ }
164
+ catch (err) {
165
+ sendSpinner.stop();
166
+ const msg = err instanceof Error ? err.message : String(err);
167
+ failure("Tx sent but confirmation timed out: " + msg.slice(0, 100));
168
+ info("Check manually: https://basescan.org/tx/" + txHash);
169
+ process.exit(1);
170
+ }
171
+ });
172
+ program
173
+ .command("agent:info")
174
+ .description("Show info and balances for an agent")
175
+ .argument("<name>", "Agent name")
176
+ .action(async (name) => {
177
+ header(`Agent: ${name}`);
178
+ const cfg = loadConfig();
179
+ const agent = cfg.agents[name];
180
+ if (!agent) {
181
+ failure(`Agent "${name}" not found. Run: otonix agent:list`);
182
+ process.exit(1);
183
+ }
184
+ const spinner = ora("Fetching balances from Base...").start();
185
+ try {
186
+ const [eth, otx] = await Promise.all([
187
+ getEthBalance(agent.address),
188
+ getOtxBalance(agent.address),
189
+ ]);
190
+ spinner.stop();
191
+ br();
192
+ row("Agent name", name);
193
+ row("Address", agent.address);
194
+ row("Created at", new Date(agent.createdAt).toLocaleString());
195
+ row("Status", agent.registered
196
+ ? chalk.green("✓ Registered & Active")
197
+ : chalk.yellow("⊘ Not registered — run: otonix agent:register --name " + name));
198
+ if (agent.registerTxHash)
199
+ row("Register tx", agent.registerTxHash);
200
+ br();
201
+ row("ETH balance", parseFloat(eth).toFixed(6) + " ETH");
202
+ row("$OTX balance", formatOtx(otx) + " OTX");
203
+ br();
204
+ const ethNum = parseFloat(eth);
205
+ if (!agent.registered) {
206
+ console.log(warn("⊘ ") + chalk.dim("Not registered — run this to activate:"));
207
+ console.log(" " + chalk.cyan(`otonix agent:register --name ${name}`));
208
+ console.log(" " + chalk.dim("(auto-sends 200 $OTX from your creator wallet)"));
209
+ }
210
+ else if (ethNum < 0.0005) {
211
+ console.log(warn("⚠ ") + chalk.dim("Low ETH — fund this address with ≥0.001 ETH for gas:"));
212
+ console.log(" " + chalk.white(agent.address));
213
+ }
214
+ else {
215
+ console.log(chalk.green("✓ ") + chalk.dim("Ready to deploy tokens"));
216
+ }
217
+ }
218
+ catch {
219
+ spinner.stop();
220
+ failure("Failed to fetch balances.");
221
+ process.exit(1);
222
+ }
223
+ });
224
+ program
225
+ .command("agent:list")
226
+ .description("List all your agents")
227
+ .action(async () => {
228
+ header("Your Agents");
229
+ const cfg = loadConfig();
230
+ const names = Object.keys(cfg.agents);
231
+ if (names.length === 0) {
232
+ br();
233
+ info("No agents yet. Create one:");
234
+ info(' otonix agent:create --name "MyAgent"');
235
+ return;
236
+ }
237
+ br();
238
+ const spinner = ora(`Fetching balances for ${names.length} agent(s)...`).start();
239
+ const results = await Promise.all(names.map(async (n) => {
240
+ const a = cfg.agents[n];
241
+ try {
242
+ const eth = await getEthBalance(a.address);
243
+ return { name: n, address: a.address, eth: parseFloat(eth).toFixed(5), registered: a.registered };
244
+ }
245
+ catch {
246
+ return { name: n, address: a.address, eth: "—", registered: a.registered };
247
+ }
248
+ }));
249
+ spinner.stop();
250
+ for (const r of results) {
251
+ const status = r.registered ? chalk.green("✓") : chalk.yellow("⊘");
252
+ console.log(status + " " +
253
+ chalk.bold.white(r.name.padEnd(16)) +
254
+ chalk.dim(r.address.slice(0, 10) + "...") +
255
+ " " +
256
+ chalk.yellow(r.eth + " ETH"));
257
+ }
258
+ br();
259
+ info(`${names.length} agent(s) total`);
260
+ });
261
+ program
262
+ .command("agent:remove")
263
+ .description("Remove an agent from local config")
264
+ .argument("<name>", "Agent name")
265
+ .action(async (name) => {
266
+ const cfg = loadConfig();
267
+ if (!cfg.agents[name]) {
268
+ failure(`Agent "${name}" not found.`);
269
+ process.exit(1);
270
+ }
271
+ const ok = await confirm({
272
+ message: `Remove agent "${name}" (${cfg.agents[name].address})? This only removes local config, not on-chain.`,
273
+ default: false,
274
+ });
275
+ if (!ok) {
276
+ info("Cancelled.");
277
+ return;
278
+ }
279
+ delete cfg.agents[name];
280
+ saveConfig(cfg);
281
+ success(`Agent "${name}" removed from local config.`);
282
+ });
283
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function launchCommand(program: Command): void;