@ekkos/cli 1.3.1 → 1.3.2
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/dist/commands/dashboard.js +147 -57
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +54 -16
- package/dist/commands/run.js +163 -44
- package/dist/commands/status.d.ts +4 -1
- package/dist/commands/status.js +165 -27
- package/dist/commands/synk.d.ts +7 -0
- package/dist/commands/synk.js +339 -0
- package/dist/deploy/settings.d.ts +6 -5
- package/dist/deploy/settings.js +27 -17
- package/dist/index.js +12 -82
- package/dist/lib/usage-parser.d.ts +1 -1
- package/dist/lib/usage-parser.js +5 -3
- package/dist/local/index.d.ts +14 -0
- package/dist/local/index.js +28 -0
- package/dist/local/local-embeddings.d.ts +49 -0
- package/dist/local/local-embeddings.js +232 -0
- package/dist/local/offline-fallback.d.ts +44 -0
- package/dist/local/offline-fallback.js +159 -0
- package/dist/local/sqlite-store.d.ts +126 -0
- package/dist/local/sqlite-store.js +393 -0
- package/dist/local/sync-engine.d.ts +42 -0
- package/dist/local/sync-engine.js +223 -0
- package/dist/synk/api.d.ts +22 -0
- package/dist/synk/api.js +133 -0
- package/dist/synk/auth.d.ts +7 -0
- package/dist/synk/auth.js +30 -0
- package/dist/synk/config.d.ts +18 -0
- package/dist/synk/config.js +37 -0
- package/dist/synk/daemon/control-client.d.ts +11 -0
- package/dist/synk/daemon/control-client.js +101 -0
- package/dist/synk/daemon/control-server.d.ts +24 -0
- package/dist/synk/daemon/control-server.js +91 -0
- package/dist/synk/daemon/run.d.ts +14 -0
- package/dist/synk/daemon/run.js +338 -0
- package/dist/synk/encryption.d.ts +17 -0
- package/dist/synk/encryption.js +133 -0
- package/dist/synk/index.d.ts +13 -0
- package/dist/synk/index.js +36 -0
- package/dist/synk/machine-client.d.ts +42 -0
- package/dist/synk/machine-client.js +218 -0
- package/dist/synk/persistence.d.ts +51 -0
- package/dist/synk/persistence.js +211 -0
- package/dist/synk/qr.d.ts +5 -0
- package/dist/synk/qr.js +33 -0
- package/dist/synk/session-bridge.d.ts +58 -0
- package/dist/synk/session-bridge.js +171 -0
- package/dist/synk/session-client.d.ts +46 -0
- package/dist/synk/session-client.js +240 -0
- package/dist/synk/types.d.ts +574 -0
- package/dist/synk/types.js +74 -0
- package/dist/utils/platform.d.ts +5 -1
- package/dist/utils/platform.js +24 -4
- package/dist/utils/proxy-url.d.ts +10 -0
- package/dist/utils/proxy-url.js +19 -0
- package/dist/utils/state.d.ts +1 -1
- package/dist/utils/state.js +11 -3
- package/package.json +13 -4
- package/templates/claude-plugins-admin/AGENT_TEAM_PROPOSALS.md +0 -819
- package/templates/claude-plugins-admin/README.md +0 -446
- package/templates/claude-plugins-admin/autonomous-admin-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/autonomous-admin-agent/commands/agent.md +0 -595
- package/templates/claude-plugins-admin/backend-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/backend-agent/commands/backend.md +0 -798
- package/templates/claude-plugins-admin/deploy-guardian/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/deploy-guardian/commands/deploy.md +0 -554
- package/templates/claude-plugins-admin/frontend-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/frontend-agent/commands/frontend.md +0 -881
- package/templates/claude-plugins-admin/mcp-server-manager/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/mcp-server-manager/commands/mcp.md +0 -85
- package/templates/claude-plugins-admin/memory-system-monitor/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/memory-system-monitor/commands/memory-health.md +0 -569
- package/templates/claude-plugins-admin/qa-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/qa-agent/commands/qa.md +0 -863
- package/templates/claude-plugins-admin/tech-lead-agent/.claude-plugin/plugin.json +0 -8
- package/templates/claude-plugins-admin/tech-lead-agent/commands/lead.md +0 -732
- package/templates/hooks-node/lib/state.js +0 -187
- package/templates/hooks-node/stop.js +0 -416
- package/templates/hooks-node/user-prompt-submit.js +0 -337
- package/templates/rules/00-hooks-contract.mdc +0 -89
- package/templates/rules/30-ekkos-core.mdc +0 -188
- package/templates/rules/31-ekkos-messages.mdc +0 -78
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ekkOS_synk commands — remote session sync for Claude Code
|
|
4
|
+
*
|
|
5
|
+
* Provides: ekkos synk auth, connect, disconnect, sessions, daemon start/stop/status, doctor
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.registerSynkCommands = registerSynkCommands;
|
|
45
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
46
|
+
function registerSynkCommands(program) {
|
|
47
|
+
const synkCmd = program
|
|
48
|
+
.command('synk')
|
|
49
|
+
.description('Remote session sync — control Claude Code from anywhere');
|
|
50
|
+
// ── Auth ──
|
|
51
|
+
synkCmd
|
|
52
|
+
.command('auth')
|
|
53
|
+
.description('Authenticate with synk-server and display QR code for mobile pairing')
|
|
54
|
+
.option('-f, --force', 'Force re-authentication')
|
|
55
|
+
.action(async (options) => {
|
|
56
|
+
const { synkConfig } = await Promise.resolve().then(() => __importStar(require('../synk/config')));
|
|
57
|
+
const { readCredentials } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
58
|
+
const { getRandomBytes, encodeBase64 } = await Promise.resolve().then(() => __importStar(require('../synk/encryption')));
|
|
59
|
+
const { authGetToken, generateAppUrl } = await Promise.resolve().then(() => __importStar(require('../synk/auth')));
|
|
60
|
+
const { displayQRCode } = await Promise.resolve().then(() => __importStar(require('../synk/qr')));
|
|
61
|
+
synkConfig.ensureDirectories();
|
|
62
|
+
let credentials = await readCredentials();
|
|
63
|
+
if (credentials && !options.force) {
|
|
64
|
+
console.log(chalk_1.default.green(' Already authenticated with synk-server.'));
|
|
65
|
+
console.log(chalk_1.default.gray(` Server: ${synkConfig.serverUrl}`));
|
|
66
|
+
console.log(chalk_1.default.gray(` Use --force to re-authenticate.`));
|
|
67
|
+
// Still show QR code for mobile pairing
|
|
68
|
+
if (credentials.encryption.type === 'legacy') {
|
|
69
|
+
const url = generateAppUrl(credentials.encryption.secret);
|
|
70
|
+
displayQRCode(url);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
console.log('');
|
|
75
|
+
console.log(chalk_1.default.cyan.bold(' ekkOS_synk') + chalk_1.default.gray(' — Setting up remote session sync'));
|
|
76
|
+
console.log('');
|
|
77
|
+
// Generate new secret key
|
|
78
|
+
const secret = getRandomBytes(32);
|
|
79
|
+
try {
|
|
80
|
+
const token = await authGetToken(secret);
|
|
81
|
+
const { writeCredentialsLegacy } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
82
|
+
await writeCredentialsLegacy({ secret, token });
|
|
83
|
+
console.log(chalk_1.default.green(' Authenticated successfully!'));
|
|
84
|
+
console.log(chalk_1.default.gray(` Server: ${synkConfig.serverUrl}`));
|
|
85
|
+
console.log(chalk_1.default.gray(` Credentials saved to: ${synkConfig.credentialsFile}`));
|
|
86
|
+
// Show QR code for mobile pairing
|
|
87
|
+
const url = generateAppUrl(secret);
|
|
88
|
+
displayQRCode(url);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error(chalk_1.default.red(` Authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// ── Status (default when running `ekkos synk`) ──
|
|
96
|
+
synkCmd
|
|
97
|
+
.command('status', { isDefault: true })
|
|
98
|
+
.description('Show synk connection status')
|
|
99
|
+
.action(async () => {
|
|
100
|
+
const { synkConfig } = await Promise.resolve().then(() => __importStar(require('../synk/config')));
|
|
101
|
+
const { readCredentials, readDaemonState } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
102
|
+
console.log('');
|
|
103
|
+
console.log(chalk_1.default.cyan.bold(' ekkOS_synk') + chalk_1.default.gray(' — Remote Session Sync'));
|
|
104
|
+
console.log('');
|
|
105
|
+
// Check credentials
|
|
106
|
+
const credentials = await readCredentials();
|
|
107
|
+
if (!credentials) {
|
|
108
|
+
console.log(chalk_1.default.yellow(' Not authenticated.'));
|
|
109
|
+
console.log(chalk_1.default.gray(' Run: ') + chalk_1.default.white('ekkos synk auth'));
|
|
110
|
+
console.log('');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
console.log(` ${chalk_1.default.green('●')} Authenticated`);
|
|
114
|
+
console.log(chalk_1.default.gray(` Server: ${synkConfig.serverUrl}`));
|
|
115
|
+
// Check daemon
|
|
116
|
+
const daemonState = await readDaemonState();
|
|
117
|
+
if (daemonState) {
|
|
118
|
+
try {
|
|
119
|
+
process.kill(daemonState.pid, 0);
|
|
120
|
+
console.log(` ${chalk_1.default.green('●')} Daemon running`);
|
|
121
|
+
console.log(chalk_1.default.gray(` PID: ${daemonState.pid} | Port: ${daemonState.httpPort}`));
|
|
122
|
+
console.log(chalk_1.default.gray(` Started: ${daemonState.startTime}`));
|
|
123
|
+
if (daemonState.lastHeartbeat) {
|
|
124
|
+
console.log(chalk_1.default.gray(` Last heartbeat: ${daemonState.lastHeartbeat}`));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
console.log(` ${chalk_1.default.red('●')} Daemon not running (stale state)`);
|
|
129
|
+
console.log(chalk_1.default.gray(' Run: ') + chalk_1.default.white('ekkos synk daemon start'));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
console.log(` ${chalk_1.default.gray('○')} Daemon not running`);
|
|
134
|
+
console.log(chalk_1.default.gray(' Run: ') + chalk_1.default.white('ekkos synk daemon start'));
|
|
135
|
+
}
|
|
136
|
+
console.log('');
|
|
137
|
+
});
|
|
138
|
+
// ── Connect ──
|
|
139
|
+
synkCmd
|
|
140
|
+
.command('connect')
|
|
141
|
+
.description('Start daemon and connect to synk-server')
|
|
142
|
+
.action(async () => {
|
|
143
|
+
const { readCredentials } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
144
|
+
const credentials = await readCredentials();
|
|
145
|
+
if (!credentials) {
|
|
146
|
+
console.log(chalk_1.default.yellow(' Not authenticated. Run: ') + chalk_1.default.white('ekkos synk auth'));
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
console.log(chalk_1.default.cyan(' Starting synk daemon...'));
|
|
150
|
+
// Spawn daemon in detached mode
|
|
151
|
+
const { spawn } = await Promise.resolve().then(() => __importStar(require('node:child_process')));
|
|
152
|
+
const child = spawn(process.execPath, [process.argv[1], 'synk', 'daemon', 'start-sync'], {
|
|
153
|
+
detached: true,
|
|
154
|
+
stdio: 'ignore',
|
|
155
|
+
});
|
|
156
|
+
child.unref();
|
|
157
|
+
// Wait a moment and check if it started
|
|
158
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
159
|
+
const { readDaemonState } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
160
|
+
const state = await readDaemonState();
|
|
161
|
+
if (state) {
|
|
162
|
+
console.log(chalk_1.default.green(' Daemon started successfully!'));
|
|
163
|
+
console.log(chalk_1.default.gray(` PID: ${state.pid} | Port: ${state.httpPort}`));
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
console.log(chalk_1.default.yellow(' Daemon may still be starting. Check: ') + chalk_1.default.white('ekkos synk status'));
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
// ── Disconnect ──
|
|
170
|
+
synkCmd
|
|
171
|
+
.command('disconnect')
|
|
172
|
+
.description('Stop the synk daemon')
|
|
173
|
+
.action(async () => {
|
|
174
|
+
const { stopDaemon } = await Promise.resolve().then(() => __importStar(require('../synk/daemon/control-client')));
|
|
175
|
+
console.log(chalk_1.default.cyan(' Stopping synk daemon...'));
|
|
176
|
+
await stopDaemon();
|
|
177
|
+
console.log(chalk_1.default.green(' Daemon stopped.'));
|
|
178
|
+
});
|
|
179
|
+
// ── Sessions ──
|
|
180
|
+
synkCmd
|
|
181
|
+
.command('sessions')
|
|
182
|
+
.description('List active synk sessions')
|
|
183
|
+
.option('-j, --json', 'Output as JSON')
|
|
184
|
+
.action(async (options) => {
|
|
185
|
+
const { listDaemonSessions } = await Promise.resolve().then(() => __importStar(require('../synk/daemon/control-client')));
|
|
186
|
+
const sessions = await listDaemonSessions();
|
|
187
|
+
if (options.json) {
|
|
188
|
+
console.log(JSON.stringify(sessions, null, 2));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
console.log('');
|
|
192
|
+
console.log(chalk_1.default.cyan.bold(' Synk Sessions'));
|
|
193
|
+
console.log('');
|
|
194
|
+
if (sessions.length === 0) {
|
|
195
|
+
console.log(chalk_1.default.gray(' No active sessions.'));
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
for (const session of sessions) {
|
|
199
|
+
console.log(` ${chalk_1.default.green('●')} ${chalk_1.default.bold(session.synkSessionId || 'unknown')}`);
|
|
200
|
+
console.log(chalk_1.default.gray(` PID: ${session.pid} | Started by: ${session.startedBy}`));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
console.log('');
|
|
204
|
+
});
|
|
205
|
+
// ── Daemon subcommand ──
|
|
206
|
+
const daemonCmd = synkCmd
|
|
207
|
+
.command('daemon')
|
|
208
|
+
.description('Manage the synk background daemon');
|
|
209
|
+
daemonCmd
|
|
210
|
+
.command('start')
|
|
211
|
+
.description('Start the synk daemon')
|
|
212
|
+
.option('-v, --verbose', 'Show verbose output')
|
|
213
|
+
.action(async (options) => {
|
|
214
|
+
const { checkIfDaemonRunning } = await Promise.resolve().then(() => __importStar(require('../synk/daemon/control-client')));
|
|
215
|
+
const running = await checkIfDaemonRunning();
|
|
216
|
+
if (running) {
|
|
217
|
+
console.log(chalk_1.default.yellow(' Daemon is already running.'));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
console.log(chalk_1.default.cyan(' Starting synk daemon...'));
|
|
221
|
+
const { spawn } = await Promise.resolve().then(() => __importStar(require('node:child_process')));
|
|
222
|
+
const child = spawn(process.execPath, [process.argv[1], 'synk', 'daemon', 'start-sync'], {
|
|
223
|
+
detached: true,
|
|
224
|
+
stdio: options.verbose ? 'inherit' : 'ignore',
|
|
225
|
+
});
|
|
226
|
+
child.unref();
|
|
227
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
228
|
+
const { readDaemonState } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
229
|
+
const state = await readDaemonState();
|
|
230
|
+
if (state) {
|
|
231
|
+
console.log(chalk_1.default.green(' Daemon started.'));
|
|
232
|
+
console.log(chalk_1.default.gray(` PID: ${state.pid} | Port: ${state.httpPort}`));
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
console.log(chalk_1.default.yellow(' Daemon may still be starting...'));
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
// Internal: start-sync runs the daemon in the foreground (called by detached process)
|
|
239
|
+
daemonCmd
|
|
240
|
+
.command('start-sync')
|
|
241
|
+
.description('Run daemon in foreground (internal)')
|
|
242
|
+
.action(async () => {
|
|
243
|
+
const { startDaemon } = await Promise.resolve().then(() => __importStar(require('../synk/daemon/run')));
|
|
244
|
+
await startDaemon();
|
|
245
|
+
});
|
|
246
|
+
daemonCmd
|
|
247
|
+
.command('stop')
|
|
248
|
+
.description('Stop the synk daemon')
|
|
249
|
+
.action(async () => {
|
|
250
|
+
const { stopDaemon } = await Promise.resolve().then(() => __importStar(require('../synk/daemon/control-client')));
|
|
251
|
+
console.log(chalk_1.default.cyan(' Stopping synk daemon...'));
|
|
252
|
+
await stopDaemon();
|
|
253
|
+
console.log(chalk_1.default.green(' Daemon stopped.'));
|
|
254
|
+
});
|
|
255
|
+
daemonCmd
|
|
256
|
+
.command('status')
|
|
257
|
+
.description('Show daemon status')
|
|
258
|
+
.option('-j, --json', 'Output as JSON')
|
|
259
|
+
.action(async (options) => {
|
|
260
|
+
const { readDaemonState } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
261
|
+
const state = await readDaemonState();
|
|
262
|
+
if (options.json) {
|
|
263
|
+
console.log(JSON.stringify(state, null, 2));
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (!state) {
|
|
267
|
+
console.log(chalk_1.default.gray(' Daemon is not running.'));
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
process.kill(state.pid, 0);
|
|
272
|
+
console.log(` ${chalk_1.default.green('●')} Daemon running`);
|
|
273
|
+
console.log(chalk_1.default.gray(` PID: ${state.pid}`));
|
|
274
|
+
console.log(chalk_1.default.gray(` Port: ${state.httpPort}`));
|
|
275
|
+
console.log(chalk_1.default.gray(` Started: ${state.startTime}`));
|
|
276
|
+
console.log(chalk_1.default.gray(` Version: ${state.startedWithCliVersion}`));
|
|
277
|
+
if (state.lastHeartbeat) {
|
|
278
|
+
console.log(chalk_1.default.gray(` Last heartbeat: ${state.lastHeartbeat}`));
|
|
279
|
+
}
|
|
280
|
+
if (state.daemonLogPath) {
|
|
281
|
+
console.log(chalk_1.default.gray(` Log: ${state.daemonLogPath}`));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
console.log(` ${chalk_1.default.red('●')} Daemon not running (stale state file)`);
|
|
286
|
+
console.log(chalk_1.default.gray(' Cleaning up...'));
|
|
287
|
+
const { clearDaemonState } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
288
|
+
await clearDaemonState();
|
|
289
|
+
console.log(chalk_1.default.gray(' Done.'));
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
// ── Doctor ──
|
|
293
|
+
synkCmd
|
|
294
|
+
.command('doctor')
|
|
295
|
+
.description('Diagnose synk connectivity and configuration')
|
|
296
|
+
.action(async () => {
|
|
297
|
+
const { synkConfig } = await Promise.resolve().then(() => __importStar(require('../synk/config')));
|
|
298
|
+
const { readCredentials, readDaemonState } = await Promise.resolve().then(() => __importStar(require('../synk/persistence')));
|
|
299
|
+
const axios = (await Promise.resolve().then(() => __importStar(require('axios')))).default;
|
|
300
|
+
console.log('');
|
|
301
|
+
console.log(chalk_1.default.cyan.bold(' ekkOS_synk Doctor'));
|
|
302
|
+
console.log('');
|
|
303
|
+
// Check config
|
|
304
|
+
console.log(chalk_1.default.gray(' Server URL: ') + synkConfig.serverUrl);
|
|
305
|
+
console.log(chalk_1.default.gray(' Data dir: ') + synkConfig.synkHomeDir);
|
|
306
|
+
// Check credentials
|
|
307
|
+
const credentials = await readCredentials();
|
|
308
|
+
if (credentials) {
|
|
309
|
+
console.log(` ${chalk_1.default.green('✓')} Credentials found`);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
console.log(` ${chalk_1.default.red('✗')} No credentials — run "ekkos synk auth"`);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
// Check server connectivity
|
|
316
|
+
try {
|
|
317
|
+
const response = await axios.get(synkConfig.serverUrl, { timeout: 5000 });
|
|
318
|
+
console.log(` ${chalk_1.default.green('✓')} Server reachable`);
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
console.log(` ${chalk_1.default.red('✗')} Server unreachable: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
322
|
+
}
|
|
323
|
+
// Check daemon
|
|
324
|
+
const daemonState = await readDaemonState();
|
|
325
|
+
if (daemonState) {
|
|
326
|
+
try {
|
|
327
|
+
process.kill(daemonState.pid, 0);
|
|
328
|
+
console.log(` ${chalk_1.default.green('✓')} Daemon running (PID ${daemonState.pid})`);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
console.log(` ${chalk_1.default.yellow('!')} Stale daemon state (PID ${daemonState.pid} not running)`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
console.log(` ${chalk_1.default.gray('○')} Daemon not running`);
|
|
336
|
+
}
|
|
337
|
+
console.log('');
|
|
338
|
+
});
|
|
339
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Claude Code settings.json management for ekkOS.
|
|
3
|
+
* - Disables Claude's built-in auto-memory (ekkOS replaces it with 11-layer memory)
|
|
4
|
+
* - Cleans up any legacy hooks entries
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
* Deploy Claude Code settings.json —
|
|
8
|
-
*
|
|
7
|
+
* Deploy Claude Code settings.json — disables auto-memory and cleans up legacy hooks.
|
|
8
|
+
* ekkOS provides its own memory system via MCP, so Claude's built-in auto-memory
|
|
9
|
+
* is redundant and wastes ~1K tokens/turn on duplicate context.
|
|
9
10
|
*/
|
|
10
11
|
export declare function deployClaudeSettings(): void;
|
|
11
12
|
/**
|
package/dist/deploy/settings.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Claude Code settings.json management for ekkOS.
|
|
4
|
+
* - Disables Claude's built-in auto-memory (ekkOS replaces it with 11-layer memory)
|
|
5
|
+
* - Cleans up any legacy hooks entries
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.deployClaudeSettings = deployClaudeSettings;
|
|
@@ -10,28 +10,38 @@ exports.areHooksConfigured = areHooksConfigured;
|
|
|
10
10
|
const fs_1 = require("fs");
|
|
11
11
|
const platform_1 = require("../utils/platform");
|
|
12
12
|
/**
|
|
13
|
-
* Deploy Claude Code settings.json —
|
|
14
|
-
*
|
|
13
|
+
* Deploy Claude Code settings.json — disables auto-memory and cleans up legacy hooks.
|
|
14
|
+
* ekkOS provides its own memory system via MCP, so Claude's built-in auto-memory
|
|
15
|
+
* is redundant and wastes ~1K tokens/turn on duplicate context.
|
|
15
16
|
*/
|
|
16
17
|
function deployClaudeSettings() {
|
|
17
18
|
// Ensure .claude directory exists
|
|
18
19
|
if (!(0, fs_1.existsSync)(platform_1.CLAUDE_DIR)) {
|
|
19
20
|
(0, fs_1.mkdirSync)(platform_1.CLAUDE_DIR, { recursive: true });
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
delete settings.hooks;
|
|
30
|
-
(0, fs_1.writeFileSync)(platform_1.CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
|
|
22
|
+
let settings = {};
|
|
23
|
+
if ((0, fs_1.existsSync)(platform_1.CLAUDE_SETTINGS)) {
|
|
24
|
+
try {
|
|
25
|
+
settings = JSON.parse((0, fs_1.readFileSync)(platform_1.CLAUDE_SETTINGS, 'utf-8'));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Invalid JSON — start fresh
|
|
29
|
+
settings = {};
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
let changed = false;
|
|
33
|
+
// Disable Claude's built-in auto-memory — ekkOS replaces it
|
|
34
|
+
if (settings.autoMemoryEnabled !== false) {
|
|
35
|
+
settings.autoMemoryEnabled = false;
|
|
36
|
+
changed = true;
|
|
37
|
+
}
|
|
38
|
+
// Remove any previously-installed ekkOS hooks entries
|
|
39
|
+
if ('hooks' in settings) {
|
|
40
|
+
delete settings.hooks;
|
|
41
|
+
changed = true;
|
|
42
|
+
}
|
|
43
|
+
if (changed) {
|
|
44
|
+
(0, fs_1.writeFileSync)(platform_1.CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
|
|
35
45
|
}
|
|
36
46
|
}
|
|
37
47
|
/**
|
package/dist/index.js
CHANGED
|
@@ -47,14 +47,13 @@ const doctor_1 = require("./commands/doctor");
|
|
|
47
47
|
const stream_1 = require("./commands/stream");
|
|
48
48
|
// DEPRECATED: Hooks removed in hookless architecture migration
|
|
49
49
|
// hooksInstall, hooksVerify, hooksStatus no longer called — `hooks` command prints a deprecation notice.
|
|
50
|
-
const setup_remote_1 = require("./commands/setup-remote");
|
|
51
|
-
const agent_1 = require("./commands/agent");
|
|
52
50
|
const state_1 = require("./utils/state");
|
|
53
51
|
const index_1 = require("./commands/usage/index");
|
|
54
52
|
const dashboard_1 = require("./commands/dashboard");
|
|
55
53
|
const swarm_1 = require("./commands/swarm");
|
|
56
54
|
const swarm_dashboard_1 = require("./commands/swarm-dashboard");
|
|
57
55
|
const swarm_setup_1 = require("./commands/swarm-setup");
|
|
56
|
+
const synk_1 = require("./commands/synk");
|
|
58
57
|
const chalk_1 = __importDefault(require("chalk"));
|
|
59
58
|
const fs = __importStar(require("fs"));
|
|
60
59
|
const path = __importStar(require("path"));
|
|
@@ -174,11 +173,10 @@ commander_1.program
|
|
|
174
173
|
],
|
|
175
174
|
},
|
|
176
175
|
{
|
|
177
|
-
title: 'Remote
|
|
176
|
+
title: 'Synk (Remote Session Sync)',
|
|
178
177
|
icon: '▸',
|
|
179
178
|
commands: [
|
|
180
|
-
{ name: '
|
|
181
|
-
{ name: 'agent', desc: 'Manage the remote terminal agent (start, stop, status, logs)' },
|
|
179
|
+
{ name: 'synk', desc: 'Remote session sync — control Claude Code from anywhere' },
|
|
182
180
|
],
|
|
183
181
|
},
|
|
184
182
|
{
|
|
@@ -224,14 +222,19 @@ commander_1.program
|
|
|
224
222
|
.option('-i, --ide <ide>', 'IDE to setup (claude, cursor, windsurf, all)')
|
|
225
223
|
.option('-k, --key <key>', 'Use API key instead of device auth')
|
|
226
224
|
.option('-f, --force', 'Force re-authentication and overwrite existing config')
|
|
225
|
+
.option('-q, --quick', 'Quick setup: auto-detect IDE, use defaults, only prompt for API key if missing')
|
|
227
226
|
.option('--skip-hooks', '[DEPRECATED] Hooks are no longer deployed; this flag is a no-op')
|
|
228
227
|
.option('--skip-skills', 'Skip skills deployment')
|
|
229
228
|
.action(init_1.init);
|
|
230
229
|
// Status command
|
|
231
230
|
commander_1.program
|
|
232
231
|
.command('status')
|
|
233
|
-
.description('Show
|
|
234
|
-
.
|
|
232
|
+
.description('Show live session metrics and memory status')
|
|
233
|
+
.option('-w, --watch', 'Watch mode — refresh session panel every 2s')
|
|
234
|
+
.option('--json', 'Output raw metrics JSON (no memory API call)')
|
|
235
|
+
.action((options) => {
|
|
236
|
+
(0, status_1.status)({ watch: options.watch, json: options.json });
|
|
237
|
+
});
|
|
235
238
|
// Test command
|
|
236
239
|
commander_1.program
|
|
237
240
|
.command('test')
|
|
@@ -382,82 +385,9 @@ commander_1.program
|
|
|
382
385
|
});
|
|
383
386
|
});
|
|
384
387
|
// ============================================================================
|
|
385
|
-
//
|
|
388
|
+
// SYNK COMMANDS (Remote Session Sync)
|
|
386
389
|
// ============================================================================
|
|
387
|
-
|
|
388
|
-
commander_1.program
|
|
389
|
-
.command('setup-remote')
|
|
390
|
-
.description('Set up remote terminal access (run Claude on your PC from anywhere)')
|
|
391
|
-
.option('-f, --force', 'Force re-pairing even if already paired')
|
|
392
|
-
.option('--skip-service', 'Skip installing background service')
|
|
393
|
-
.option('-v, --verbose', 'Show detailed output')
|
|
394
|
-
.action((options) => {
|
|
395
|
-
(0, setup_remote_1.setupRemote)({
|
|
396
|
-
force: options.force,
|
|
397
|
-
skipService: options.skipService,
|
|
398
|
-
verbose: options.verbose,
|
|
399
|
-
});
|
|
400
|
-
});
|
|
401
|
-
// Agent command - manage the background agent
|
|
402
|
-
const agentCmd = commander_1.program
|
|
403
|
-
.command('agent')
|
|
404
|
-
.description('Manage the remote terminal agent');
|
|
405
|
-
agentCmd
|
|
406
|
-
.command('daemon')
|
|
407
|
-
.description('Run the agent daemon (used by system service)')
|
|
408
|
-
.option('-v, --verbose', 'Show verbose output')
|
|
409
|
-
.action((options) => {
|
|
410
|
-
(0, agent_1.agentDaemon)({ verbose: options.verbose });
|
|
411
|
-
});
|
|
412
|
-
agentCmd
|
|
413
|
-
.command('start')
|
|
414
|
-
.description('Start the agent service')
|
|
415
|
-
.option('-v, --verbose', 'Show verbose output')
|
|
416
|
-
.action((options) => {
|
|
417
|
-
(0, agent_1.agentStart)({ verbose: options.verbose });
|
|
418
|
-
});
|
|
419
|
-
agentCmd
|
|
420
|
-
.command('stop')
|
|
421
|
-
.description('Stop the agent service')
|
|
422
|
-
.option('-v, --verbose', 'Show verbose output')
|
|
423
|
-
.action((options) => {
|
|
424
|
-
(0, agent_1.agentStop)({ verbose: options.verbose });
|
|
425
|
-
});
|
|
426
|
-
agentCmd
|
|
427
|
-
.command('restart')
|
|
428
|
-
.description('Restart the agent service')
|
|
429
|
-
.option('-v, --verbose', 'Show verbose output')
|
|
430
|
-
.action((options) => {
|
|
431
|
-
(0, agent_1.agentRestart)({ verbose: options.verbose });
|
|
432
|
-
});
|
|
433
|
-
agentCmd
|
|
434
|
-
.command('status')
|
|
435
|
-
.description('Check agent status and connection')
|
|
436
|
-
.option('-v, --verbose', 'Show verbose output')
|
|
437
|
-
.action((options) => {
|
|
438
|
-
(0, agent_1.agentStatus)({ verbose: options.verbose });
|
|
439
|
-
});
|
|
440
|
-
agentCmd
|
|
441
|
-
.command('uninstall')
|
|
442
|
-
.description('Remove the agent service and unpair device')
|
|
443
|
-
.option('-v, --verbose', 'Show verbose output')
|
|
444
|
-
.action((options) => {
|
|
445
|
-
(0, agent_1.agentUninstall)({ verbose: options.verbose });
|
|
446
|
-
});
|
|
447
|
-
agentCmd
|
|
448
|
-
.command('logs')
|
|
449
|
-
.description('Show agent logs')
|
|
450
|
-
.option('-f, --follow', 'Follow log output (like tail -f)')
|
|
451
|
-
.action((options) => {
|
|
452
|
-
(0, agent_1.agentLogs)({ follow: options.follow });
|
|
453
|
-
});
|
|
454
|
-
agentCmd
|
|
455
|
-
.command('health')
|
|
456
|
-
.description('Check agent daemon health and diagnose connection issues')
|
|
457
|
-
.option('-j, --json', 'Output machine-readable JSON')
|
|
458
|
-
.action((options) => {
|
|
459
|
-
(0, agent_1.agentHealth)({ json: options.json });
|
|
460
|
-
});
|
|
390
|
+
(0, synk_1.registerSynkCommands)(commander_1.program);
|
|
461
391
|
// Swarm command - manage Q-learning routing
|
|
462
392
|
const swarmCmd = commander_1.program
|
|
463
393
|
.command('swarm')
|
|
@@ -13,7 +13,7 @@ interface SessionNameResolution {
|
|
|
13
13
|
encodedProjectPath: string;
|
|
14
14
|
startedAt?: string;
|
|
15
15
|
}
|
|
16
|
-
/** Detect ekkOS 3-word session names like "lit-lex-zip" */
|
|
16
|
+
/** Detect ekkOS 3-word session names like "lit-lex-zip" or "ink-net-wag-235" */
|
|
17
17
|
export declare function isEkkosSessionName(name: string): boolean;
|
|
18
18
|
/** Resolve an ekkOS session name to a JSONL UUID */
|
|
19
19
|
export declare function resolveSessionName(name: string): SessionNameResolution | null;
|
package/dist/lib/usage-parser.js
CHANGED
|
@@ -74,12 +74,14 @@ function calculateTurnCost(model, usage) {
|
|
|
74
74
|
(usage.cache_creation_tokens / 1000000) * p.cacheWrite +
|
|
75
75
|
(usage.cache_read_tokens / 1000000) * p.cacheRead);
|
|
76
76
|
}
|
|
77
|
-
/** Detect ekkOS 3-word session names like "lit-lex-zip" */
|
|
77
|
+
/** Detect ekkOS 3-word session names like "lit-lex-zip" or "ink-net-wag-235" */
|
|
78
78
|
function isEkkosSessionName(name) {
|
|
79
|
-
return /^[a-z]+-[a-z]+-[a-z]
|
|
79
|
+
return /^[a-z]+-[a-z]+-[a-z]+(-\d+)?$/.test(name);
|
|
80
80
|
}
|
|
81
81
|
function encodeProjectPath(projectPath) {
|
|
82
|
-
|
|
82
|
+
// Claude Code replaces all non-alphanumeric chars with '-' in project dir names.
|
|
83
|
+
// This must match Claude's encoding (e.g., /Volumes/ekkOS_Drive → -Volumes-ekkOS-Drive).
|
|
84
|
+
return projectPath.replace(/[^a-zA-Z0-9]/g, '-');
|
|
83
85
|
}
|
|
84
86
|
/** Resolve an ekkOS session name to a JSONL UUID */
|
|
85
87
|
function resolveSessionName(name) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-First Mode — barrel export
|
|
3
|
+
*
|
|
4
|
+
* Phase 6 of the ekkOS Leadership Plan.
|
|
5
|
+
* Provides offline-capable memory, fallback logic, sync, and local embeddings.
|
|
6
|
+
*/
|
|
7
|
+
export { LocalMemoryStore, localStore, } from './sqlite-store';
|
|
8
|
+
export type { Pattern, Directive, EpisodicMemory, SyncQueueItem, StoreStats, } from './sqlite-store';
|
|
9
|
+
export { callWithFallback, isOfflineFallbackReady, OFFLINE_CAPABLE_TOOLS, } from './offline-fallback';
|
|
10
|
+
export type { ToolCallResult, RemoteCallFn, } from './offline-fallback';
|
|
11
|
+
export { SyncEngine, createSyncEngine, } from './sync-engine';
|
|
12
|
+
export type { SyncResult, } from './sync-engine';
|
|
13
|
+
export { generateLocalEmbedding, cosineSimilarity, searchByEmbedding, isEmbeddingAvailable, } from './local-embeddings';
|
|
14
|
+
export type { SimilarityResult, } from './local-embeddings';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Local-First Mode — barrel export
|
|
4
|
+
*
|
|
5
|
+
* Phase 6 of the ekkOS Leadership Plan.
|
|
6
|
+
* Provides offline-capable memory, fallback logic, sync, and local embeddings.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.isEmbeddingAvailable = exports.searchByEmbedding = exports.cosineSimilarity = exports.generateLocalEmbedding = exports.createSyncEngine = exports.SyncEngine = exports.OFFLINE_CAPABLE_TOOLS = exports.isOfflineFallbackReady = exports.callWithFallback = exports.localStore = exports.LocalMemoryStore = void 0;
|
|
10
|
+
// SQLite memory store (Phase 6A)
|
|
11
|
+
var sqlite_store_1 = require("./sqlite-store");
|
|
12
|
+
Object.defineProperty(exports, "LocalMemoryStore", { enumerable: true, get: function () { return sqlite_store_1.LocalMemoryStore; } });
|
|
13
|
+
Object.defineProperty(exports, "localStore", { enumerable: true, get: function () { return sqlite_store_1.localStore; } });
|
|
14
|
+
// Offline MCP fallback (Phase 6B)
|
|
15
|
+
var offline_fallback_1 = require("./offline-fallback");
|
|
16
|
+
Object.defineProperty(exports, "callWithFallback", { enumerable: true, get: function () { return offline_fallback_1.callWithFallback; } });
|
|
17
|
+
Object.defineProperty(exports, "isOfflineFallbackReady", { enumerable: true, get: function () { return offline_fallback_1.isOfflineFallbackReady; } });
|
|
18
|
+
Object.defineProperty(exports, "OFFLINE_CAPABLE_TOOLS", { enumerable: true, get: function () { return offline_fallback_1.OFFLINE_CAPABLE_TOOLS; } });
|
|
19
|
+
// Sync engine (Phase 6C)
|
|
20
|
+
var sync_engine_1 = require("./sync-engine");
|
|
21
|
+
Object.defineProperty(exports, "SyncEngine", { enumerable: true, get: function () { return sync_engine_1.SyncEngine; } });
|
|
22
|
+
Object.defineProperty(exports, "createSyncEngine", { enumerable: true, get: function () { return sync_engine_1.createSyncEngine; } });
|
|
23
|
+
// Local embeddings (Phase 6D)
|
|
24
|
+
var local_embeddings_1 = require("./local-embeddings");
|
|
25
|
+
Object.defineProperty(exports, "generateLocalEmbedding", { enumerable: true, get: function () { return local_embeddings_1.generateLocalEmbedding; } });
|
|
26
|
+
Object.defineProperty(exports, "cosineSimilarity", { enumerable: true, get: function () { return local_embeddings_1.cosineSimilarity; } });
|
|
27
|
+
Object.defineProperty(exports, "searchByEmbedding", { enumerable: true, get: function () { return local_embeddings_1.searchByEmbedding; } });
|
|
28
|
+
Object.defineProperty(exports, "isEmbeddingAvailable", { enumerable: true, get: function () { return local_embeddings_1.isEmbeddingAvailable; } });
|