@bfun-bot/cli 1.0.5

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 ADDED
@@ -0,0 +1,93 @@
1
+ # BFunBot CLI
2
+
3
+ Deploy tokens, check balances, and manage your AI agent from the terminal.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @bfun_bot/cli
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ # Authenticate
15
+ bfunbot login
16
+
17
+ # Create a token
18
+ bfunbot token create --name "My Token" --symbol MYT
19
+
20
+ # Check balances
21
+ bfunbot balances
22
+
23
+ # Check fee earnings
24
+ bfunbot fees
25
+ ```
26
+
27
+ ## Commands
28
+
29
+ | Command | Description |
30
+ |---|---|
31
+ | `bfunbot login` | Authenticate with your BFunBot API key |
32
+ | `bfunbot logout` | Clear stored credentials |
33
+ | `bfunbot whoami` | Show current user info |
34
+ | `bfunbot token create` | Create a new token |
35
+ | `bfunbot token info <address>` | Get token details |
36
+ | `bfunbot tokens created` | List tokens you've created |
37
+ | `bfunbot status <jobId>` | Check job status |
38
+ | `bfunbot balances` | Show wallet balances (BSC) |
39
+ | `bfunbot quota` | Show daily API quota |
40
+ | `bfunbot fees` | Check fee earnings summary |
41
+ | `bfunbot fees --platform flap` | Per-platform fee breakdown |
42
+ | `bfunbot llm models` | List available LLM models |
43
+ | `bfunbot llm credits` | Check BFun.bot Credits balance |
44
+ | `bfunbot llm reload` | Reload credits from trading wallet |
45
+ | `bfunbot llm setup openclaw` | Configure OpenClaw integration |
46
+ | `bfunbot skills` | List agent capabilities |
47
+ | `bfunbot config get` | Show current config |
48
+ | `bfunbot config set` | Set a config value |
49
+ | `bfunbot about` | About BFunBot CLI |
50
+
51
+ ## Authentication
52
+
53
+ Get your API key at [bfun.bot/settings/api-keys](https://bfun.bot/settings/api-keys).
54
+
55
+ ```bash
56
+ bfunbot login --api-key bfbot_...
57
+ # or open browser
58
+ bfunbot login --url
59
+ ```
60
+
61
+ Config is stored at `~/.bfunbot/config.json` (permissions: 0600).
62
+
63
+ You can also set `BFUN_API_KEY` environment variable instead of storing a key.
64
+
65
+ ## Networks
66
+
67
+ BSC (BNB Chain) only — flap and fourmeme platforms.
68
+
69
+ ## LLM Gateway
70
+
71
+ The BFun LLM Gateway gives your agent access to frontier AI models (Claude, GPT, Gemini), billed from your BFun.bot Credits balance.
72
+
73
+ ```bash
74
+ # Set up OpenClaw integration
75
+ bfunbot llm setup openclaw --install
76
+
77
+ # Check credit balance
78
+ bfunbot llm credits
79
+
80
+ # Reload credits from trading wallet
81
+ bfunbot llm reload
82
+ ```
83
+
84
+ ## Global Options
85
+
86
+ - `--json` — Machine-readable JSON output
87
+ - `--debug` — Verbose HTTP request/response logging
88
+
89
+ ## Links
90
+
91
+ - Website: [bfun.bot](https://bfun.bot)
92
+ - Docs: [bfun.bot/docs/agent](https://bfun.bot/docs/agent)
93
+ - GitHub: [github.com/BFunBot](https://github.com/BFunBot)
package/bin/bfunbot.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * bfunbot about — branded info card
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerAbout(program: Command): void;
@@ -0,0 +1,62 @@
1
+ import chalk from 'chalk';
2
+ import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';
3
+ import { join, dirname } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { homedir } from 'node:os';
6
+ function getVersion() {
7
+ try {
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8'));
10
+ return pkg.version || 'unknown';
11
+ }
12
+ catch {
13
+ return 'unknown';
14
+ }
15
+ }
16
+ export function registerAbout(program) {
17
+ program
18
+ .command('about')
19
+ .description('About BFunBot CLI')
20
+ .action(() => {
21
+ const version = getVersion();
22
+ const W = 43; // inner width between ║ borders
23
+ function pad(text, displayWidth) {
24
+ const dw = displayWidth ?? text.length;
25
+ const padding = W - dw;
26
+ return text + ' '.repeat(Math.max(0, padding));
27
+ }
28
+ const lines = [
29
+ '',
30
+ ' B F U N . B O T',
31
+ '',
32
+ ' Deploy tokens. Earn fees.',
33
+ ' Self-fund your AI agent.',
34
+ '',
35
+ ` Version ${version}`,
36
+ ' Website bfun.bot',
37
+ ' Docs bfun.bot/docs/agent',
38
+ ' GitHub github.com/BFunBot',
39
+ '',
40
+ ' BSC',
41
+ '',
42
+ ];
43
+ console.log();
44
+ console.log(chalk.cyan(` ╔${'═'.repeat(W)}╗`));
45
+ for (const line of lines) {
46
+ console.log(chalk.cyan(' ║') + pad(line) + chalk.cyan('║'));
47
+ }
48
+ console.log(chalk.cyan(` ╚${'═'.repeat(W)}╝`));
49
+ console.log();
50
+ // Mark as welcomed
51
+ try {
52
+ const bfunDir = join(homedir(), '.bfunbot');
53
+ const marker = join(bfunDir, '.welcomed');
54
+ if (!existsSync(marker)) {
55
+ if (!existsSync(bfunDir))
56
+ mkdirSync(bfunDir, { recursive: true });
57
+ writeFileSync(marker, new Date().toISOString());
58
+ }
59
+ }
60
+ catch { }
61
+ });
62
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * bfunbot balances — BSC only
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerBalances(program: Command): void;
@@ -0,0 +1,48 @@
1
+ import chalk from 'chalk';
2
+ import { agent, handleApiError } from '../lib/api.js';
3
+ import { fmtBalance, shortAddr } from '../lib/display.js';
4
+ function printWallet(label, slot) {
5
+ if (!slot.address) {
6
+ console.log(` ${chalk.dim(label + ':')} ${chalk.dim('Not configured')}`);
7
+ return;
8
+ }
9
+ console.log(` ${chalk.bold(label)} ${chalk.dim(shortAddr(slot.address))}`);
10
+ const balances = [
11
+ ['BNB (BSC)', slot.balance_bnb, slot.bnb_error],
12
+ ['USDT (BSC)', slot.balance_usdt_bsc, slot.usdt_bsc_error],
13
+ ];
14
+ for (const [name, value, error] of balances) {
15
+ if (error) {
16
+ console.log(` ${name.padEnd(14)} ${chalk.red('error')}`);
17
+ }
18
+ else if (name === 'BNB (BSC)' || (value && parseFloat(value) > 0)) {
19
+ const symbol = name.split(' ')[0];
20
+ console.log(` ${name.padEnd(14)} ${fmtBalance(value, symbol)}`);
21
+ }
22
+ }
23
+ console.log();
24
+ }
25
+ export function registerBalances(program) {
26
+ program
27
+ .command('balances')
28
+ .description('Show wallet balances (BSC)')
29
+ .action(async (_, cmd) => {
30
+ try {
31
+ const res = await agent.walletBalance();
32
+ const isJson = cmd.optsWithGlobals().json;
33
+ if (isJson) {
34
+ console.log(JSON.stringify(res, null, 2));
35
+ return;
36
+ }
37
+ console.log();
38
+ console.log(chalk.bold.cyan('Wallet Balances'));
39
+ console.log(chalk.dim('─'.repeat(40)));
40
+ console.log();
41
+ printWallet('EVM Main', res.evm_main);
42
+ printWallet('EVM Trading', res.evm_trading);
43
+ }
44
+ catch (err) {
45
+ handleApiError(err);
46
+ }
47
+ });
48
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * bfunbot config get / bfun config set
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerConfig(program: Command): void;
@@ -0,0 +1,53 @@
1
+ import chalk from 'chalk';
2
+ import { readConfig, setConfigValue, CONFIG_PATH } from '../lib/config.js';
3
+ const VALID_KEYS = ['apiKey'];
4
+ function maskKey(key) {
5
+ if (key.length <= 8)
6
+ return '***';
7
+ return key.slice(0, 6) + '...' + key.slice(-4);
8
+ }
9
+ export function registerConfig(program) {
10
+ const configCmd = program
11
+ .command('config')
12
+ .description('Read or write CLI configuration');
13
+ configCmd
14
+ .command('get [key]')
15
+ .description('Show config values')
16
+ .action((key) => {
17
+ const config = readConfig();
18
+ if (key) {
19
+ if (!VALID_KEYS.includes(key)) {
20
+ console.error(`Error: Unknown key '${key}'. Valid keys: ${VALID_KEYS.join(', ')}`);
21
+ process.exit(1);
22
+ }
23
+ const value = config[key];
24
+ if (value) {
25
+ console.log(key === 'apiKey' ? maskKey(value) : value);
26
+ }
27
+ else {
28
+ console.log(chalk.dim('(not set)'));
29
+ }
30
+ return;
31
+ }
32
+ // Show all
33
+ console.log();
34
+ console.log(chalk.bold.cyan('Configuration'));
35
+ console.log(chalk.dim('─'.repeat(40)));
36
+ console.log(` ${chalk.dim('File:')} ${CONFIG_PATH}`);
37
+ console.log(` ${chalk.dim('apiKey:')} ${config.apiKey ? maskKey(config.apiKey) : chalk.dim('(not set)')}`);
38
+ console.log(` ${chalk.dim('apiUrl:')} ${'https://api.bfun.bot'}`);
39
+ console.log(` ${chalk.dim('llmUrl:')} ${'https://llm.bfun.bot/v1'}`);
40
+ console.log();
41
+ });
42
+ configCmd
43
+ .command('set <key> <value>')
44
+ .description('Set a config value (apiKey)')
45
+ .action((key, value) => {
46
+ if (!VALID_KEYS.includes(key)) {
47
+ console.error(`Error: Unknown key '${key}'. Valid keys: ${VALID_KEYS.join(', ')}`);
48
+ process.exit(1);
49
+ }
50
+ setConfigValue(key, value);
51
+ console.log(chalk.green('✓') + ` ${key} updated`);
52
+ });
53
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * bfunbot fees — summary
3
+ * bfunbot fees --platform flap — per-platform breakdown
4
+ * bfunbot fees --token <addr> — single token fee detail
5
+ */
6
+ import { Command } from 'commander';
7
+ export declare function registerFees(program: Command): void;
@@ -0,0 +1,99 @@
1
+ import chalk from 'chalk';
2
+ import { agent, handleApiError } from '../lib/api.js';
3
+ import { fmtBalance, printTable } from '../lib/display.js';
4
+ const VALID_PLATFORMS = ['flap', 'fourmeme'];
5
+ // ─── Display Helpers ─────────────────────────────────────
6
+ function printSummary(res) {
7
+ console.log();
8
+ console.log(chalk.bold.cyan('Fee Earnings Summary'));
9
+ console.log(chalk.dim('─'.repeat(44)));
10
+ console.log();
11
+ console.log(` ${chalk.bold('BSC (BNB Chain)')} ${chalk.dim(res.bsc.token_count + ' tokens')}`);
12
+ console.log(` ${'Total Earned'.padEnd(22)} ${fmtBalance(res.bsc.total_earned_bnb.toString(), 'BNB')}`);
13
+ console.log();
14
+ }
15
+ function printEarnings(res) {
16
+ console.log();
17
+ console.log(chalk.bold.cyan(`Fee Earnings · BSC`));
18
+ console.log(chalk.dim('─'.repeat(44)));
19
+ console.log();
20
+ printTable(['Platform', 'Earned', 'Tokens'], [
21
+ ['flap', fmtBalance(res.flap.total_earned_bnb.toString(), 'BNB'), res.flap.earning_token_count.toString()],
22
+ ['fourmeme', fmtBalance(res.fourmeme.total_earned_bnb.toString(), 'BNB'), res.fourmeme.earning_token_count.toString()],
23
+ ]);
24
+ }
25
+ function printToken(res) {
26
+ if ('supported' in res && res.supported === false) {
27
+ console.log();
28
+ console.log(chalk.yellow('⚠') + ' ' + res.message);
29
+ console.log();
30
+ return;
31
+ }
32
+ const bsc = res;
33
+ console.log();
34
+ console.log(chalk.bold.cyan('Token Fee Earnings'));
35
+ console.log(chalk.dim('─'.repeat(44)));
36
+ console.log();
37
+ console.log(` ${'Token'.padEnd(14)} ${bsc.token_name} (${bsc.token_symbol})`);
38
+ console.log(` ${'Address'.padEnd(14)} ${chalk.dim(bsc.token_address)}`);
39
+ console.log(` ${'Platform'.padEnd(14)} ${bsc.platform}`);
40
+ console.log(` ${'Earned'.padEnd(14)} ${fmtBalance(bsc.earned_bnb.toString(), 'BNB')}`);
41
+ console.log();
42
+ }
43
+ // ─── Command Registration ─────────────────────────────────
44
+ export function registerFees(program) {
45
+ program
46
+ .command('fees')
47
+ .description('Check fee earnings (summary, per-platform, or per-token)')
48
+ .option('--platform <platform>', 'Platform: flap or fourmeme')
49
+ .option('--token <address>', 'Token contract address')
50
+ .action(async (opts, cmd) => {
51
+ const isJson = cmd.optsWithGlobals().json;
52
+ try {
53
+ // Per-token: requires --platform and --token
54
+ if (opts.token) {
55
+ const platform = opts.platform;
56
+ if (!platform) {
57
+ console.error(chalk.red('Error:') + ' --platform is required with --token. Use: bfunbot fees --platform flap --token <address>');
58
+ process.exit(1);
59
+ }
60
+ if (!VALID_PLATFORMS.includes(platform)) {
61
+ console.error(chalk.red('Error:') + ` Platform must be one of: ${VALID_PLATFORMS.join(', ')}`);
62
+ process.exit(1);
63
+ }
64
+ const res = await agent.feesToken('bsc', platform, opts.token);
65
+ if (isJson) {
66
+ console.log(JSON.stringify(res, null, 2));
67
+ return;
68
+ }
69
+ printToken(res);
70
+ return;
71
+ }
72
+ // Per-platform breakdown
73
+ if (opts.platform) {
74
+ if (!VALID_PLATFORMS.includes(opts.platform)) {
75
+ console.error(chalk.red('Error:') + ` Platform must be one of: ${VALID_PLATFORMS.join(', ')}`);
76
+ process.exit(1);
77
+ }
78
+ // Show full breakdown (both platforms) — the platform flag is for future filtering
79
+ const res = await agent.feesEarnings('bsc');
80
+ if (isJson) {
81
+ console.log(JSON.stringify(res, null, 2));
82
+ return;
83
+ }
84
+ printEarnings(res);
85
+ return;
86
+ }
87
+ // Default: summary
88
+ const res = await agent.feesSummary();
89
+ if (isJson) {
90
+ console.log(JSON.stringify(res, null, 2));
91
+ return;
92
+ }
93
+ printSummary(res);
94
+ }
95
+ catch (err) {
96
+ handleApiError(err);
97
+ }
98
+ });
99
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * bfunbot llm models / bfun llm credits / bfun llm setup <target>
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerLlm(program: Command): void;
@@ -0,0 +1,216 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { agent, llm, handleApiError } from '../lib/api.js';
4
+ import { readConfig } from '../lib/config.js';
5
+ import { printCard, success } from '../lib/display.js';
6
+ export function registerLlm(program) {
7
+ const llmCmd = program
8
+ .command('llm')
9
+ .description('LLM Gateway commands');
10
+ // ── llm models ────────────────────────────────────────
11
+ llmCmd
12
+ .command('models')
13
+ .description('List available LLM models')
14
+ .action(async (_, cmd) => {
15
+ try {
16
+ const res = await llm.models();
17
+ const isJson = cmd.optsWithGlobals().json;
18
+ if (isJson) {
19
+ console.log(JSON.stringify(res, null, 2));
20
+ return;
21
+ }
22
+ const models = res.models || [];
23
+ if (models.length === 0) {
24
+ console.log('\nNo models available.\n');
25
+ return;
26
+ }
27
+ console.log();
28
+ console.log(chalk.bold.cyan(`Available Models (${models.length})`));
29
+ console.log(chalk.dim('─'.repeat(40)));
30
+ for (const modelId of models) {
31
+ console.log(` ${chalk.bold(modelId)}`);
32
+ }
33
+ console.log();
34
+ }
35
+ catch (err) {
36
+ handleApiError(err);
37
+ }
38
+ });
39
+ // ── llm credits ───────────────────────────────────────
40
+ llmCmd
41
+ .command('credits')
42
+ .description('Check your BFun.bot Credits balance')
43
+ .action(async (_, cmd) => {
44
+ try {
45
+ const res = await agent.creditBalance();
46
+ const isJson = cmd.optsWithGlobals().json;
47
+ if (isJson) {
48
+ console.log(JSON.stringify(res, null, 2));
49
+ return;
50
+ }
51
+ printCard('BFun.bot Credits', [
52
+ ['Balance', `$${res.balance_usd}`],
53
+ ]);
54
+ // Show agent reload config
55
+ if (res.agent_reload) {
56
+ const r = res.agent_reload;
57
+ console.log();
58
+ if (r.enabled) {
59
+ console.log(` ${chalk.dim('Agent Reload:')} ${chalk.green('ON')}`);
60
+ console.log(` ${chalk.dim('Amount:')} $${r.amount_usd.toFixed(2)}`);
61
+ console.log(` ${chalk.dim('Daily Limit:')} $${r.daily_limit_usd.toFixed(2)}`);
62
+ console.log(` ${chalk.dim('Chains:')} ${r.chains.join(', ')}`);
63
+ }
64
+ else {
65
+ console.log(` ${chalk.dim('Agent Reload:')} ${chalk.dim('OFF')}`);
66
+ }
67
+ }
68
+ }
69
+ catch (err) {
70
+ handleApiError(err);
71
+ }
72
+ });
73
+ // ── llm reload ────────────────────────────────────────
74
+ llmCmd
75
+ .command('reload')
76
+ .description('Reload BFun.bot Credits from trading wallet')
77
+ .option('--disable', 'Emergency disable agent reload')
78
+ .action(async (opts, cmd) => {
79
+ try {
80
+ if (opts.disable) {
81
+ await agent.disableReload();
82
+ const isJson = cmd.optsWithGlobals().json;
83
+ if (isJson) {
84
+ console.log(JSON.stringify({ disabled: true }));
85
+ }
86
+ else {
87
+ success('Agent reload disabled. Re-enable from your BFunBot dashboard.');
88
+ }
89
+ return;
90
+ }
91
+ const isJson = cmd.optsWithGlobals().json;
92
+ const spinner = ora('Reloading BFun.bot Credits from trading wallet...').start();
93
+ const res = await agent.reloadCredits();
94
+ if (isJson) {
95
+ spinner.stop();
96
+ console.log(JSON.stringify(res, null, 2));
97
+ return;
98
+ }
99
+ spinner.succeed('Reload complete!');
100
+ printCard('BFun.bot Credit Reload', [
101
+ ['Amount', `$${res.amount_usd}`],
102
+ ['Tx Hash', res.tx_hash],
103
+ ['New Balance', res.new_balance_usd ? `$${res.new_balance_usd}` : undefined],
104
+ ['Daily Used', `$${res.daily_used_usd} / $${res.daily_remaining_usd} remaining`],
105
+ ]);
106
+ }
107
+ catch (err) {
108
+ handleApiError(err);
109
+ }
110
+ });
111
+ // ── llm setup ─────────────────────────────────────────
112
+ llmCmd
113
+ .command('setup <target>')
114
+ .description('Generate config for OpenClaw')
115
+ .option('--install', 'Write config directly to ~/.openclaw/openclaw.json')
116
+ .action(async (target, opts, cmd) => {
117
+ const config = readConfig();
118
+ const apiKey = config.apiKey || process.env['BFUN_API_KEY'];
119
+ if (!apiKey) {
120
+ console.error("Error: Not logged in. Run 'bfunbot login' first.");
121
+ process.exit(1);
122
+ }
123
+ switch (target.toLowerCase()) {
124
+ case 'openclaw': {
125
+ // Fetch model catalog from API — always up-to-date
126
+ let apiConfig;
127
+ try {
128
+ apiConfig = await llm.openclawConfig();
129
+ }
130
+ catch (err) {
131
+ console.error('Error: Could not fetch model catalog from BFunBot API.');
132
+ if (err instanceof Error)
133
+ console.error(` ${err.message}`);
134
+ process.exit(1);
135
+ }
136
+ // Build allowlist from fetched models
137
+ const allowlist = {};
138
+ for (const m of apiConfig.models) {
139
+ allowlist[`bfunbot/${m.id}`] = { alias: m.id };
140
+ }
141
+ const openclawConfig = {
142
+ models: {
143
+ mode: 'merge',
144
+ providers: {
145
+ bfunbot: {
146
+ baseUrl: apiConfig.baseUrl,
147
+ apiKey: apiKey,
148
+ api: apiConfig.api,
149
+ models: apiConfig.models.map(({ input, ...rest }) => rest),
150
+ },
151
+ },
152
+ },
153
+ agents: {
154
+ defaults: {
155
+ models: allowlist,
156
+ },
157
+ },
158
+ };
159
+ if (opts.install) {
160
+ try {
161
+ const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import('node:fs');
162
+ const { join } = await import('node:path');
163
+ const { homedir } = await import('node:os');
164
+ const configDir = join(homedir(), '.openclaw');
165
+ const configPath = join(configDir, 'openclaw.json');
166
+ let existing = {};
167
+ if (existsSync(configPath)) {
168
+ try {
169
+ existing = JSON.parse(readFileSync(configPath, 'utf-8'));
170
+ }
171
+ catch {
172
+ existing = {};
173
+ }
174
+ }
175
+ else {
176
+ mkdirSync(configDir, { recursive: true });
177
+ }
178
+ // Deep merge providers
179
+ existing.models = existing.models || {};
180
+ existing.models.mode = 'merge';
181
+ existing.models.providers = existing.models.providers || {};
182
+ existing.models.providers.bfunbot = openclawConfig.models.providers.bfunbot;
183
+ // Deep merge agents.defaults.models (allowlist + aliases)
184
+ existing.agents = existing.agents || {};
185
+ existing.agents.defaults = existing.agents.defaults || {};
186
+ existing.agents.defaults.models = existing.agents.defaults.models || {};
187
+ Object.assign(existing.agents.defaults.models, openclawConfig.agents.defaults.models);
188
+ writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
189
+ success(`BFunBot provider added to ${configPath}`);
190
+ console.log(chalk.dim(' Restart OpenClaw: openclaw gateway restart'));
191
+ }
192
+ catch (err) {
193
+ console.error(`Error: Failed to write config — ${err instanceof Error ? err.message : err}`);
194
+ process.exit(1);
195
+ }
196
+ }
197
+ else {
198
+ console.log();
199
+ console.log(chalk.bold.cyan('OpenClaw Configuration'));
200
+ console.log(chalk.dim('─'.repeat(40)));
201
+ console.log();
202
+ console.log('Add this to your ~/.openclaw/openclaw.json:');
203
+ console.log();
204
+ console.log(JSON.stringify(openclawConfig, null, 2));
205
+ console.log();
206
+ console.log(chalk.dim('Or run: bfunbot llm setup openclaw --install'));
207
+ console.log();
208
+ }
209
+ break;
210
+ }
211
+ default:
212
+ console.error(`Error: Unknown target '${target}'. Supported: openclaw`);
213
+ process.exit(1);
214
+ }
215
+ });
216
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * bfunbot login / bfun logout
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerLogin(program: Command): void;