@ekkos/cli 1.3.6 → 1.3.7
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/LICENSE +21 -0
- package/dist/commands/dashboard.js +29 -10
- package/dist/commands/gemini.js +12 -1
- package/dist/index.js +101 -26
- package/package.json +7 -10
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ekkOS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -71,7 +71,9 @@ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12
|
|
|
71
71
|
// ── Pricing ──
|
|
72
72
|
// Pricing per MTok from https://platform.claude.com/docs/en/about-claude/pricing
|
|
73
73
|
const MODEL_PRICING = {
|
|
74
|
+
'claude-opus-4-6-20260514': { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.50 },
|
|
74
75
|
'claude-opus-4-6': { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.50 },
|
|
76
|
+
'claude-sonnet-4-6-20260514': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 },
|
|
75
77
|
'claude-opus-4-5-20250620': { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.50 },
|
|
76
78
|
'claude-sonnet-4-6': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 },
|
|
77
79
|
'claude-sonnet-4-5-20250929': { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.30 },
|
|
@@ -96,12 +98,23 @@ function calculateTurnCost(model, usage) {
|
|
|
96
98
|
(usage.cache_creation_tokens / 1000000) * p.cacheWrite +
|
|
97
99
|
(usage.cache_read_tokens / 1000000) * p.cacheRead);
|
|
98
100
|
}
|
|
99
|
-
function getModelCtxSize(model) {
|
|
100
|
-
|
|
101
|
+
function getModelCtxSize(model, contextTierHint) {
|
|
102
|
+
const normalized = (model || '').toLowerCase();
|
|
103
|
+
if (contextTierHint === '1m')
|
|
104
|
+
return 1000000;
|
|
105
|
+
// Claude 4.6 has GA 1M context in Claude Code/API.
|
|
106
|
+
if (/^claude-(?:opus|sonnet)-4-6(?:$|-)/.test(normalized))
|
|
107
|
+
return 1000000;
|
|
108
|
+
// Keep Gemini on the 1M class in dashboard context math.
|
|
109
|
+
if (normalized.startsWith('gemini-'))
|
|
110
|
+
return 1000000;
|
|
111
|
+
if (normalized.includes('1m'))
|
|
112
|
+
return 1000000;
|
|
113
|
+
if (normalized.includes('opus'))
|
|
101
114
|
return 200000;
|
|
102
|
-
if (
|
|
115
|
+
if (normalized.includes('haiku'))
|
|
103
116
|
return 200000;
|
|
104
|
-
if (
|
|
117
|
+
if (normalized.includes('sonnet'))
|
|
105
118
|
return 200000;
|
|
106
119
|
return 200000; // Default Anthropic context
|
|
107
120
|
}
|
|
@@ -183,12 +196,15 @@ function parseJsonlFile(jsonlPath, sessionName) {
|
|
|
183
196
|
const evictionState = typeof entry.message._ekkos_eviction_state === 'string'
|
|
184
197
|
? entry.message._ekkos_eviction_state
|
|
185
198
|
: (parseCacheHintValue(cacheHint, 'eviction') || 'unknown');
|
|
199
|
+
const contextTierHint = typeof entry.message._ekkos_context_tier === 'string'
|
|
200
|
+
? entry.message._ekkos_context_tier.trim().toLowerCase()
|
|
201
|
+
: undefined;
|
|
186
202
|
const inputTokens = usage.input_tokens || 0;
|
|
187
203
|
const outputTokens = usage.output_tokens || 0;
|
|
188
204
|
const cacheReadTokens = usage.cache_read_input_tokens || 0;
|
|
189
205
|
const cacheCreationTokens = usage.cache_creation_input_tokens || 0;
|
|
190
206
|
const contextTokens = inputTokens + cacheReadTokens + cacheCreationTokens;
|
|
191
|
-
const modelCtxSize = getModelCtxSize(
|
|
207
|
+
const modelCtxSize = getModelCtxSize(routedModel, contextTierHint);
|
|
192
208
|
const contextPct = (contextTokens / modelCtxSize) * 100;
|
|
193
209
|
const ts = entry.timestamp || new Date().toISOString();
|
|
194
210
|
if (!startedAt)
|
|
@@ -215,6 +231,7 @@ function parseJsonlFile(jsonlPath, sessionName) {
|
|
|
215
231
|
const turnData = {
|
|
216
232
|
turn: turnNum,
|
|
217
233
|
contextPct,
|
|
234
|
+
modelContextSize: modelCtxSize,
|
|
218
235
|
input: inputTokens,
|
|
219
236
|
cacheRead: cacheReadTokens,
|
|
220
237
|
cacheCreate: cacheCreationTokens,
|
|
@@ -267,7 +284,9 @@ function parseJsonlFile(jsonlPath, sessionName) {
|
|
|
267
284
|
const currentContextTokens = lastTurn
|
|
268
285
|
? lastTurn.input + lastTurn.cacheRead + lastTurn.cacheCreate
|
|
269
286
|
: 0;
|
|
270
|
-
const modelContextSize =
|
|
287
|
+
const modelContextSize = lastTurn
|
|
288
|
+
? lastTurn.modelContextSize
|
|
289
|
+
: getModelCtxSize(model);
|
|
271
290
|
return {
|
|
272
291
|
sessionName,
|
|
273
292
|
model,
|
|
@@ -1100,8 +1119,8 @@ async function launchDashboard(initialSessionName, initialJsonlPath, refreshMs,
|
|
|
1100
1119
|
try {
|
|
1101
1120
|
const ctxPct = Math.min(data.currentContextPct, 100);
|
|
1102
1121
|
const ctxColor = ctxPct < 50 ? 'green' : ctxPct < 80 ? 'yellow' : 'red';
|
|
1103
|
-
const
|
|
1104
|
-
const
|
|
1122
|
+
const tokensLabel = fmtK(data.currentContextTokens);
|
|
1123
|
+
const maxLabel = fmtK(data.modelContextSize);
|
|
1105
1124
|
// Visual progress bar (fills available width)
|
|
1106
1125
|
const contextInnerWidth = Math.max(10, contextBox.width - 2);
|
|
1107
1126
|
// Extend bar slightly closer to mascot while keeping a small visual gap.
|
|
@@ -1121,7 +1140,7 @@ async function launchDashboard(initialSessionName, initialJsonlPath, refreshMs,
|
|
|
1121
1140
|
const hitColor = data.cacheHitRate >= 80 ? 'green' : data.cacheHitRate >= 50 ? 'yellow' : 'red';
|
|
1122
1141
|
const cappedMax = Math.min(data.maxContextPct, 100);
|
|
1123
1142
|
contextBox.setContent(` ${bar}\n` +
|
|
1124
|
-
` {${ctxColor}-fg}${ctxPct.toFixed(0)}%{/${ctxColor}-fg} ${
|
|
1143
|
+
` {${ctxColor}-fg}${ctxPct.toFixed(0)}%{/${ctxColor}-fg} ${tokensLabel}/${maxLabel}` +
|
|
1125
1144
|
` {white-fg}Input{/white-fg} $${breakdown.input.toFixed(2)}` +
|
|
1126
1145
|
` {green-fg}Read{/green-fg} $${breakdown.read.toFixed(2)}` +
|
|
1127
1146
|
` {yellow-fg}Write{/yellow-fg} $${breakdown.write.toFixed(2)}` +
|
|
@@ -1766,7 +1785,7 @@ async function launchDashboard(initialSessionName, initialJsonlPath, refreshMs,
|
|
|
1766
1785
|
const tier = cachedProfile.organization?.rate_limit_tier ?? 'unknown';
|
|
1767
1786
|
const status = cachedProfile.organization?.subscription_status ?? 'unknown';
|
|
1768
1787
|
const extraUsage = cachedProfile.organization?.has_extra_usage_enabled
|
|
1769
|
-
? ' {green-fg}extra usage on{/green-fg}'
|
|
1788
|
+
? ' {green-fg}extra usage on{/green-fg} {gray-fg}(legacy >200k only){/gray-fg}'
|
|
1770
1789
|
: '';
|
|
1771
1790
|
line2 =
|
|
1772
1791
|
` {bold}Plan:{/bold} ${plan} {bold}Tier:{/bold} ${tier} {bold}Sub:{/bold} ${status}${extraUsage}`;
|
package/dist/commands/gemini.js
CHANGED
|
@@ -154,8 +154,19 @@ async function gemini(options = {}) {
|
|
|
154
154
|
console.log(chalk_1.default.cyan(' 🧠 ekkOS_Continuum Loaded!'));
|
|
155
155
|
}
|
|
156
156
|
console.log('');
|
|
157
|
+
// Extract any trailing arguments meant for the inner CLI
|
|
158
|
+
// We look for 'gemini' in process.argv and pass everything after it.
|
|
159
|
+
// If the user did `ekkos gemini -m gemini-3.1-pro-preview`, we want to pass `-m gemini-3.1-pro-preview`
|
|
160
|
+
let extraArgs = [];
|
|
161
|
+
const geminiIdx = process.argv.indexOf('gemini');
|
|
162
|
+
if (geminiIdx !== -1) {
|
|
163
|
+
extraArgs = process.argv.slice(geminiIdx + 1).filter(a => {
|
|
164
|
+
// Filter out ekkos wrapper options
|
|
165
|
+
return !['--skip-proxy', '-v', '--verbose'].includes(a) && !(a === '-s' || a === '--session' || process.argv[process.argv.indexOf(a) - 1] === '-s' || process.argv[process.argv.indexOf(a) - 1] === '--session');
|
|
166
|
+
});
|
|
167
|
+
}
|
|
157
168
|
// Spawn Gemini CLI — stdio: inherit for full terminal passthrough
|
|
158
|
-
const child = (0, child_process_1.spawn)(geminiPath,
|
|
169
|
+
const child = (0, child_process_1.spawn)(geminiPath, extraArgs, {
|
|
159
170
|
stdio: 'inherit',
|
|
160
171
|
env,
|
|
161
172
|
cwd: process.cwd(),
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,7 @@ const scan_1 = require("./commands/scan");
|
|
|
59
59
|
const chalk_1 = __importDefault(require("chalk"));
|
|
60
60
|
const fs = __importStar(require("fs"));
|
|
61
61
|
const path = __importStar(require("path"));
|
|
62
|
+
const child_process_1 = require("child_process");
|
|
62
63
|
// Get version from package.json (CommonJS compatible)
|
|
63
64
|
const pkgPath = path.resolve(__dirname, '../package.json');
|
|
64
65
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
@@ -75,16 +76,12 @@ commander_1.program
|
|
|
75
76
|
.addHelpText('after', [
|
|
76
77
|
'',
|
|
77
78
|
chalk_1.default.cyan.bold('Examples:'),
|
|
78
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos')} ${chalk_1.default.gray('Start Claude Code with ekkOS memory (default
|
|
79
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
80
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
81
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
82
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos
|
|
83
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos run
|
|
84
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos doctor --fix')} ${chalk_1.default.gray('Check and auto-fix system prerequisites')}`,
|
|
85
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos usage daily')} ${chalk_1.default.gray("View today's token usage and costs")}`,
|
|
86
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos gemini')} ${chalk_1.default.gray('Launch Gemini CLI with ekkOS memory proxy')}`,
|
|
87
|
-
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos swarm launch -t "build X"')} ${chalk_1.default.gray('Launch parallel workers on a task')}`,
|
|
79
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos')} ${chalk_1.default.gray('Start Claude Code with ekkOS memory (default)')}`,
|
|
80
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos codex')} ${chalk_1.default.gray('Start Codex (OpenAI) mode')}`,
|
|
81
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos daemon start')} ${chalk_1.default.gray('Start the background mobile sync service')}`,
|
|
82
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos connect gemini')} ${chalk_1.default.gray('Securely store your Gemini API key in the cloud')}`,
|
|
83
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos agent create --path ./repo')} ${chalk_1.default.gray('Spawn a headless remote agent in a directory')}`,
|
|
84
|
+
` ${chalk_1.default.gray('$')} ${chalk_1.default.white('ekkos run --dashboard')} ${chalk_1.default.gray('Launch Claude with live usage dashboard')}`,
|
|
88
85
|
'',
|
|
89
86
|
chalk_1.default.gray(' Run ') + chalk_1.default.white('ekkos <command> --help') + chalk_1.default.gray(' for detailed options on any command.'),
|
|
90
87
|
'',
|
|
@@ -152,38 +149,48 @@ commander_1.program
|
|
|
152
149
|
title: 'Getting Started',
|
|
153
150
|
icon: '▸',
|
|
154
151
|
commands: [
|
|
155
|
-
{ name: 'init', desc: '
|
|
152
|
+
{ name: 'init', desc: 'First-time setup — authenticate and configure IDEs' },
|
|
156
153
|
{ name: 'scan', desc: 'Scan repo structure and seed ekkOS system registry' },
|
|
157
|
-
{ name: 'status', desc: 'Show
|
|
158
|
-
{ name: '
|
|
159
|
-
{ name: 'doctor', desc: 'Check system prerequisites (Node, PTY, Claude, MCP)' },
|
|
154
|
+
{ name: 'status', desc: 'Show overall system status (Memory, Sync Daemon, Auth)' },
|
|
155
|
+
{ name: 'doctor', desc: 'Check system prerequisites and fix runaway processes' },
|
|
160
156
|
],
|
|
161
157
|
},
|
|
162
158
|
{
|
|
163
|
-
title: '
|
|
159
|
+
title: 'Launch Agents (Local + Mobile Synced)',
|
|
164
160
|
icon: '▸',
|
|
165
161
|
commands: [
|
|
166
|
-
{ name: 'run', desc: 'Launch Claude Code with
|
|
167
|
-
{ name: '
|
|
168
|
-
{ name: '
|
|
169
|
-
{ name: '
|
|
162
|
+
{ name: 'run', desc: 'Launch Claude Code with memory and mobile control', note: 'default' },
|
|
163
|
+
{ name: 'codex', desc: 'Launch Codex (OpenAI) with mobile control' },
|
|
164
|
+
{ name: 'gemini', desc: 'Launch Gemini mode (ACP) with mobile control' },
|
|
165
|
+
{ name: 'acp', desc: 'Launch a generic ACP-compatible agent' },
|
|
170
166
|
],
|
|
171
167
|
},
|
|
172
168
|
{
|
|
173
|
-
title: '
|
|
169
|
+
title: 'Mobile Sync & Cloud (Synk)',
|
|
174
170
|
icon: '▸',
|
|
175
171
|
commands: [
|
|
176
|
-
{ name: '
|
|
177
|
-
{ name: '
|
|
178
|
-
{ name: '
|
|
179
|
-
{ name: '
|
|
172
|
+
{ name: 'daemon', desc: 'Manage background mobile sync service (start, stop, status)' },
|
|
173
|
+
{ name: 'connect', desc: 'Securely store AI vendor API keys in the cloud' },
|
|
174
|
+
{ name: 'sandbox', desc: 'Configure OS-level sandboxing for agent execution' },
|
|
175
|
+
{ name: 'notify', desc: 'Send push notifications to your Synk mobile app' },
|
|
180
176
|
],
|
|
181
177
|
},
|
|
182
178
|
{
|
|
183
|
-
title: '
|
|
179
|
+
title: 'Headless Agents (Remote Control)',
|
|
184
180
|
icon: '▸',
|
|
185
181
|
commands: [
|
|
186
|
-
{ name: '
|
|
182
|
+
{ name: 'agent', desc: 'Manage remote headless agents (create, list, stop)' },
|
|
183
|
+
{ name: 'swarm', desc: 'Parallel workers, Q-learning routing, and swarm dashboard' },
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
title: 'Monitoring & Usage',
|
|
188
|
+
icon: '▸',
|
|
189
|
+
commands: [
|
|
190
|
+
{ name: 'auth', desc: 'Manage authentication for Memory, Agents, and Mobile App' },
|
|
191
|
+
{ name: 'usage', desc: 'Token usage and cost tracking (daily, weekly, monthly, session)' },
|
|
192
|
+
{ name: 'dashboard', desc: 'Live TUI dashboard for session monitoring' },
|
|
193
|
+
{ name: 'sessions', desc: 'List active local CLI sessions' },
|
|
187
194
|
],
|
|
188
195
|
},
|
|
189
196
|
];
|
|
@@ -501,6 +508,74 @@ swarmCmd
|
|
|
501
508
|
(0, swarm_setup_1.swarmSetup)();
|
|
502
509
|
});
|
|
503
510
|
swarmCmd.addCommand(swarm_dashboard_1.swarmDashboardCommand);
|
|
511
|
+
// --- Remote & Agent Wrapper Helpers ---
|
|
512
|
+
function runRemoteCommand(command, ...args) {
|
|
513
|
+
const isAgent = command === 'agent';
|
|
514
|
+
const pkgName = isAgent ? 'ekkos-agent' : 'ekkos-remote';
|
|
515
|
+
const binName = isAgent ? 'ekkos-agent.mjs' : 'ekkos-synk.mjs';
|
|
516
|
+
// Try resolving local monorepo first
|
|
517
|
+
let binPath = path.resolve(__dirname, '../../' + pkgName + '/bin/' + binName);
|
|
518
|
+
// If we are installed globally (dist folder structure), resolve relatively
|
|
519
|
+
if (!fs.existsSync(binPath)) {
|
|
520
|
+
try {
|
|
521
|
+
const globalPath = require.resolve('@ekkos/' + (isAgent ? 'agent' : 'remote') + '/package.json');
|
|
522
|
+
binPath = path.join(path.dirname(globalPath), 'bin', binName);
|
|
523
|
+
}
|
|
524
|
+
catch (e) {
|
|
525
|
+
// Fallback relative to current dist
|
|
526
|
+
binPath = path.resolve(__dirname, '../../' + pkgName + '/bin/' + binName);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
const p = (0, child_process_1.spawn)('node', [binPath, ...args], {
|
|
530
|
+
stdio: 'inherit',
|
|
531
|
+
env: process.env
|
|
532
|
+
});
|
|
533
|
+
p.on('exit', (code) => {
|
|
534
|
+
process.exit(code || 0);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
// Mobile Sync & Cloud (Synk) Commands
|
|
538
|
+
commander_1.program
|
|
539
|
+
.command('auth')
|
|
540
|
+
.description('Manage authentication for Memory, Agents, and Mobile App')
|
|
541
|
+
.allowUnknownOption()
|
|
542
|
+
.action(() => runRemoteCommand('synk', 'auth', ...process.argv.slice(3)));
|
|
543
|
+
commander_1.program
|
|
544
|
+
.command('codex')
|
|
545
|
+
.description('Launch Codex (OpenAI) with mobile control')
|
|
546
|
+
.allowUnknownOption()
|
|
547
|
+
.action(() => runRemoteCommand('synk', 'codex', ...process.argv.slice(3)));
|
|
548
|
+
commander_1.program
|
|
549
|
+
.command('acp')
|
|
550
|
+
.description('Launch a generic ACP-compatible agent')
|
|
551
|
+
.allowUnknownOption()
|
|
552
|
+
.action(() => runRemoteCommand('synk', 'acp', ...process.argv.slice(3)));
|
|
553
|
+
commander_1.program
|
|
554
|
+
.command('daemon')
|
|
555
|
+
.description('Manage background mobile sync service (start, stop, status)')
|
|
556
|
+
.allowUnknownOption()
|
|
557
|
+
.action(() => runRemoteCommand('synk', 'daemon', ...process.argv.slice(3)));
|
|
558
|
+
commander_1.program
|
|
559
|
+
.command('connect')
|
|
560
|
+
.description('Securely store AI vendor API keys in the cloud')
|
|
561
|
+
.allowUnknownOption()
|
|
562
|
+
.action(() => runRemoteCommand('synk', 'connect', ...process.argv.slice(3)));
|
|
563
|
+
commander_1.program
|
|
564
|
+
.command('sandbox')
|
|
565
|
+
.description('Configure OS-level sandboxing for agent execution')
|
|
566
|
+
.allowUnknownOption()
|
|
567
|
+
.action(() => runRemoteCommand('synk', 'sandbox', ...process.argv.slice(3)));
|
|
568
|
+
commander_1.program
|
|
569
|
+
.command('notify')
|
|
570
|
+
.description('Send push notifications to your Synk mobile app')
|
|
571
|
+
.allowUnknownOption()
|
|
572
|
+
.action(() => runRemoteCommand('synk', 'notify', ...process.argv.slice(3)));
|
|
573
|
+
// Headless Agents (Remote Control)
|
|
574
|
+
commander_1.program
|
|
575
|
+
.command('agent')
|
|
576
|
+
.description('Manage remote headless agents (create, list, stop)')
|
|
577
|
+
.allowUnknownOption()
|
|
578
|
+
.action(() => runRemoteCommand('agent', ...process.argv.slice(3)));
|
|
504
579
|
// Handle `-help` (single dash) — rewrite to `--help` for Commander compatibility
|
|
505
580
|
const helpIdx = process.argv.indexOf('-help');
|
|
506
581
|
if (helpIdx !== -1) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ekkos/cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,13 +8,6 @@
|
|
|
8
8
|
"cli": "dist/index.js",
|
|
9
9
|
"ekkos-capture": "dist/cache/capture.js"
|
|
10
10
|
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsc",
|
|
13
|
-
"dev": "tsx src/index.ts",
|
|
14
|
-
"prepack": "node scripts/build-templates.js prepack",
|
|
15
|
-
"postpack": "node scripts/build-templates.js postpack",
|
|
16
|
-
"prepublishOnly": "npm run build"
|
|
17
|
-
},
|
|
18
11
|
"keywords": [
|
|
19
12
|
"ekkos",
|
|
20
13
|
"ai",
|
|
@@ -58,5 +51,9 @@
|
|
|
58
51
|
"!dist/cron",
|
|
59
52
|
"templates/CLAUDE.md",
|
|
60
53
|
"templates/skills"
|
|
61
|
-
]
|
|
62
|
-
|
|
54
|
+
],
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "tsc",
|
|
57
|
+
"dev": "tsx src/index.ts"
|
|
58
|
+
}
|
|
59
|
+
}
|