@kibibot/cli 1.0.0

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,148 @@
1
+ # @kibibot/cli
2
+
3
+ The official KibiBot command-line interface. Deploy tokens on-chain, check balances, manage Kibi Credits, and control your AI agent from the terminal.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @kibibot/cli
9
+ ```
10
+
11
+ ```bash
12
+ kibi --version
13
+ ```
14
+
15
+ ### Run without installing
16
+
17
+ ```bash
18
+ npx @kibibot/cli whoami
19
+ npx @kibibot/cli token create --name MyToken --symbol MTK --chain base
20
+ ```
21
+
22
+ ## Setup
23
+
24
+ ### 1. Get an API key
25
+
26
+ Go to [kibi.bot/settings/api-keys](https://kibi.bot/settings/api-keys) → Create API Key → copy the `kb_...` key.
27
+
28
+ ### 2. Login
29
+
30
+ ```bash
31
+ # Interactive — prompts for API key
32
+ kibi login
33
+
34
+ # Headless — pass key directly
35
+ kibi login --api-key kb_YOUR_KEY
36
+ ```
37
+
38
+ Credentials are stored in `~/.kibi/config.json`. You can also set `KIBI_API_KEY` as an environment variable.
39
+
40
+ ### 3. Verify
41
+
42
+ ```bash
43
+ kibi whoami
44
+ ```
45
+
46
+ ## Commands
47
+
48
+ ### Identity
49
+
50
+ ```bash
51
+ kibi whoami # your account info and wallet addresses
52
+ kibi logout # clear stored credentials
53
+ ```
54
+
55
+ ### Token Creation
56
+
57
+ ```bash
58
+ # Interactive (prompts for name, symbol, chain)
59
+ kibi token create
60
+
61
+ # Headless
62
+ kibi token create --name "MyToken" --symbol MTK --chain base
63
+ kibi token create --name "Moon" --symbol MOON --chain solana --description "To the moon"
64
+ kibi token create --name "Test" --symbol TST --chain base --no-wait # return job ID immediately
65
+
66
+ # Check deployment status
67
+ kibi status 12345
68
+
69
+ # Get token info
70
+ kibi token info 0x1234...
71
+ kibi token info 5Yz8K... --chain solana
72
+
73
+ # List tokens you've created
74
+ kibi tokens created
75
+ kibi tokens created --page 2
76
+ ```
77
+
78
+ Supported chains: `base` · `bsc` · `solana`
79
+
80
+ ### Balances & Quota
81
+
82
+ ```bash
83
+ kibi balances # on-chain wallet balances across all chains
84
+ kibi quota # daily token creation quota per chain
85
+ ```
86
+
87
+ ### Kibi Credits & Kibi LLM Gateway
88
+
89
+ ```bash
90
+ # Check Kibi Credit balance + agent reload config
91
+ kibi llm credits
92
+
93
+ # List available AI models
94
+ kibi llm models
95
+
96
+ # Reload Kibi Credits from trading wallet (requires Agent Reload enabled)
97
+ kibi llm reload
98
+
99
+ # Emergency disable agent reload
100
+ kibi llm reload --disable
101
+
102
+ # Generate provider config for your tool
103
+ kibi llm setup openclaw # OpenClaw config JSON (use with --install to write directly)
104
+ kibi llm setup cursor # Cursor IDE settings
105
+ kibi llm setup claude # Claude Code env vars
106
+ ```
107
+
108
+ ### Skills & Config
109
+
110
+ ```bash
111
+ kibi skills # list all agent capabilities
112
+
113
+ kibi config get # show all config
114
+ kibi config get apiKey # show specific key
115
+ kibi config set apiUrl https://custom.api.url
116
+ ```
117
+
118
+ ## Global Flags
119
+
120
+ | Flag | Description |
121
+ |---|---|
122
+ | `--json` | Machine-readable JSON output |
123
+ | `--debug` | Verbose HTTP request/response logging |
124
+ | `--version` | Print version |
125
+ | `--help` | Print help |
126
+
127
+ ## Configuration
128
+
129
+ Config precedence (highest to lowest):
130
+
131
+ 1. **Environment variable** — `KIBI_API_KEY`
132
+ 2. **Config file** — `~/.kibi/config.json`
133
+ 3. **Defaults** — API URL: `https://api.kibi.bot`, LLM URL: `https://llm.kibi.bot`
134
+
135
+ ## Requirements
136
+
137
+ - Node.js >= 18.0.0
138
+
139
+ ## Links
140
+
141
+ - [Agent & Developer Docs](https://kibi.bot/docs/agent)
142
+ - [API Keys](https://kibi.bot/settings/api-keys)
143
+ - [Kibi Credits](https://kibi.bot/credits)
144
+ - [GitHub Skills](https://github.com/OfficialKibiBot/skills)
145
+
146
+ ## License
147
+
148
+ MIT
package/bin/kibi.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * kibi balances
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerBalances(program: Command): void;
@@ -0,0 +1,60 @@
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, kind) {
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
+ // Show only relevant balances per wallet type
11
+ const balances = kind === 'evm'
12
+ ? [
13
+ ['ETH (Base)', slot.balance_eth, slot.eth_error],
14
+ ['BNB (BSC)', slot.balance_bnb, slot.bnb_error],
15
+ ['USDC (Base)', slot.balance_usdc_base, slot.usdc_base_error],
16
+ ['USDT (BSC)', slot.balance_usdt_bsc, slot.usdt_bsc_error],
17
+ ]
18
+ : [
19
+ ['SOL', slot.balance_sol, slot.sol_error],
20
+ ['USDC (Sol)', slot.balance_usdc_solana, slot.usdc_solana_error],
21
+ ];
22
+ // Always show native balances (even if zero); show stablecoins only if > 0
23
+ const nativeTokens = kind === 'evm' ? ['ETH (Base)', 'BNB (BSC)'] : ['SOL'];
24
+ for (const [name, value, error] of balances) {
25
+ if (error) {
26
+ console.log(` ${name.padEnd(14)} ${chalk.red('error')}`);
27
+ }
28
+ else if (nativeTokens.includes(name) || (value && parseFloat(value) > 0)) {
29
+ const symbol = name.split(' ')[0];
30
+ console.log(` ${name.padEnd(14)} ${fmtBalance(value, symbol)}`);
31
+ }
32
+ }
33
+ console.log();
34
+ }
35
+ export function registerBalances(program) {
36
+ program
37
+ .command('balances')
38
+ .description('Show wallet balances across all chains')
39
+ .action(async (_, cmd) => {
40
+ try {
41
+ const res = await agent.walletBalance();
42
+ const isJson = cmd.optsWithGlobals().json;
43
+ if (isJson) {
44
+ console.log(JSON.stringify(res, null, 2));
45
+ return;
46
+ }
47
+ console.log();
48
+ console.log(chalk.bold.cyan('Wallet Balances'));
49
+ console.log(chalk.dim('─'.repeat(40)));
50
+ console.log();
51
+ printWallet('EVM Main', res.evm_main, 'evm');
52
+ printWallet('EVM Trading', res.evm_trading, 'evm');
53
+ printWallet('Solana Main', res.solana_main, 'solana');
54
+ printWallet('Solana Trading', res.solana_trading, 'solana');
55
+ }
56
+ catch (err) {
57
+ handleApiError(err);
58
+ }
59
+ });
60
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * kibi config get / kibi 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', 'apiUrl', 'llmUrl'];
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:')} ${config.apiUrl || chalk.dim('(not set)')}`);
39
+ console.log(` ${chalk.dim('llmUrl:')} ${config.llmUrl || chalk.dim('(not set)')}`);
40
+ console.log();
41
+ });
42
+ configCmd
43
+ .command('set <key> <value>')
44
+ .description('Set a config value (apiKey, apiUrl, llmUrl)')
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,5 @@
1
+ /**
2
+ * kibi llm models / kibi llm credits / kibi llm setup <target>
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerLlm(program: Command): void;
@@ -0,0 +1,229 @@
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 Kibi Credit balance')
43
+ .action(async (_, cmd) => {
44
+ try {
45
+ const res = await agent.kibiCreditBalance();
46
+ const isJson = cmd.optsWithGlobals().json;
47
+ if (isJson) {
48
+ console.log(JSON.stringify(res, null, 2));
49
+ return;
50
+ }
51
+ printCard('Kibi 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 Kibi 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 KibiBot dashboard.');
88
+ }
89
+ return;
90
+ }
91
+ const isJson = cmd.optsWithGlobals().json;
92
+ const spinner = ora('Reloading Kibi Credits from trading wallet...').start();
93
+ const res = await agent.reloadKibiCredits();
94
+ if (isJson) {
95
+ spinner.stop();
96
+ console.log(JSON.stringify(res, null, 2));
97
+ return;
98
+ }
99
+ spinner.succeed('Reload complete!');
100
+ printCard('Kibi 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 coding tools (cursor, claude, openclaw)')
115
+ .option('--install', 'Write config directly (openclaw only)')
116
+ .action(async (target, opts, cmd) => {
117
+ const config = readConfig();
118
+ const apiKey = config.apiKey || process.env['KIBI_API_KEY'];
119
+ const llmUrl = config.llmUrl || 'https://llm.kibi.bot/v1';
120
+ if (!apiKey) {
121
+ console.error("Error: Not logged in. Run 'kibi login' first.");
122
+ process.exit(1);
123
+ }
124
+ switch (target.toLowerCase()) {
125
+ case 'cursor': {
126
+ console.log();
127
+ console.log(chalk.bold.cyan('Cursor IDE Configuration'));
128
+ console.log(chalk.dim('─'.repeat(40)));
129
+ console.log();
130
+ console.log('Add this to your Cursor settings (Settings → Models → OpenAI API Key):');
131
+ console.log();
132
+ console.log(` ${chalk.bold('API Base URL:')} ${llmUrl}`);
133
+ console.log(` ${chalk.bold('API Key:')} ${apiKey}`);
134
+ console.log();
135
+ console.log(chalk.yellow('⚠ Your API key is shown above. Do not share this output.'));
136
+ console.log(chalk.dim('Then select a Kibi model from the model dropdown.'));
137
+ console.log();
138
+ break;
139
+ }
140
+ case 'claude': {
141
+ console.log();
142
+ console.log(chalk.bold.cyan('Claude Code Configuration'));
143
+ console.log(chalk.dim('─'.repeat(40)));
144
+ console.log();
145
+ console.log('Set these environment variables:');
146
+ console.log();
147
+ console.log(` export ANTHROPIC_BASE_URL="${llmUrl}"`);
148
+ console.log(` export ANTHROPIC_API_KEY="${apiKey}"`);
149
+ console.log();
150
+ console.log(chalk.yellow('⚠ Your API key is shown above. Do not share this output.'));
151
+ console.log(chalk.dim('Then run `claude` as usual.'));
152
+ console.log();
153
+ break;
154
+ }
155
+ case 'openclaw': {
156
+ const openclawConfig = {
157
+ models: {
158
+ mode: 'merge',
159
+ providers: {
160
+ kibi: {
161
+ baseUrl: llmUrl.replace('/v1', ''),
162
+ apiKey: apiKey,
163
+ api: 'openai-completions',
164
+ models: [
165
+ { id: 'claude-haiku-4-5', name: 'Claude Haiku (KibiBot)', api: 'anthropic-messages', contextWindow: 200000, maxTokens: 4096 },
166
+ { id: 'claude-sonnet-4-6', name: 'Claude Sonnet (KibiBot)', api: 'anthropic-messages', contextWindow: 200000, maxTokens: 8192 },
167
+ { id: 'claude-opus-4-6', name: 'Claude Opus (KibiBot)', api: 'anthropic-messages', contextWindow: 200000, maxTokens: 8192 },
168
+ { id: 'gpt-4o', name: 'GPT-4o (KibiBot)', contextWindow: 128000, maxTokens: 16384 },
169
+ { id: 'gpt-4o-mini', name: 'GPT-4o Mini (KibiBot)', contextWindow: 128000, maxTokens: 16384 },
170
+ { id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash (KibiBot)', contextWindow: 1048576, maxTokens: 8192 },
171
+ { id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro (KibiBot)', contextWindow: 1048576, maxTokens: 8192 },
172
+ ],
173
+ },
174
+ },
175
+ },
176
+ };
177
+ if (opts.install) {
178
+ try {
179
+ const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import('node:fs');
180
+ const { join } = await import('node:path');
181
+ const { homedir } = await import('node:os');
182
+ const configDir = join(homedir(), '.openclaw');
183
+ const configPath = join(configDir, 'openclaw.json');
184
+ let existing = {};
185
+ if (existsSync(configPath)) {
186
+ try {
187
+ existing = JSON.parse(readFileSync(configPath, 'utf-8'));
188
+ }
189
+ catch {
190
+ existing = {};
191
+ }
192
+ }
193
+ else {
194
+ mkdirSync(configDir, { recursive: true });
195
+ }
196
+ // Deep merge into models.providers
197
+ existing.models = existing.models || {};
198
+ existing.models.mode = 'merge';
199
+ existing.models.providers = existing.models.providers || {};
200
+ existing.models.providers.kibi = openclawConfig.models.providers.kibi;
201
+ writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
202
+ success(`Kibi provider added to ${configPath}`);
203
+ console.log(chalk.dim(' Restart OpenClaw: openclaw gateway restart'));
204
+ }
205
+ catch (err) {
206
+ console.error(`Error: Failed to write config — ${err instanceof Error ? err.message : err}`);
207
+ process.exit(1);
208
+ }
209
+ }
210
+ else {
211
+ console.log();
212
+ console.log(chalk.bold.cyan('OpenClaw Configuration'));
213
+ console.log(chalk.dim('─'.repeat(40)));
214
+ console.log();
215
+ console.log('Add this to your ~/.openclaw/openclaw.json:');
216
+ console.log();
217
+ console.log(JSON.stringify(openclawConfig, null, 2));
218
+ console.log();
219
+ console.log(chalk.dim('Or run: kibi llm setup openclaw --install'));
220
+ console.log();
221
+ }
222
+ break;
223
+ }
224
+ default:
225
+ console.error(`Error: Unknown target '${target}'. Supported: cursor, claude, openclaw`);
226
+ process.exit(1);
227
+ }
228
+ });
229
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * kibi login / kibi logout
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerLogin(program: Command): void;
@@ -0,0 +1,68 @@
1
+ import chalk from 'chalk';
2
+ import { writeConfig, clearConfig, CONFIG_PATH } from '../lib/config.js';
3
+ import { agent, handleApiError } from '../lib/api.js';
4
+ import { success } from '../lib/display.js';
5
+ export function registerLogin(program) {
6
+ program
7
+ .command('login')
8
+ .description('Authenticate with your KibiBot API key')
9
+ .option('--api-key <key>', 'API key (kb_...)')
10
+ .option('--url', 'Open the KibiBot API keys page in your browser')
11
+ .action(async (opts) => {
12
+ if (opts.url) {
13
+ const url = 'https://kibi.bot/settings/api-keys';
14
+ console.log(`Open this URL to get your API key:\n\n ${chalk.cyan(url)}\n`);
15
+ // Try to open browser
16
+ try {
17
+ const { exec } = await import('node:child_process');
18
+ const cmd = process.platform === 'darwin' ? 'open'
19
+ : process.platform === 'win32' ? 'start'
20
+ : 'xdg-open';
21
+ exec(`${cmd} ${url}`);
22
+ }
23
+ catch {
24
+ // browser open is best-effort
25
+ }
26
+ return;
27
+ }
28
+ let apiKey = opts.apiKey;
29
+ if (!apiKey) {
30
+ // Interactive prompt
31
+ const readline = await import('node:readline');
32
+ const rl = readline.createInterface({
33
+ input: process.stdin,
34
+ output: process.stdout,
35
+ });
36
+ apiKey = await new Promise((resolve) => {
37
+ rl.question('Enter your API key: ', (answer) => {
38
+ rl.close();
39
+ resolve(answer.trim());
40
+ });
41
+ });
42
+ }
43
+ if (!apiKey || !apiKey.startsWith('kb_')) {
44
+ console.error('Error: Invalid API key. Keys start with kb_');
45
+ process.exit(1);
46
+ }
47
+ // Save key first so the API call can use it
48
+ writeConfig({ apiKey });
49
+ // Verify the key works
50
+ try {
51
+ const me = await agent.me();
52
+ success(`Logged in as ${chalk.bold('@' + (me.twitter_username || me.twitter_user_id))}`);
53
+ console.log(` Config saved to ${chalk.dim(CONFIG_PATH)}`);
54
+ }
55
+ catch (err) {
56
+ // Key is bad — clear it
57
+ clearConfig();
58
+ handleApiError(err);
59
+ }
60
+ });
61
+ program
62
+ .command('logout')
63
+ .description('Clear stored credentials')
64
+ .action(() => {
65
+ clearConfig();
66
+ success('Logged out. Credentials cleared.');
67
+ });
68
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * kibi quota
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerQuota(program: Command): void;
@@ -0,0 +1,28 @@
1
+ import chalk from 'chalk';
2
+ import { agent, handleApiError } from '../lib/api.js';
3
+ import { printTable } from '../lib/display.js';
4
+ export function registerQuota(program) {
5
+ program
6
+ .command('quota')
7
+ .description('Show daily token creation quota per chain')
8
+ .action(async (_, cmd) => {
9
+ try {
10
+ const res = await agent.quota();
11
+ const isJson = cmd.optsWithGlobals().json;
12
+ if (isJson) {
13
+ console.log(JSON.stringify(res, null, 2));
14
+ return;
15
+ }
16
+ printTable(['Chain', 'Free Used', 'Free Limit', 'Sponsored', 'Can Create'], res.chains.map((c) => [
17
+ chalk.bold(c.chain.charAt(0).toUpperCase() + c.chain.slice(1)),
18
+ `${c.free_used_today}`,
19
+ `${c.free_limit}`,
20
+ `${c.sponsored_remaining}`,
21
+ c.can_create_paid ? chalk.green('Yes') : chalk.dim('No'),
22
+ ]));
23
+ }
24
+ catch (err) {
25
+ handleApiError(err);
26
+ }
27
+ });
28
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * kibi skills
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerSkills(program: Command): void;
@@ -0,0 +1,32 @@
1
+ import chalk from 'chalk';
2
+ import { agent, handleApiError } from '../lib/api.js';
3
+ export function registerSkills(program) {
4
+ program
5
+ .command('skills')
6
+ .description('List available KibiBot agent capabilities')
7
+ .action(async (_, cmd) => {
8
+ try {
9
+ const res = await agent.skills();
10
+ const isJson = cmd.optsWithGlobals().json;
11
+ if (isJson) {
12
+ console.log(JSON.stringify(res, null, 2));
13
+ return;
14
+ }
15
+ console.log();
16
+ console.log(chalk.bold.cyan(`Available Skills (${res.total})`));
17
+ console.log(chalk.dim('─'.repeat(50)));
18
+ for (const skill of res.skills) {
19
+ console.log();
20
+ console.log(` ${chalk.bold(skill.name)}`);
21
+ console.log(` ${skill.description}`);
22
+ if (skill.example) {
23
+ console.log(` ${chalk.dim(skill.example)}`);
24
+ }
25
+ }
26
+ console.log();
27
+ }
28
+ catch (err) {
29
+ handleApiError(err);
30
+ }
31
+ });
32
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * kibi status <jobId>
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function registerStatus(program: Command): void;