pluribus-cli 0.1.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.
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ import { program } from 'commander';
3
+ import { printBanner } from '../src/utils/banner.js';
4
+ import { importAgent } from '../src/commands/import.js';
5
+ import { registerAgent } from '../src/commands/register.js';
6
+ import { initAgent } from '../src/commands/init.js';
7
+ import { deployAgent } from '../src/commands/deploy.js';
8
+ import { listAgents } from '../src/commands/list.js';
9
+ import { networkStatus } from '../src/commands/status.js';
10
+ import { submitTask } from '../src/commands/submit.js';
11
+ import { stake, unstake } from '../src/commands/stake.js';
12
+ import { balance } from '../src/commands/balance.js';
13
+ import { logs } from '../src/commands/logs.js';
14
+ import { configCmd } from '../src/commands/config.js';
15
+
16
+ program
17
+ .name('pluribus')
18
+ .description('Pluribus CLI — Many Agents. One Mind.')
19
+ .version('0.1.0', '-v, --version', 'Show CLI version')
20
+ .addHelpText('beforeAll', () => {
21
+ printBanner();
22
+ return '';
23
+ });
24
+
25
+ // ─── import ─────────────────────────────────────────────────────────────────
26
+ program
27
+ .command('import [agent-id]')
28
+ .description('Import an existing agent into the Pluribus network')
29
+ .option('-p, --platform <platform>', 'Agent framework (virtuals, eliza, langchain, etc.)')
30
+ .option('-s, --stake <amount>', '$PLUR to stake')
31
+ .action(importAgent);
32
+
33
+ // ─── register ───────────────────────────────────────────────────────────────
34
+ program
35
+ .command('register')
36
+ .description('Register a new agent and stake $PLUR to join the network')
37
+ .option('-n, --name <name>', 'Agent name')
38
+ .option('-e, --endpoint <url>', 'Webhook endpoint URL')
39
+ .action(registerAgent);
40
+
41
+ // ─── init ────────────────────────────────────────────────────────────────────
42
+ program
43
+ .command('init [name]')
44
+ .description('Scaffold a new Pluribus agent project')
45
+ .option('-t, --template <template>', 'Starter template (default, research, social, onchain)')
46
+ .action(initAgent);
47
+
48
+ // ─── deploy ──────────────────────────────────────────────────────────────────
49
+ program
50
+ .command('deploy')
51
+ .description('Deploy your agent to the Pluribus network')
52
+ .option('-c, --config <path>', 'Path to pluribus.config.json', 'pluribus.config.json')
53
+ .action(deployAgent);
54
+
55
+ // ─── list ─────────────────────────────────────────────────────────────────────
56
+ program
57
+ .command('list')
58
+ .alias('ls')
59
+ .description('List agents registered on the network')
60
+ .option('-t, --type <type>', 'Filter by capability type')
61
+ .option('--mine', 'Show only your registered agents')
62
+ .action(listAgents);
63
+
64
+ // ─── status ──────────────────────────────────────────────────────────────────
65
+ program
66
+ .command('status')
67
+ .description('Show Pluribus network and protocol status')
68
+ .action(networkStatus);
69
+
70
+ // ─── submit ──────────────────────────────────────────────────────────────────
71
+ program
72
+ .command('submit [task]')
73
+ .description('Submit a task to the Pluribus agent network')
74
+ .option('-t, --type <type>', 'Task type (research, social, monitoring, onchain, auto)')
75
+ .option('-p, --plur <amount>', '$PLUR payment for the task', '0.5')
76
+ .action(submitTask);
77
+
78
+ // ─── stake ───────────────────────────────────────────────────────────────────
79
+ program
80
+ .command('stake [amount]')
81
+ .description('Stake $PLUR to earn yield from network task fees')
82
+ .option('-w, --wallet <address>', 'Wallet address')
83
+ .option('--tier <tier>', 'Staking tier (sentinel, archon, sovereign)')
84
+ .action(stake);
85
+
86
+ // ─── unstake ─────────────────────────────────────────────────────────────────
87
+ program
88
+ .command('unstake [amount]')
89
+ .description('Unstake $PLUR from the network')
90
+ .option('-w, --wallet <address>', 'Wallet address')
91
+ .action(unstake);
92
+
93
+ // ─── balance ─────────────────────────────────────────────────────────────────
94
+ program
95
+ .command('balance [address]')
96
+ .description('Check $PLUR balance for a wallet address')
97
+ .action(balance);
98
+
99
+ // ─── logs ─────────────────────────────────────────────────────────────────────
100
+ program
101
+ .command('logs [agent-id]')
102
+ .description('Stream live logs from an agent or task')
103
+ .option('-f, --follow', 'Follow log output in real time')
104
+ .option('-n, --lines <n>', 'Number of recent lines to show', '50')
105
+ .action(logs);
106
+
107
+ // ─── config ───────────────────────────────────────────────────────────────────
108
+ program
109
+ .command('config [action]')
110
+ .description('Manage CLI configuration (show | set | reset)')
111
+ .action(configCmd);
112
+
113
+ // Default: show banner + help if no command
114
+ if (process.argv.length === 2) {
115
+ printBanner();
116
+ program.outputHelp();
117
+ process.exit(0);
118
+ }
119
+
120
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "pluribus-cli",
3
+ "version": "0.1.0",
4
+ "description": "Pluribus CLI — Register, manage, and deploy AI agents on the Pluribus multi-agent coordination protocol",
5
+ "type": "module",
6
+ "bin": {
7
+ "pluribus": "./bin/pluribus.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node bin/pluribus.js"
11
+ },
12
+ "keywords": ["pluribus", "ai", "agents", "base", "web3", "cli", "multi-agent"],
13
+ "author": "Pluribus Protocol",
14
+ "license": "MIT",
15
+ "dependencies": {
16
+ "chalk": "^5.6.2",
17
+ "commander": "^14.0.3",
18
+ "inquirer": "^13.3.0",
19
+ "ora": "^9.3.0"
20
+ },
21
+ "engines": {
22
+ "node": ">=18.0.0"
23
+ }
24
+ }
@@ -0,0 +1,50 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { label, printDivider, info, warn } from '../utils/banner.js';
4
+
5
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
6
+
7
+ export async function balance(address, options) {
8
+ const inquirer = (await import('inquirer')).default;
9
+
10
+ console.log('');
11
+ console.log(chalk.cyan.bold(' → $PLUR Balance'));
12
+ console.log('');
13
+
14
+ if (!address) {
15
+ const answers = await inquirer.prompt([
16
+ {
17
+ type: 'input',
18
+ name: 'address',
19
+ message: chalk.white('Wallet address (0x...):'),
20
+ prefix: chalk.cyan(' ▸'),
21
+ validate: v => v.startsWith('0x') && v.length === 42 ? true : 'Enter a valid Ethereum address',
22
+ },
23
+ ]);
24
+ address = answers.address;
25
+ }
26
+
27
+ console.log('');
28
+ const spinner = ora({ text: chalk.dim('Querying Base network...'), spinner: 'dots', color: 'cyan' }).start();
29
+ await sleep(900);
30
+ spinner.succeed(chalk.green('Balance retrieved'));
31
+
32
+ console.log('');
33
+ console.log(chalk.cyan.bold(' Wallet'));
34
+ printDivider();
35
+ label('Address:', address);
36
+ label('Network:', 'Base Mainnet');
37
+ console.log('');
38
+
39
+ console.log(chalk.cyan.bold(' $PLUR Balance'));
40
+ printDivider();
41
+ label('Available:', chalk.cyan('— (token not yet launched)'));
42
+ label('Staked:', chalk.cyan('—'));
43
+ label('Earned:', chalk.cyan('—'));
44
+ label('Total:', chalk.cyan('—'));
45
+ console.log('');
46
+
47
+ warn('$PLUR launches with the Pluribus network. Stay tuned.');
48
+ info(`Track launch: ${chalk.underline('https://pluribus.xyz')}`);
49
+ console.log('');
50
+ }
@@ -0,0 +1,108 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import fs from 'fs';
4
+ import os from 'os';
5
+ import path from 'path';
6
+ import { label, printDivider, info, success } from '../utils/banner.js';
7
+
8
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
9
+
10
+ const CONFIG_PATH = path.join(os.homedir(), '.pluribus', 'config.json');
11
+
12
+ function loadConfig() {
13
+ try {
14
+ return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
15
+ } catch {
16
+ return {
17
+ rpcUrl: 'https://mainnet.base.org',
18
+ wallet: '',
19
+ apiKey: '',
20
+ network: 'base-mainnet',
21
+ };
22
+ }
23
+ }
24
+
25
+ function saveConfig(cfg) {
26
+ fs.mkdirSync(path.dirname(CONFIG_PATH), { recursive: true });
27
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
28
+ }
29
+
30
+ export async function configCmd(action, options) {
31
+ const inquirer = (await import('inquirer')).default;
32
+
33
+ console.log('');
34
+ console.log(chalk.cyan.bold(' → CLI Configuration'));
35
+ console.log('');
36
+
37
+ const cfg = loadConfig();
38
+
39
+ if (action === 'show' || !action) {
40
+ console.log(chalk.cyan.bold(' Current Configuration'));
41
+ printDivider();
42
+ label('Config file:', CONFIG_PATH);
43
+ label('Network:', cfg.network || 'base-mainnet');
44
+ label('RPC URL:', cfg.rpcUrl || chalk.dim('not set'));
45
+ label('Wallet:', cfg.wallet || chalk.dim('not set'));
46
+ label('API Key:', cfg.apiKey ? chalk.green('● set') : chalk.dim('not set'));
47
+ console.log('');
48
+ return;
49
+ }
50
+
51
+ if (action === 'set') {
52
+ const answers = await inquirer.prompt([
53
+ {
54
+ type: 'list',
55
+ name: 'network',
56
+ message: chalk.white('Network:'),
57
+ prefix: chalk.cyan(' ▸'),
58
+ choices: [
59
+ { name: 'Base Mainnet', value: 'base-mainnet' },
60
+ { name: 'Base Sepolia (testnet)', value: 'base-sepolia' },
61
+ ],
62
+ default: cfg.network,
63
+ },
64
+ {
65
+ type: 'input',
66
+ name: 'rpcUrl',
67
+ message: chalk.white('RPC URL:'),
68
+ prefix: chalk.cyan(' ▸'),
69
+ default: cfg.rpcUrl || 'https://mainnet.base.org',
70
+ },
71
+ {
72
+ type: 'input',
73
+ name: 'wallet',
74
+ message: chalk.white('Default wallet address (0x...):'),
75
+ prefix: chalk.cyan(' ▸'),
76
+ default: cfg.wallet,
77
+ },
78
+ {
79
+ type: 'password',
80
+ name: 'apiKey',
81
+ message: chalk.white('Pluribus API key (leave blank to skip):'),
82
+ prefix: chalk.cyan(' ▸'),
83
+ mask: '●',
84
+ },
85
+ ]);
86
+
87
+ const newCfg = {
88
+ network: answers.network,
89
+ rpcUrl: answers.rpcUrl,
90
+ wallet: answers.wallet,
91
+ apiKey: answers.apiKey || cfg.apiKey,
92
+ };
93
+
94
+ const spinner = ora({ text: chalk.dim('Saving configuration...'), spinner: 'dots', color: 'cyan' }).start();
95
+ await sleep(400);
96
+ saveConfig(newCfg);
97
+ spinner.succeed(chalk.green('Configuration saved'));
98
+ console.log('');
99
+ label('Saved to:', CONFIG_PATH);
100
+ console.log('');
101
+
102
+ } else if (action === 'reset') {
103
+ const defaultCfg = { rpcUrl: 'https://mainnet.base.org', wallet: '', apiKey: '', network: 'base-mainnet' };
104
+ saveConfig(defaultCfg);
105
+ success('Configuration reset to defaults.');
106
+ console.log('');
107
+ }
108
+ }
@@ -0,0 +1,58 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import fs from 'fs';
4
+ import { label, printDivider, warn, info, success, error } from '../utils/banner.js';
5
+
6
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
7
+
8
+ export async function deployAgent(options) {
9
+ console.log('');
10
+ console.log(chalk.cyan.bold(' → Deploy Agent'));
11
+ console.log(chalk.dim(' Deploy your agent to the Pluribus network'));
12
+ console.log('');
13
+
14
+ // Check for pluribus.config.json
15
+ if (!fs.existsSync('pluribus.config.json')) {
16
+ error('No pluribus.config.json found in current directory.');
17
+ info(`Run ${chalk.cyan('pluribus init')} to scaffold a new agent, or navigate to your agent directory.`);
18
+ console.log('');
19
+ process.exit(1);
20
+ }
21
+
22
+ let config;
23
+ try {
24
+ config = JSON.parse(fs.readFileSync('pluribus.config.json', 'utf8'));
25
+ } catch {
26
+ error('Invalid pluribus.config.json — check JSON syntax.');
27
+ process.exit(1);
28
+ }
29
+
30
+ console.log(chalk.cyan.bold(' Deployment Config'));
31
+ printDivider();
32
+ label('Agent Name:', config.name || '—');
33
+ label('Version:', config.version || '0.1.0');
34
+ label('Capabilities:', (config.capabilities || []).join(', '));
35
+ label('Endpoint:', config.endpoint || '—');
36
+ label('Network:', config.network || 'base-mainnet');
37
+ label('Stake Tier:', config.stake?.tier || '—');
38
+ console.log('');
39
+
40
+ const spinner = ora({ text: chalk.dim('Validating configuration...'), spinner: 'dots', color: 'cyan' }).start();
41
+ await sleep(700);
42
+ spinner.text = chalk.dim('Checking endpoint health...');
43
+ await sleep(600);
44
+ spinner.text = chalk.dim('Verifying stake requirements...');
45
+ await sleep(500);
46
+ spinner.text = chalk.dim('Staging on-chain deployment...');
47
+ await sleep(800);
48
+ spinner.succeed(chalk.green('Deployment staged'));
49
+
50
+ console.log('');
51
+ label('Status:', chalk.yellow('Staged — pending network launch'));
52
+ label('Estimated Launch:', chalk.cyan('Soon™'));
53
+ console.log('');
54
+
55
+ warn('Deployment will execute when the Pluribus network goes live on Base.');
56
+ info(`Monitor status: ${chalk.cyan('pluribus status')}`);
57
+ console.log('');
58
+ }
@@ -0,0 +1,128 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { createRequire } from 'module';
4
+ import { success, error, info, warn, label, printDivider } from '../utils/banner.js';
5
+
6
+ export async function importAgent(agentId, options) {
7
+ const { select, input, confirm } = await import('@inquirer/prompts').catch(() => {
8
+ return import('inquirer').then(m => m.default.prompt ? { select: null, input: null, confirm: null } : {});
9
+ }).catch(() => ({ select: null, input: null, confirm: null }));
10
+
11
+ console.log('');
12
+ console.log(chalk.cyan.bold(' → Import Agent into Pluribus'));
13
+ console.log(chalk.dim(' Connect an existing agent to the network'));
14
+ console.log('');
15
+
16
+ if (!agentId) {
17
+ // Interactive mode
18
+ const inquirer = (await import('inquirer')).default;
19
+
20
+ const answers = await inquirer.prompt([
21
+ {
22
+ type: 'input',
23
+ name: 'agentId',
24
+ message: chalk.white('Agent ID or endpoint URL:'),
25
+ prefix: chalk.cyan(' ▸'),
26
+ validate: v => v.length > 0 ? true : 'Agent ID is required',
27
+ },
28
+ {
29
+ type: 'list',
30
+ name: 'platform',
31
+ message: chalk.white('Agent framework:'),
32
+ prefix: chalk.cyan(' ▸'),
33
+ choices: [
34
+ { name: 'Virtuals Protocol', value: 'virtuals' },
35
+ { name: 'ElizaOS', value: 'eliza' },
36
+ { name: 'LangChain', value: 'langchain' },
37
+ { name: 'AutoGPT', value: 'autogpt' },
38
+ { name: 'CrewAI', value: 'crewai' },
39
+ { name: 'Custom / Other', value: 'custom' },
40
+ ],
41
+ },
42
+ {
43
+ type: 'checkbox',
44
+ name: 'capabilities',
45
+ message: chalk.white('Declare capabilities:'),
46
+ prefix: chalk.cyan(' ▸'),
47
+ choices: [
48
+ { name: 'Research & Analysis', value: 'research' },
49
+ { name: 'Social Media', value: 'social' },
50
+ { name: 'Onchain Execution', value: 'onchain' },
51
+ { name: 'Wallet Monitoring', value: 'monitoring' },
52
+ { name: 'Content Generation', value: 'content' },
53
+ { name: 'Data Retrieval', value: 'data' },
54
+ ],
55
+ validate: v => v.length > 0 ? true : 'Select at least one capability',
56
+ },
57
+ {
58
+ type: 'input',
59
+ name: 'stakeAmount',
60
+ message: chalk.white('$PLUR to stake (minimum required to join):'),
61
+ prefix: chalk.cyan(' ▸'),
62
+ default: '1000',
63
+ validate: v => !isNaN(Number(v)) && Number(v) > 0 ? true : 'Enter a valid amount',
64
+ },
65
+ ]);
66
+
67
+ agentId = answers.agentId;
68
+
69
+ console.log('');
70
+ printDivider();
71
+ console.log('');
72
+
73
+ const spinner = ora({
74
+ text: chalk.dim('Verifying agent endpoint...'),
75
+ spinner: 'dots',
76
+ color: 'cyan',
77
+ }).start();
78
+
79
+ await sleep(1200);
80
+ spinner.text = chalk.dim('Checking stake requirements...');
81
+ await sleep(800);
82
+ spinner.text = chalk.dim('Validating capabilities...');
83
+ await sleep(700);
84
+ spinner.succeed(chalk.green('Agent verified'));
85
+
86
+ console.log('');
87
+ console.log(chalk.cyan.bold(' Registration Preview'));
88
+ printDivider();
89
+ label('Agent ID:', agentId);
90
+ label('Platform:', answers.platform);
91
+ label('Capabilities:', answers.capabilities.join(', '));
92
+ label('Stake Amount:', `${Number(answers.stakeAmount).toLocaleString()} $PLUR`);
93
+ label('Status:', chalk.yellow('Pending — awaiting mainnet launch'));
94
+ console.log('');
95
+
96
+ warn('Mainnet launch is coming soon. Your agent config has been saved locally.');
97
+ info('Run ' + chalk.cyan('pluribus list') + ' to view your staged agents.');
98
+ info('Run ' + chalk.cyan('pluribus deploy') + ' once the network is live.');
99
+ console.log('');
100
+
101
+ } else {
102
+ // Direct import with ID
103
+ const spinner = ora({
104
+ text: chalk.dim(`Importing agent ${chalk.cyan(agentId)}...`),
105
+ spinner: 'dots',
106
+ color: 'cyan',
107
+ }).start();
108
+
109
+ await sleep(900);
110
+ spinner.text = chalk.dim('Resolving agent metadata...');
111
+ await sleep(700);
112
+ spinner.text = chalk.dim('Staging registration...');
113
+ await sleep(600);
114
+ spinner.succeed(chalk.green(`Agent ${chalk.cyan(agentId)} staged for import`));
115
+
116
+ console.log('');
117
+ label('Agent ID:', agentId);
118
+ label('Network:', 'Base (Mainnet)');
119
+ label('Status:', chalk.yellow('Staged — deploy when network launches'));
120
+ console.log('');
121
+ info(`Run ${chalk.cyan('pluribus deploy')} once the Pluribus network goes live.`);
122
+ console.log('');
123
+ }
124
+ }
125
+
126
+ function sleep(ms) {
127
+ return new Promise(r => setTimeout(r, ms));
128
+ }
@@ -0,0 +1,220 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { success, info, warn, label, printDivider } from '../utils/banner.js';
6
+
7
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
8
+
9
+ const AGENT_TEMPLATE = (name, capabilities) => `import { PluribusAgent } from '@pluribus/agent-sdk';
10
+
11
+ /**
12
+ * ${name} — Pluribus Agent
13
+ * Capabilities: ${capabilities.join(', ')}
14
+ *
15
+ * Docs: https://pluribus.xyz/docs/sdk
16
+ */
17
+ const agent = new PluribusAgent({
18
+ name: '${name}',
19
+ capabilities: ${JSON.stringify(capabilities)},
20
+ version: '0.1.0',
21
+ });
22
+
23
+ // Handle incoming tasks routed by the Pluribus orchestrator
24
+ agent.on('task', async (task) => {
25
+ const { id, type, payload, respond } = task;
26
+
27
+ console.log(\`Received task \${id} of type \${type}\`);
28
+
29
+ // TODO: Implement your agent logic here
30
+ const result = await processTask(type, payload);
31
+
32
+ await respond({
33
+ taskId: id,
34
+ result,
35
+ confidence: 0.95,
36
+ metadata: {
37
+ processingTime: Date.now(),
38
+ agentVersion: agent.version,
39
+ },
40
+ });
41
+ });
42
+
43
+ async function processTask(type, payload) {
44
+ // Add your agent logic here
45
+ switch (type) {
46
+ case 'research':
47
+ return { summary: 'Research result placeholder', sources: [] };
48
+ case 'social':
49
+ return { content: 'Generated content placeholder', platform: payload.platform };
50
+ default:
51
+ throw new Error(\`Unsupported task type: \${type}\`);
52
+ }
53
+ }
54
+
55
+ agent.start().then(() => {
56
+ console.log(\`Agent "${name}" is live and listening for tasks\`);
57
+ });
58
+ `;
59
+
60
+ const PLURIBUS_CONFIG = (name, capabilities) => JSON.stringify({
61
+ name,
62
+ version: '0.1.0',
63
+ capabilities,
64
+ endpoint: 'https://your-agent-endpoint.com/webhook',
65
+ network: 'base-mainnet',
66
+ stake: {
67
+ tier: 'sentinel',
68
+ amount: 1000,
69
+ },
70
+ metadata: {
71
+ description: `${name} — Pluribus agent`,
72
+ framework: 'custom',
73
+ created: new Date().toISOString(),
74
+ },
75
+ }, null, 2);
76
+
77
+ const DOCKERFILE = (name) => `FROM node:20-alpine
78
+
79
+ WORKDIR /app
80
+ COPY package*.json ./
81
+ RUN npm ci --production
82
+ COPY . .
83
+
84
+ EXPOSE 3000
85
+
86
+ ENV NODE_ENV=production
87
+ ENV AGENT_NAME="${name}"
88
+
89
+ CMD ["node", "agent.js"]
90
+ `;
91
+
92
+ const PACKAGE_JSON = (name) => JSON.stringify({
93
+ name: name.toLowerCase().replace(/\s+/g, '-'),
94
+ version: '0.1.0',
95
+ type: 'module',
96
+ main: 'agent.js',
97
+ scripts: {
98
+ start: 'node agent.js',
99
+ dev: 'node --watch agent.js',
100
+ test: 'node --test',
101
+ },
102
+ dependencies: {
103
+ '@pluribus/agent-sdk': '^0.1.0',
104
+ },
105
+ }, null, 2);
106
+
107
+ const README = (name) => `# ${name}
108
+
109
+ A Pluribus agent for the multi-agent coordination protocol on Base.
110
+
111
+ ## Setup
112
+
113
+ \`\`\`bash
114
+ npm install
115
+ npm run dev
116
+ \`\`\`
117
+
118
+ ## Deploy
119
+
120
+ \`\`\`bash
121
+ npx pluribus deploy
122
+ \`\`\`
123
+
124
+ ## Configuration
125
+
126
+ Edit \`pluribus.config.json\` to configure your agent's capabilities, stake tier, and endpoint.
127
+
128
+ ## Docs
129
+
130
+ https://pluribus.xyz/docs/sdk
131
+ `;
132
+
133
+ export async function initAgent(name, options) {
134
+ const inquirer = (await import('inquirer')).default;
135
+
136
+ console.log('');
137
+ console.log(chalk.cyan.bold(' → Initialize New Agent Project'));
138
+ console.log(chalk.dim(' Scaffold a production-ready Pluribus agent'));
139
+ console.log('');
140
+
141
+ let agentName = name;
142
+ let capabilities;
143
+ let dir;
144
+
145
+ if (!agentName) {
146
+ const answers = await inquirer.prompt([
147
+ {
148
+ type: 'input',
149
+ name: 'name',
150
+ message: chalk.white('Agent name:'),
151
+ prefix: chalk.cyan(' ▸'),
152
+ validate: v => v.length >= 2 ? true : 'Name must be at least 2 characters',
153
+ },
154
+ {
155
+ type: 'checkbox',
156
+ name: 'capabilities',
157
+ message: chalk.white('Capabilities this agent will handle:'),
158
+ prefix: chalk.cyan(' ▸'),
159
+ choices: [
160
+ { name: 'research — Market analysis, risk scoring', value: 'research', checked: true },
161
+ { name: 'social — Content, posting, engagement', value: 'social' },
162
+ { name: 'onchain — DeFi, swaps, bridge ops', value: 'onchain' },
163
+ { name: 'monitoring — Wallets, TXs, alerts', value: 'monitoring' },
164
+ { name: 'data — APIs, retrieval', value: 'data' },
165
+ { name: 'content — Writing, summarization', value: 'content' },
166
+ ],
167
+ validate: v => v.length > 0 ? true : 'Select at least one capability',
168
+ },
169
+ ]);
170
+ agentName = answers.name;
171
+ capabilities = answers.capabilities;
172
+ } else {
173
+ capabilities = ['research'];
174
+ }
175
+
176
+ dir = agentName.toLowerCase().replace(/\s+/g, '-');
177
+
178
+ console.log('');
179
+ printDivider();
180
+ console.log('');
181
+
182
+ const spinner = ora({ text: chalk.dim(`Scaffolding agent project in ./${dir}/`), spinner: 'dots', color: 'cyan' }).start();
183
+
184
+ await sleep(400);
185
+
186
+ // Create directory
187
+ if (!fs.existsSync(dir)) {
188
+ fs.mkdirSync(dir, { recursive: true });
189
+ }
190
+
191
+ // Write files
192
+ fs.writeFileSync(path.join(dir, 'agent.js'), AGENT_TEMPLATE(agentName, capabilities));
193
+ fs.writeFileSync(path.join(dir, 'package.json'), PACKAGE_JSON(agentName));
194
+ fs.writeFileSync(path.join(dir, 'pluribus.config.json'), PLURIBUS_CONFIG(agentName, capabilities));
195
+ fs.writeFileSync(path.join(dir, 'Dockerfile'), DOCKERFILE(agentName));
196
+ fs.writeFileSync(path.join(dir, 'README.md'), README(agentName));
197
+ fs.writeFileSync(path.join(dir, '.gitignore'), 'node_modules/\n.env\n*.log\n');
198
+ fs.writeFileSync(path.join(dir, '.env.example'), 'PLURIBUS_API_KEY=\nAGENT_WEBHOOK_SECRET=\nRPC_URL=https://mainnet.base.org\n');
199
+
200
+ await sleep(600);
201
+ spinner.succeed(chalk.green(`Agent project created at ${chalk.cyan('./' + dir + '/')}`));
202
+
203
+ console.log('');
204
+ console.log(chalk.cyan.bold(' Files created:'));
205
+ printDivider();
206
+ const files = ['agent.js', 'package.json', 'pluribus.config.json', 'Dockerfile', 'README.md', '.gitignore', '.env.example'];
207
+ files.forEach(f => console.log(` ${chalk.dim('+')} ${chalk.white(path.join(dir, f))}`));
208
+ console.log('');
209
+
210
+ console.log(chalk.cyan.bold(' Next steps:'));
211
+ printDivider();
212
+ console.log(` ${chalk.dim('1.')} ${chalk.white(`cd ${dir}`)}`);
213
+ console.log(` ${chalk.dim('2.')} ${chalk.white('npm install')}`);
214
+ console.log(` ${chalk.dim('3.')} ${chalk.white('npm run dev')} ${chalk.dim('# develop locally')}`);
215
+ console.log(` ${chalk.dim('4.')} ${chalk.white('npx pluribus register')} ${chalk.dim('# register when network launches')}`);
216
+ console.log(` ${chalk.dim('5.')} ${chalk.white('npx pluribus deploy')} ${chalk.dim('# deploy to Pluribus network')}`);
217
+ console.log('');
218
+ info(`Docs: ${chalk.underline('https://pluribus.xyz/sdk')}`);
219
+ console.log('');
220
+ }
@@ -0,0 +1,46 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { label, printDivider, info, warn } from '../utils/banner.js';
4
+
5
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
6
+
7
+ export async function listAgents(options) {
8
+ console.log('');
9
+ console.log(chalk.cyan.bold(' → Agent Registry'));
10
+ console.log(chalk.dim(' Browse agents registered on the Pluribus network'));
11
+ console.log('');
12
+
13
+ const spinner = ora({ text: chalk.dim('Querying agent registry...'), spinner: 'dots', color: 'cyan' }).start();
14
+ await sleep(1000);
15
+ spinner.succeed(chalk.green('Registry queried'));
16
+
17
+ console.log('');
18
+ printDivider();
19
+ console.log('');
20
+
21
+ console.log(` ${chalk.cyan('No agents registered yet')} ${chalk.dim('— network is pre-launch')}`);
22
+ console.log('');
23
+
24
+ console.log(chalk.cyan.bold(' Staged Agents (local)'));
25
+ printDivider();
26
+ info('No local agents staged. Run ' + chalk.cyan('pluribus register') + ' to stage one.');
27
+ console.log('');
28
+
29
+ console.log(chalk.cyan.bold(' Supported Frameworks'));
30
+ printDivider();
31
+ const frameworks = [
32
+ { name: 'Virtuals Protocol', tag: 'virtuals' },
33
+ { name: 'ElizaOS', tag: 'eliza' },
34
+ { name: 'LangChain', tag: 'langchain' },
35
+ { name: 'AutoGPT', tag: 'autogpt' },
36
+ { name: 'CrewAI', tag: 'crewai' },
37
+ { name: 'Custom / Other', tag: 'custom' },
38
+ ];
39
+ frameworks.forEach(f => {
40
+ console.log(` ${chalk.cyan('▸')} ${chalk.white(f.name.padEnd(22))} ${chalk.dim('[' + f.tag + ']')}`);
41
+ });
42
+ console.log('');
43
+
44
+ info(`Docs: ${chalk.underline('https://pluribus.xyz/agents')}`);
45
+ console.log('');
46
+ }
@@ -0,0 +1,44 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { label, printDivider, info, warn } from '../utils/banner.js';
4
+
5
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
6
+
7
+ export async function logs(agentId, options) {
8
+ const inquirer = (await import('inquirer')).default;
9
+
10
+ console.log('');
11
+ console.log(chalk.cyan.bold(' → Agent Logs'));
12
+ console.log('');
13
+
14
+ if (!agentId) {
15
+ const answers = await inquirer.prompt([
16
+ {
17
+ type: 'input',
18
+ name: 'agentId',
19
+ message: chalk.white('Agent ID (PLR-XXXXXX or task ID):'),
20
+ prefix: chalk.cyan(' ▸'),
21
+ validate: v => v.length > 0 ? true : 'Agent ID is required',
22
+ },
23
+ ]);
24
+ agentId = answers.agentId;
25
+ }
26
+
27
+ const spinner = ora({ text: chalk.dim(`Connecting to agent ${chalk.cyan(agentId)}...`), spinner: 'dots', color: 'cyan' }).start();
28
+ await sleep(900);
29
+ spinner.succeed(chalk.green('Connected'));
30
+
31
+ console.log('');
32
+ printDivider();
33
+
34
+ console.log(` ${chalk.dim('No logs available')} ${chalk.cyan('—')} ${chalk.dim('network is pre-launch')}`);
35
+ console.log('');
36
+
37
+ label('Agent:', agentId);
38
+ label('Status:', chalk.yellow('Awaiting network launch'));
39
+ label('Log stream:', chalk.yellow('Available post-launch'));
40
+ console.log('');
41
+
42
+ info('Once live, this command streams real-time task execution logs.');
43
+ console.log('');
44
+ }
@@ -0,0 +1,101 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { success, error, info, warn, label, printDivider } from '../utils/banner.js';
4
+
5
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
6
+
7
+ export async function registerAgent(options) {
8
+ const inquirer = (await import('inquirer')).default;
9
+
10
+ console.log('');
11
+ console.log(chalk.cyan.bold(' → Register New Agent'));
12
+ console.log(chalk.dim(' Create a new agent and stake $PLUR to join the network'));
13
+ console.log('');
14
+
15
+ const answers = await inquirer.prompt([
16
+ {
17
+ type: 'input',
18
+ name: 'name',
19
+ message: chalk.white('Agent name:'),
20
+ prefix: chalk.cyan(' ▸'),
21
+ validate: v => v.length >= 3 ? true : 'Name must be at least 3 characters',
22
+ },
23
+ {
24
+ type: 'input',
25
+ name: 'endpoint',
26
+ message: chalk.white('Agent webhook endpoint (https://...):'),
27
+ prefix: chalk.cyan(' ▸'),
28
+ validate: v => v.startsWith('http') ? true : 'Must be a valid URL',
29
+ },
30
+ {
31
+ type: 'list',
32
+ name: 'tier',
33
+ message: chalk.white('Staking tier:'),
34
+ prefix: chalk.cyan(' ▸'),
35
+ choices: [
36
+ { name: `Sentinel ${chalk.dim('— Entry tier, basic yield')}`, value: 'sentinel' },
37
+ { name: `Archon ${chalk.dim('— Mid tier, enhanced yield + priority routing')}`, value: 'archon' },
38
+ { name: `Sovereign ${chalk.dim('— Elite tier, max yield + governance seat')}`, value: 'sovereign' },
39
+ ],
40
+ },
41
+ {
42
+ type: 'checkbox',
43
+ name: 'capabilities',
44
+ message: chalk.white('Capability tags:'),
45
+ prefix: chalk.cyan(' ▸'),
46
+ choices: [
47
+ { name: 'research — Token analysis, risk scoring, market research', value: 'research' },
48
+ { name: 'social — Twitter/X, Farcaster, content generation', value: 'social' },
49
+ { name: 'onchain — DeFi execution, bridge ops, LP management', value: 'onchain' },
50
+ { name: 'monitoring — Wallet watch, TX alerts, MEV detection', value: 'monitoring' },
51
+ { name: 'data — APIs, retrieval, aggregation', value: 'data' },
52
+ { name: 'content — Writing, summarization, translation', value: 'content' },
53
+ ],
54
+ validate: v => v.length > 0 ? true : 'Select at least one capability',
55
+ },
56
+ {
57
+ type: 'input',
58
+ name: 'wallet',
59
+ message: chalk.white('Wallet address (0x...):'),
60
+ prefix: chalk.cyan(' ▸'),
61
+ validate: v => v.startsWith('0x') && v.length === 42 ? true : 'Enter a valid Ethereum address',
62
+ },
63
+ ]);
64
+
65
+ const tierStake = { sentinel: '1,000', archon: '25,000', sovereign: '100,000' };
66
+
67
+ console.log('');
68
+ printDivider();
69
+ console.log('');
70
+
71
+ const spinner = ora({ text: chalk.dim('Generating agent identity...'), spinner: 'dots', color: 'cyan' }).start();
72
+ await sleep(900);
73
+ spinner.text = chalk.dim('Validating endpoint...');
74
+ await sleep(700);
75
+ spinner.text = chalk.dim('Computing capability fingerprint...');
76
+ await sleep(600);
77
+ spinner.text = chalk.dim('Staging on-chain registration...');
78
+ await sleep(800);
79
+ spinner.succeed(chalk.green('Agent staged for registration'));
80
+
81
+ const agentId = 'PLR-' + Math.random().toString(36).substring(2, 8).toUpperCase();
82
+
83
+ console.log('');
84
+ console.log(chalk.cyan.bold(' Registration Summary'));
85
+ printDivider();
86
+ label('Agent ID:', chalk.cyan(agentId));
87
+ label('Name:', answers.name);
88
+ label('Endpoint:', answers.endpoint);
89
+ label('Tier:', answers.tier.charAt(0).toUpperCase() + answers.tier.slice(1));
90
+ label('Stake Required:', `${tierStake[answers.tier]} $PLUR`);
91
+ label('Capabilities:', answers.capabilities.join(', '));
92
+ label('Wallet:', answers.wallet);
93
+ label('Network:', 'Base Mainnet');
94
+ label('Status:', chalk.yellow('Staged — pending launch'));
95
+ console.log('');
96
+
97
+ warn('Registration will finalize when the Pluribus network launches.');
98
+ info(`Your agent ID is ${chalk.cyan(agentId)} — save this for reference.`);
99
+ info(`Run ${chalk.cyan('pluribus status')} to check network launch status.`);
100
+ console.log('');
101
+ }
@@ -0,0 +1,85 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { label, printDivider, warn, info, success } from '../utils/banner.js';
4
+
5
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
6
+
7
+ export async function stake(amount, options) {
8
+ const inquirer = (await import('inquirer')).default;
9
+
10
+ console.log('');
11
+ console.log(chalk.cyan.bold(' → Stake $PLUR'));
12
+ console.log(chalk.dim(' Stake tokens to earn yield from network task fees'));
13
+ console.log('');
14
+
15
+ if (!amount) {
16
+ const answers = await inquirer.prompt([
17
+ {
18
+ type: 'list',
19
+ name: 'tier',
20
+ message: chalk.white('Select staking tier:'),
21
+ prefix: chalk.cyan(' ▸'),
22
+ choices: [
23
+ { name: `Sentinel ${chalk.dim('Entry tier — basic yield')}`, value: 'sentinel' },
24
+ { name: `Archon ${chalk.dim('Mid tier — enhanced yield + routing')}`, value: 'archon' },
25
+ { name: `Sovereign ${chalk.dim('Elite tier — max yield + governance')}`, value: 'sovereign' },
26
+ ],
27
+ },
28
+ {
29
+ type: 'input',
30
+ name: 'amount',
31
+ message: chalk.white('Amount of $PLUR to stake:'),
32
+ prefix: chalk.cyan(' ▸'),
33
+ validate: v => !isNaN(Number(v)) && Number(v) > 0 ? true : 'Enter a valid amount',
34
+ },
35
+ {
36
+ type: 'input',
37
+ name: 'wallet',
38
+ message: chalk.white('Wallet address (0x...):'),
39
+ prefix: chalk.cyan(' ▸'),
40
+ validate: v => v.startsWith('0x') && v.length === 42 ? true : 'Enter a valid Ethereum address',
41
+ },
42
+ ]);
43
+ amount = answers.amount;
44
+
45
+ console.log('');
46
+ printDivider();
47
+ console.log('');
48
+
49
+ const spinner = ora({ text: chalk.dim('Preparing stake transaction...'), spinner: 'dots', color: 'cyan' }).start();
50
+ await sleep(700);
51
+ spinner.text = chalk.dim('Validating wallet...');
52
+ await sleep(600);
53
+ spinner.text = chalk.dim('Staging stake...');
54
+ await sleep(500);
55
+ spinner.succeed(chalk.green('Stake staged'));
56
+
57
+ console.log('');
58
+ label('Tier:', answers.tier.charAt(0).toUpperCase() + answers.tier.slice(1));
59
+ label('Amount:', `${Number(amount).toLocaleString()} $PLUR`);
60
+ label('Wallet:', answers.wallet);
61
+ label('APY:', chalk.cyan('TBA at launch'));
62
+ label('Status:', chalk.yellow('Staged — pending network launch'));
63
+ console.log('');
64
+ warn('Staking goes live when the Pluribus network launches on Base.');
65
+ info(`Run ${chalk.cyan('pluribus balance')} to check your $PLUR balance.`);
66
+ console.log('');
67
+ }
68
+ }
69
+
70
+ export async function unstake(amount, options) {
71
+ console.log('');
72
+ console.log(chalk.cyan.bold(' → Unstake $PLUR'));
73
+ console.log('');
74
+
75
+ const spinner = ora({ text: chalk.dim('Preparing unstake...'), spinner: 'dots', color: 'cyan' }).start();
76
+ await sleep(1000);
77
+ spinner.succeed(chalk.green('Unstake staged'));
78
+
79
+ console.log('');
80
+ label('Amount:', amount ? `${Number(amount).toLocaleString()} $PLUR` : 'All staked $PLUR');
81
+ label('Status:', chalk.yellow('Staged — pending network launch'));
82
+ console.log('');
83
+ warn('Unstake will execute when the Pluribus staking contract is live.');
84
+ console.log('');
85
+ }
@@ -0,0 +1,45 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { label, printDivider, info } from '../utils/banner.js';
4
+
5
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
6
+
7
+ export async function networkStatus() {
8
+ console.log('');
9
+ console.log(chalk.cyan.bold(' → Network Status'));
10
+ console.log('');
11
+
12
+ const spinner = ora({ text: chalk.dim('Querying Pluribus network...'), spinner: 'dots', color: 'cyan' }).start();
13
+ await sleep(1100);
14
+ spinner.succeed(chalk.green('Status retrieved'));
15
+
16
+ console.log('');
17
+ console.log(chalk.cyan.bold(' Protocol Status'));
18
+ printDivider();
19
+ label('Network:', 'Base Mainnet');
20
+ label('Launch Phase:', chalk.yellow('Pre-Launch'));
21
+ label('Protocol Status:', chalk.yellow('● Staging'));
22
+ label('Contracts:', chalk.yellow('Deploying soon'));
23
+ label('Agent Registry:', chalk.yellow('Opening soon'));
24
+ label('Task Queue:', chalk.yellow('Coming soon'));
25
+ console.log('');
26
+
27
+ console.log(chalk.cyan.bold(' Network Metrics'));
28
+ printDivider();
29
+ label('Agents Staged:', chalk.cyan('—'));
30
+ label('Tasks Processed:', chalk.cyan('—'));
31
+ label('$PLUR Burned:', chalk.cyan('—'));
32
+ label('Staker APY:', chalk.cyan('TBA at launch'));
33
+ label('Uptime:', chalk.cyan('—'));
34
+ console.log('');
35
+
36
+ console.log(chalk.cyan.bold(' CLI Version'));
37
+ printDivider();
38
+ label('CLI:', '0.1.0');
39
+ label('SDK Target:', '0.1.0');
40
+ label('Node.js:', process.version);
41
+ console.log('');
42
+
43
+ info(`Follow ${chalk.underline('https://pluribus.xyz')} for launch updates.`);
44
+ console.log('');
45
+ }
@@ -0,0 +1,84 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { label, printDivider, warn, info } from '../utils/banner.js';
4
+
5
+ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
6
+
7
+ export async function submitTask(taskDescription, options) {
8
+ const inquirer = (await import('inquirer')).default;
9
+
10
+ console.log('');
11
+ console.log(chalk.cyan.bold(' → Submit Task'));
12
+ console.log(chalk.dim(' Submit a task to the Pluribus agent network'));
13
+ console.log('');
14
+
15
+ let task = taskDescription;
16
+ let taskType, plur;
17
+
18
+ if (!task) {
19
+ const answers = await inquirer.prompt([
20
+ {
21
+ type: 'input',
22
+ name: 'task',
23
+ message: chalk.white('Describe your task:'),
24
+ prefix: chalk.cyan(' ▸'),
25
+ validate: v => v.length >= 10 ? true : 'Please provide a meaningful task description',
26
+ },
27
+ {
28
+ type: 'list',
29
+ name: 'type',
30
+ message: chalk.white('Task type:'),
31
+ prefix: chalk.cyan(' ▸'),
32
+ choices: [
33
+ { name: 'research — Analysis, research, risk scoring', value: 'research' },
34
+ { name: 'social — Post, thread, engagement', value: 'social' },
35
+ { name: 'monitoring — Watch wallet or contract', value: 'monitoring' },
36
+ { name: 'onchain — Execute onchain action', value: 'onchain' },
37
+ { name: 'auto — Let the orchestrator decide', value: 'auto' },
38
+ ],
39
+ },
40
+ {
41
+ type: 'input',
42
+ name: 'plur',
43
+ message: chalk.white('$PLUR to pay (determines priority):'),
44
+ prefix: chalk.cyan(' ▸'),
45
+ default: '0.5',
46
+ validate: v => !isNaN(Number(v)) && Number(v) > 0 ? true : 'Enter a valid amount',
47
+ },
48
+ ]);
49
+ task = answers.task;
50
+ taskType = answers.type;
51
+ plur = answers.plur;
52
+ } else {
53
+ taskType = options.type || 'auto';
54
+ plur = options.plur || '0.5';
55
+ }
56
+
57
+ console.log('');
58
+ printDivider();
59
+ console.log('');
60
+
61
+ const spinner = ora({ text: chalk.dim('Connecting to orchestrator...'), spinner: 'dots', color: 'cyan' }).start();
62
+ await sleep(800);
63
+ spinner.text = chalk.dim('Routing to best agents...');
64
+ await sleep(600);
65
+ spinner.text = chalk.dim('Staging task submission...');
66
+ await sleep(700);
67
+ spinner.succeed(chalk.green('Task staged'));
68
+
69
+ const taskId = '#' + Math.floor(Math.random() * 90000 + 10000);
70
+
71
+ console.log('');
72
+ console.log(chalk.cyan.bold(' Task Summary'));
73
+ printDivider();
74
+ label('Task ID:', chalk.cyan(taskId));
75
+ label('Description:', task.length > 50 ? task.slice(0, 50) + '...' : task);
76
+ label('Type:', taskType);
77
+ label('$PLUR:', plur);
78
+ label('Status:', chalk.yellow('Staged — pending network launch'));
79
+ console.log('');
80
+
81
+ warn('Task submission goes live when the Pluribus network launches.');
82
+ info(`Task ID ${chalk.cyan(taskId)} saved. Run ${chalk.cyan('pluribus logs ' + taskId)} post-launch to track results.`);
83
+ console.log('');
84
+ }
@@ -0,0 +1,45 @@
1
+ import chalk from 'chalk';
2
+
3
+ export function printBanner() {
4
+ const cyan = chalk.cyan;
5
+ const dim = chalk.dim;
6
+ const bold = chalk.bold;
7
+
8
+ console.log('');
9
+ console.log(cyan.bold(' ██████╗ ██╗ ██╗ ██╗██████╗ ██╗██████╗ ██╗ ██╗███████╗'));
10
+ console.log(cyan.bold(' ██╔══██╗██║ ██║ ██║██╔══██╗██║██╔══██╗██║ ██║██╔════╝'));
11
+ console.log(cyan.bold(' ██████╔╝██║ ██║ ██║██████╔╝██║██████╔╝██║ ██║███████╗'));
12
+ console.log(cyan.bold(' ██╔═══╝ ██║ ██║ ██║██╔══██╗██║██╔══██╗██║ ██║╚════██║'));
13
+ console.log(cyan.bold(' ██║ ███████╗╚██████╔╝██║ ██║██║██████╔╝╚██████╔╝███████║'));
14
+ console.log(cyan.bold(' ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═════╝ ╚══════╝'));
15
+ console.log('');
16
+ console.log(` ${chalk.magenta('E PLURIBUS UNUM')} ${dim('—')} ${chalk.white.bold('Many Agents. One Mind.')}`);
17
+ console.log(` ${dim('Multi-Agent Coordination Protocol on Base')}`);
18
+ console.log('');
19
+ console.log(` ${dim('Version')} ${chalk.cyan('0.1.0')} ${dim('·')} ${chalk.underline.dim('https://pluribus.xyz')}`);
20
+ console.log('');
21
+ }
22
+
23
+ export function printDivider() {
24
+ console.log(chalk.dim(' ' + '─'.repeat(60)));
25
+ }
26
+
27
+ export function success(msg) {
28
+ console.log(` ${chalk.green('✓')} ${chalk.white(msg)}`);
29
+ }
30
+
31
+ export function error(msg) {
32
+ console.log(` ${chalk.red('✗')} ${chalk.white(msg)}`);
33
+ }
34
+
35
+ export function info(msg) {
36
+ console.log(` ${chalk.cyan('ℹ')} ${chalk.white(msg)}`);
37
+ }
38
+
39
+ export function warn(msg) {
40
+ console.log(` ${chalk.yellow('⚠')} ${chalk.white(msg)}`);
41
+ }
42
+
43
+ export function label(key, val) {
44
+ console.log(` ${chalk.dim(key.padEnd(20))} ${chalk.white(val)}`);
45
+ }