infinicode 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,130 @@
1
+ # ⚡ Infinicode
2
+
3
+ **AI coding agent powered by your local Ollama.** Fork of OpenCode optimized for self-hosted LLMs.
4
+
5
+ ```bash
6
+ npm install -g infinicode
7
+
8
+ # Connect to your Ollama master
9
+ infinicode connect 192.168.1.100
10
+
11
+ # Start coding
12
+ infinicode
13
+ ```
14
+
15
+ ## Why Infinicode?
16
+
17
+ - **100% Local** — All inference on YOUR hardware
18
+ - **Zero Cloud** — No API keys, no subscriptions, no data leaving your network
19
+ - **One Command Setup** — `infinicode connect <ip>` and you're done
20
+ - **Multi-Node** — Run on any machine, point to one Ollama master
21
+
22
+ ## Quick Start
23
+
24
+ ### 1. Install
25
+
26
+ ```bash
27
+ npm install -g infinicode
28
+ # or
29
+ pnpm add -g infinicode
30
+ ```
31
+
32
+ ### 2. Setup Ollama Master
33
+
34
+ On your GPU machine:
35
+
36
+ ```bash
37
+ # Allow network connections
38
+ OLLAMA_HOST=0.0.0.0:11434 ollama serve
39
+
40
+ # Pull a coding model
41
+ ollama pull qwen2.5-coder:14b
42
+ ```
43
+
44
+ ### 3. Connect & Code
45
+
46
+ ```bash
47
+ # From any machine on your network
48
+ infinicode connect 192.168.1.100 # Your Ollama IP
49
+ infinicode # Start coding!
50
+ ```
51
+
52
+ ## Commands
53
+
54
+ | Command | Alias | Description |
55
+ |---------|-------|-------------|
56
+ | `infinicode connect <ip>` | `ic c` | Quick connect to Ollama master |
57
+ | `infinicode setup` | `ic s` | Interactive setup wizard |
58
+ | `infinicode run` | `ic` | Start the coding agent (default) |
59
+ | `infinicode models` | `ic m` | List available models |
60
+ | `infinicode status` | | Show config & connection status |
61
+ | `infinicode config --list` | | View all configuration |
62
+ | `infinicode config --reset` | | Reset to defaults |
63
+
64
+ ## Configuration
65
+
66
+ Config is stored automatically. Override with:
67
+
68
+ ```bash
69
+ # Set default model
70
+ infinicode config --set defaultModel=codestral:22b
71
+
72
+ # Set master URL
73
+ infinicode config --set masterUrl=http://192.168.1.100:11434
74
+
75
+ # View all
76
+ infinicode config --list
77
+ ```
78
+
79
+ ## Recommended Models
80
+
81
+ For coding tasks on Ollama:
82
+
83
+ | Model | Size | Best For |
84
+ |-------|------|----------|
85
+ | `qwen2.5-coder:14b` | 9GB | Great balance |
86
+ | `qwen2.5-coder:32b` | 20GB | Best quality |
87
+ | `deepseek-coder-v2:16b` | 10GB | Strong reasoning |
88
+ | `codestral:22b` | 13GB | Fast completion |
89
+
90
+ ## Architecture
91
+
92
+ ```
93
+ ┌─────────────────┐
94
+ │ Laptop │
95
+ │ (infinicode) │──┐
96
+ └─────────────────┘ │
97
+ │ ┌─────────────────┐
98
+ ┌─────────────────┐ │ │ GPU Server │
99
+ │ Desktop │──┼───▶│ (Ollama) │
100
+ │ (infinicode) │ │ │ │
101
+ └─────────────────┘ │ │ qwen2.5-coder │
102
+ │ │ codestral │
103
+ ┌─────────────────┐ │ └─────────────────┘
104
+ │ Server │──┘
105
+ │ (infinicode) │
106
+ └─────────────────┘
107
+ ```
108
+
109
+ ## Security
110
+
111
+ Exposing Ollama to your network means anyone on that network can use it.
112
+
113
+ **Secure options:**
114
+ 1. **VPN/Tailscale** — Only accessible on private network
115
+ 2. **SSH Tunnel** — `ssh -L 11434:localhost:11434 gpu-server`
116
+ 3. **Firewall** — Allow only specific IPs
117
+
118
+ ## Requirements
119
+
120
+ - Node.js 20+
121
+ - OpenCode installed (`npm install -g opencode`)
122
+ - Ollama running somewhere on your network
123
+
124
+ ## License
125
+
126
+ MIT — Based on [OpenCode](https://github.com/sst/opencode)
127
+
128
+ ---
129
+
130
+ ⚡ Built for sovereign computing. Your code, your models, your hardware.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import('../dist/cli.js');
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import Conf from 'conf';
5
+ import { setupMaster } from './commands/setup.js';
6
+ import { runAgent } from './commands/run.js';
7
+ import { showStatus } from './commands/status.js';
8
+ import { listModels } from './commands/models.js';
9
+ const VERSION = '1.0.0';
10
+ const config = new Conf({
11
+ projectName: 'infinicode',
12
+ defaults: {
13
+ masterUrl: 'http://localhost:11434',
14
+ defaultModel: 'qwen2.5-coder:14b',
15
+ theme: 'infini'
16
+ }
17
+ });
18
+ const program = new Command();
19
+ console.log(chalk.cyan(`
20
+ ⚡ ${chalk.bold('INFINICODE')} v${VERSION}
21
+ ${chalk.dim('AI Coding Agent • Powered by Ollama')}
22
+ `));
23
+ program
24
+ .name('infinicode')
25
+ .description('AI coding agent powered by your local Ollama')
26
+ .version(VERSION);
27
+ // Quick connect command
28
+ program
29
+ .command('connect <master-ip>')
30
+ .alias('c')
31
+ .description('Quick connect to Ollama master (e.g., infinicode connect 192.168.1.100)')
32
+ .option('-p, --port <port>', 'Ollama port', '11434')
33
+ .option('-m, --model <model>', 'Default model', 'qwen2.5-coder:14b')
34
+ .action(async (masterIp, options) => {
35
+ await setupMaster(masterIp, options.port, options.model, config);
36
+ });
37
+ // Setup wizard
38
+ program
39
+ .command('setup')
40
+ .alias('s')
41
+ .description('Interactive setup wizard')
42
+ .action(async () => {
43
+ const inquirer = (await import('inquirer')).default;
44
+ const answers = await inquirer.prompt([
45
+ {
46
+ type: 'input',
47
+ name: 'masterIp',
48
+ message: 'Ollama master IP:',
49
+ default: 'localhost'
50
+ },
51
+ {
52
+ type: 'input',
53
+ name: 'port',
54
+ message: 'Ollama port:',
55
+ default: '11434'
56
+ },
57
+ {
58
+ type: 'input',
59
+ name: 'model',
60
+ message: 'Default model:',
61
+ default: 'qwen2.5-coder:14b'
62
+ }
63
+ ]);
64
+ await setupMaster(answers.masterIp, answers.port, answers.model, config);
65
+ });
66
+ // Run the agent (main command)
67
+ program
68
+ .command('run', { isDefault: true })
69
+ .alias('r')
70
+ .description('Start the coding agent')
71
+ .option('-m, --model <model>', 'Model to use')
72
+ .option('--no-tui', 'Disable TUI, use simple mode')
73
+ .action(async (options) => {
74
+ const masterUrl = config.get('masterUrl');
75
+ const model = options.model || config.get('defaultModel');
76
+ if (!masterUrl || masterUrl === 'http://localhost:11434') {
77
+ console.log(chalk.yellow('\n⚠️ No master configured. Using localhost.'));
78
+ console.log(chalk.dim(' Run: infinicode connect <master-ip>\n'));
79
+ }
80
+ await runAgent(masterUrl, model, options.tui !== false, config);
81
+ });
82
+ // Status command
83
+ program
84
+ .command('status')
85
+ .description('Show current configuration and connection status')
86
+ .action(async () => {
87
+ await showStatus(config);
88
+ });
89
+ // Models command
90
+ program
91
+ .command('models')
92
+ .alias('m')
93
+ .description('List available models on master')
94
+ .action(async () => {
95
+ await listModels(config);
96
+ });
97
+ // Config commands
98
+ program
99
+ .command('config')
100
+ .description('View or modify configuration')
101
+ .option('--get <key>', 'Get a config value')
102
+ .option('--set <key=value>', 'Set a config value')
103
+ .option('--list', 'List all config')
104
+ .option('--reset', 'Reset to defaults')
105
+ .action((options) => {
106
+ if (options.reset) {
107
+ config.clear();
108
+ console.log(chalk.green('✓ Config reset to defaults'));
109
+ return;
110
+ }
111
+ if (options.list) {
112
+ console.log(chalk.bold('\nConfiguration:'));
113
+ console.log(chalk.dim('─'.repeat(40)));
114
+ for (const [key, value] of Object.entries(config.store)) {
115
+ console.log(` ${chalk.cyan(key)}: ${value}`);
116
+ }
117
+ console.log();
118
+ return;
119
+ }
120
+ if (options.get) {
121
+ console.log(config.get(options.get));
122
+ return;
123
+ }
124
+ if (options.set) {
125
+ const [key, value] = options.set.split('=');
126
+ config.set(key, value);
127
+ console.log(chalk.green(`✓ Set ${key} = ${value}`));
128
+ return;
129
+ }
130
+ // Default: show config
131
+ console.log(chalk.bold('\nConfiguration:'));
132
+ console.log(chalk.dim('─'.repeat(40)));
133
+ for (const [key, value] of Object.entries(config.store)) {
134
+ console.log(` ${chalk.cyan(key)}: ${value}`);
135
+ }
136
+ console.log();
137
+ });
138
+ // Passthrough to opencode
139
+ program
140
+ .command('opencode [args...]')
141
+ .description('Run opencode directly with Ollama config injected')
142
+ .allowUnknownOption()
143
+ .action(async (args) => {
144
+ const { execa } = await import('execa');
145
+ const masterUrl = config.get('masterUrl');
146
+ process.env.LOCAL_ENDPOINT = `${masterUrl}/v1`;
147
+ process.env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
148
+ providers: {
149
+ anthropic: { disabled: true },
150
+ openai: { disabled: true },
151
+ gemini: { disabled: true },
152
+ local: { apiKey: 'not-needed' }
153
+ }
154
+ });
155
+ try {
156
+ await execa('opencode', args, {
157
+ stdio: 'inherit',
158
+ env: process.env
159
+ });
160
+ }
161
+ catch (e) {
162
+ if (e.exitCode)
163
+ process.exit(e.exitCode);
164
+ }
165
+ });
166
+ program.parse();
@@ -0,0 +1,2 @@
1
+ import type Conf from 'conf';
2
+ export declare function listModels(config: Conf<any>): Promise<void>;
@@ -0,0 +1,76 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ function formatSize(bytes) {
4
+ const gb = bytes / (1024 ** 3);
5
+ if (gb >= 1)
6
+ return `${gb.toFixed(1)} GB`;
7
+ const mb = bytes / (1024 ** 2);
8
+ return `${mb.toFixed(0)} MB`;
9
+ }
10
+ export async function listModels(config) {
11
+ const masterUrl = config.get('masterUrl');
12
+ const defaultModel = config.get('defaultModel');
13
+ console.log(chalk.bold('\n⚡ Available Models'));
14
+ console.log(chalk.dim(` Master: ${masterUrl}`));
15
+ console.log(chalk.dim('─'.repeat(50)));
16
+ const spinner = ora('Fetching models...').start();
17
+ try {
18
+ const response = await fetch(`${masterUrl}/api/tags`, {
19
+ signal: AbortSignal.timeout(10000)
20
+ });
21
+ if (!response.ok) {
22
+ throw new Error(`HTTP ${response.status}`);
23
+ }
24
+ const data = await response.json();
25
+ spinner.stop();
26
+ const models = data.models || [];
27
+ if (models.length === 0) {
28
+ console.log(chalk.yellow('\n No models installed.'));
29
+ console.log(chalk.dim('\n Recommended models for coding:'));
30
+ console.log(chalk.cyan(' ollama pull qwen2.5-coder:14b'));
31
+ console.log(chalk.cyan(' ollama pull deepseek-coder-v2:16b'));
32
+ console.log(chalk.cyan(' ollama pull codestral:22b'));
33
+ console.log();
34
+ return;
35
+ }
36
+ // Categorize models
37
+ const codingModels = [];
38
+ const otherModels = [];
39
+ for (const m of models) {
40
+ const name = m.name.toLowerCase();
41
+ if (name.includes('code') || name.includes('coder') || name.includes('stral')) {
42
+ codingModels.push(m);
43
+ }
44
+ else {
45
+ otherModels.push(m);
46
+ }
47
+ }
48
+ // Display coding models first
49
+ if (codingModels.length > 0) {
50
+ console.log(chalk.bold('\n 💻 Coding Models:'));
51
+ for (const m of codingModels) {
52
+ const isDefault = m.name === defaultModel || m.name.startsWith(defaultModel.split(':')[0]);
53
+ const marker = isDefault ? chalk.green('★') : ' ';
54
+ const size = formatSize(m.size);
55
+ console.log(` ${marker} ${chalk.cyan(m.name.padEnd(30))} ${chalk.dim(size)}`);
56
+ }
57
+ }
58
+ if (otherModels.length > 0) {
59
+ console.log(chalk.bold('\n 🤖 Other Models:'));
60
+ for (const m of otherModels) {
61
+ const isDefault = m.name === defaultModel;
62
+ const marker = isDefault ? chalk.green('★') : ' ';
63
+ const size = formatSize(m.size);
64
+ console.log(` ${marker} ${chalk.cyan(m.name.padEnd(30))} ${chalk.dim(size)}`);
65
+ }
66
+ }
67
+ console.log(chalk.dim(`\n Total: ${models.length} models`));
68
+ console.log(chalk.dim(` ★ = current default\n`));
69
+ }
70
+ catch (error) {
71
+ spinner.fail('Failed to fetch models');
72
+ console.log(chalk.red(`\n ✗ Could not reach ${masterUrl}`));
73
+ console.log(chalk.dim(' Is Ollama running?\n'));
74
+ process.exit(1);
75
+ }
76
+ }
@@ -0,0 +1,2 @@
1
+ import type Conf from 'conf';
2
+ export declare function runAgent(masterUrl: string, model: string, useTui: boolean, config: Conf<any>): Promise<void>;
@@ -0,0 +1,84 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ export async function runAgent(masterUrl, model, useTui, config) {
4
+ // Check connection first
5
+ const spinner = ora('Connecting to Ollama...').start();
6
+ try {
7
+ const response = await fetch(`${masterUrl}/api/tags`, {
8
+ signal: AbortSignal.timeout(5000)
9
+ });
10
+ if (!response.ok) {
11
+ throw new Error(`HTTP ${response.status}`);
12
+ }
13
+ const data = await response.json();
14
+ const models = data.models || [];
15
+ const hasModel = models.some(m => m.name === model || m.name.startsWith(model.split(':')[0]));
16
+ if (!hasModel) {
17
+ spinner.warn(`Model '${model}' not found`);
18
+ if (models.length > 0) {
19
+ console.log(chalk.dim(`\nAvailable: ${models.slice(0, 5).map(m => m.name).join(', ')}`));
20
+ }
21
+ console.log(chalk.yellow(`\nPull the model first:`));
22
+ console.log(chalk.cyan(` ollama pull ${model}\n`));
23
+ process.exit(1);
24
+ }
25
+ spinner.succeed('Ollama connected');
26
+ }
27
+ catch (error) {
28
+ spinner.fail('Connection failed');
29
+ console.log(chalk.red(`\n✗ Could not connect to ${masterUrl}`));
30
+ console.log(chalk.dim('\nRun: infinicode connect <master-ip>\n'));
31
+ process.exit(1);
32
+ }
33
+ // Set environment for opencode
34
+ process.env.LOCAL_ENDPOINT = `${masterUrl}/v1`;
35
+ process.env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
36
+ providers: {
37
+ anthropic: { disabled: true },
38
+ openai: { disabled: true },
39
+ gemini: { disabled: true },
40
+ groq: { disabled: true },
41
+ openrouter: { disabled: true },
42
+ xai: { disabled: true },
43
+ azure: { disabled: true },
44
+ bedrock: { disabled: true },
45
+ vertexai: { disabled: true },
46
+ copilot: { disabled: true },
47
+ local: { apiKey: 'not-needed' }
48
+ },
49
+ agents: {
50
+ coder: { model: `local.${model}` }
51
+ },
52
+ tui: {
53
+ theme: config.get('theme') || 'infini'
54
+ }
55
+ });
56
+ console.log(chalk.dim(`\nStarting with ${chalk.cyan(model)}...`));
57
+ console.log(chalk.dim('─'.repeat(40)));
58
+ // Try to run opencode
59
+ const { execa } = await import('execa');
60
+ try {
61
+ // Check if opencode is installed
62
+ await execa('which', ['opencode']).catch(() => execa('where', ['opencode']));
63
+ // Run opencode
64
+ await execa('opencode', [], {
65
+ stdio: 'inherit',
66
+ env: process.env
67
+ });
68
+ }
69
+ catch (e) {
70
+ if (e.code === 'ENOENT' || e.exitCode === 1) {
71
+ console.log(chalk.yellow('\n⚠️ OpenCode not found.'));
72
+ console.log(chalk.dim('\nInstall it with:'));
73
+ console.log(chalk.cyan(' npm install -g opencode'));
74
+ console.log(chalk.dim('\nOr use infinicode with the Go binary:'));
75
+ console.log(chalk.cyan(' cd /path/to/opencode-infini && go build -o infini && ./infini'));
76
+ console.log();
77
+ process.exit(1);
78
+ }
79
+ if (e.exitCode) {
80
+ process.exit(e.exitCode);
81
+ }
82
+ throw e;
83
+ }
84
+ }
@@ -0,0 +1,2 @@
1
+ import type Conf from 'conf';
2
+ export declare function setupMaster(masterIp: string, port: string, model: string, config: Conf<any>): Promise<void>;
@@ -0,0 +1,60 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ export async function setupMaster(masterIp, port, model, config) {
4
+ const masterUrl = `http://${masterIp}:${port}`;
5
+ console.log(chalk.bold('\n⚡ Infinicode Setup'));
6
+ console.log(chalk.dim('─'.repeat(40)));
7
+ console.log(` Master: ${chalk.cyan(masterUrl)}`);
8
+ console.log(` Model: ${chalk.cyan(model)}`);
9
+ console.log();
10
+ const spinner = ora('Testing connection...').start();
11
+ try {
12
+ const response = await fetch(`${masterUrl}/api/tags`, {
13
+ signal: AbortSignal.timeout(10000)
14
+ });
15
+ if (!response.ok) {
16
+ throw new Error(`HTTP ${response.status}`);
17
+ }
18
+ const data = await response.json();
19
+ spinner.succeed('Connected to Ollama');
20
+ // Save config
21
+ config.set('masterUrl', masterUrl);
22
+ config.set('defaultModel', model);
23
+ // Show available models
24
+ console.log(chalk.bold('\nAvailable models:'));
25
+ const models = data.models || [];
26
+ if (models.length === 0) {
27
+ console.log(chalk.yellow(' No models found. Pull one with:'));
28
+ console.log(chalk.dim(` ollama pull ${model}`));
29
+ }
30
+ else {
31
+ for (const m of models.slice(0, 10)) {
32
+ const isDefault = m.name === model || m.name.startsWith(model.split(':')[0]);
33
+ console.log(` ${isDefault ? chalk.green('●') : chalk.dim('○')} ${m.name}`);
34
+ }
35
+ if (models.length > 10) {
36
+ console.log(chalk.dim(` ... and ${models.length - 10} more`));
37
+ }
38
+ }
39
+ // Check if default model exists
40
+ const hasModel = models.some(m => m.name === model || m.name.startsWith(model.split(':')[0]));
41
+ if (!hasModel && models.length > 0) {
42
+ console.log(chalk.yellow(`\n⚠️ Model '${model}' not found.`));
43
+ console.log(chalk.dim(` Available: ${models.slice(0, 3).map(m => m.name).join(', ')}`));
44
+ console.log(chalk.dim(` Pull it: ollama pull ${model}`));
45
+ }
46
+ console.log(chalk.green('\n✓ Configuration saved!'));
47
+ console.log(chalk.dim('\nRun `infinicode` or `ic` to start coding.\n'));
48
+ }
49
+ catch (error) {
50
+ spinner.fail('Connection failed');
51
+ console.log(chalk.red(`\n✗ Could not connect to ${masterUrl}`));
52
+ console.log(chalk.dim('\nMake sure Ollama is running with network access:'));
53
+ console.log(chalk.cyan(' OLLAMA_HOST=0.0.0.0:11434 ollama serve'));
54
+ console.log(chalk.dim('\nOr via systemd:'));
55
+ console.log(chalk.cyan(' sudo systemctl edit ollama'));
56
+ console.log(chalk.dim(' Add: Environment="OLLAMA_HOST=0.0.0.0:11434"'));
57
+ console.log(chalk.cyan(' sudo systemctl restart ollama\n'));
58
+ process.exit(1);
59
+ }
60
+ }
@@ -0,0 +1,2 @@
1
+ import type Conf from 'conf';
2
+ export declare function showStatus(config: Conf<any>): Promise<void>;
@@ -0,0 +1,40 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ export async function showStatus(config) {
4
+ const masterUrl = config.get('masterUrl');
5
+ const defaultModel = config.get('defaultModel');
6
+ console.log(chalk.bold('\n⚡ Infinicode Status'));
7
+ console.log(chalk.dim('─'.repeat(40)));
8
+ console.log(` Master URL: ${chalk.cyan(masterUrl)}`);
9
+ console.log(` Default Model: ${chalk.cyan(defaultModel)}`);
10
+ const spinner = ora('Checking connection...').start();
11
+ try {
12
+ const response = await fetch(`${masterUrl}/api/tags`, {
13
+ signal: AbortSignal.timeout(5000)
14
+ });
15
+ if (!response.ok) {
16
+ throw new Error(`HTTP ${response.status}`);
17
+ }
18
+ const data = await response.json();
19
+ spinner.succeed('Ollama connected');
20
+ const models = data.models || [];
21
+ console.log(` Models: ${chalk.green(models.length)} available`);
22
+ // Check if default model is available
23
+ const hasDefault = models.some(m => m.name === defaultModel || m.name.startsWith(defaultModel.split(':')[0]));
24
+ if (hasDefault) {
25
+ console.log(` Status: ${chalk.green('● Ready')}`);
26
+ }
27
+ else {
28
+ console.log(` Status: ${chalk.yellow('● Missing model')}`);
29
+ console.log(chalk.yellow(`\n ⚠️ Default model '${defaultModel}' not found.`));
30
+ console.log(chalk.dim(` Pull it: ollama pull ${defaultModel}`));
31
+ }
32
+ }
33
+ catch (error) {
34
+ spinner.fail('Connection failed');
35
+ console.log(` Status: ${chalk.red('● Offline')}`);
36
+ console.log(chalk.red(`\n ✗ Could not reach ${masterUrl}`));
37
+ console.log(chalk.dim(' Is Ollama running with OLLAMA_HOST=0.0.0.0?'));
38
+ }
39
+ console.log();
40
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "infinicode",
3
+ "version": "1.0.0",
4
+ "description": "AI coding agent powered by your local Ollama. Fork of OpenCode optimized for self-hosted LLMs.",
5
+ "type": "module",
6
+ "main": "./dist/cli.js",
7
+ "bin": {
8
+ "infinicode": "./bin/infinicode.js",
9
+ "ic": "./bin/infinicode.js"
10
+ },
11
+ "files": [
12
+ "bin",
13
+ "dist",
14
+ "README.md"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsc --watch",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "keywords": [
22
+ "ai",
23
+ "coding",
24
+ "agent",
25
+ "ollama",
26
+ "llm",
27
+ "cli",
28
+ "opencode",
29
+ "local",
30
+ "self-hosted"
31
+ ],
32
+ "author": "Ra Kai'Un",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/chosen-to-build/infinicode"
37
+ },
38
+ "engines": {
39
+ "node": ">=20"
40
+ },
41
+ "dependencies": {
42
+ "chalk": "^5.3.0",
43
+ "commander": "^12.1.0",
44
+ "conf": "^12.0.0",
45
+ "execa": "^9.3.0",
46
+ "inquirer": "^9.2.23",
47
+ "node-fetch": "^3.3.2",
48
+ "ora": "^8.0.1"
49
+ },
50
+ "devDependencies": {
51
+ "@types/inquirer": "^9.0.9",
52
+ "@types/node": "^20.14.0",
53
+ "typescript": "^5.4.5"
54
+ }
55
+ }