@remits/remits-cli 0.1.100 → 0.1.101
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 +3 -1
- package/index.js +143 -5
- package/package.json +1 -1
- package/skills/remits-cli/SKILL.md +8 -1
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ On each command run, `remits-cli` checks the npm `latest` version for `@remits/r
|
|
|
16
16
|
remits-cli auth --base-url https://your-remits-host --account-id 123
|
|
17
17
|
remits-cli start
|
|
18
18
|
remits-cli status
|
|
19
|
+
remits-cli whoami
|
|
19
20
|
remits-cli stop
|
|
20
21
|
remits-cli install --skills
|
|
21
22
|
remits-cli tools
|
|
@@ -97,7 +98,8 @@ remits-cli install --skills --overwrite true
|
|
|
97
98
|
- Most non-lifecycle commands auto-start the background service if authenticated sessions already exist and no service is running.
|
|
98
99
|
- Successful `remits-cli auth` also attempts to auto-start the background service.
|
|
99
100
|
- `remits-cli start` starts a detached background process by default. Use `remits-cli start --foreground true` only when you want to run the daemon in the current terminal.
|
|
100
|
-
- `remits-cli status` reports whether the background service is alive
|
|
101
|
+
- `remits-cli status` reports whether the background service is alive, prints the dashboard URL when available, and prints the resolved session tuple: Account ID, User ID, current git branch, and active data mode.
|
|
102
|
+
- `remits-cli whoami` prints only the resolved session tuple. Use `--base-url`, `--account-id`, and `--data-mode` to prove the exact host/account/lane before running a tool or test.
|
|
101
103
|
- `remits-cli stop` stops the background service, kills the shared tmux session, and clears pane tracking state.
|
|
102
104
|
- The service starts a localhost dashboard that acts as a control center for remits-cli integration state.
|
|
103
105
|
- The dashboard shows websocket connection health, topic subscriptions, tmux session/panes, the discovered account repo index, global state files, and per-repo remits-cli files.
|
package/index.js
CHANGED
|
@@ -278,6 +278,110 @@ function printResolvedBaseUrl(baseUrl) {
|
|
|
278
278
|
console.log('Base URL:', normalizeBaseUrl(baseUrl || DEFAULT_BASE_URL));
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
+
function accountNameFromAccountInfo(info) {
|
|
282
|
+
return (info && (
|
|
283
|
+
(info.resolution && info.resolution.accountName) ||
|
|
284
|
+
(info.repoContext && info.repoContext.accountInfoAccountName) ||
|
|
285
|
+
info.name ||
|
|
286
|
+
info.accountName ||
|
|
287
|
+
(info.account && info.account.name)
|
|
288
|
+
)) || null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function resolveSessionIdentity(cwd, flags = {}) {
|
|
292
|
+
let accountId = null;
|
|
293
|
+
const fromFlag = Number(flags['account-id']);
|
|
294
|
+
if (Number.isFinite(fromFlag) && fromFlag > 0) {
|
|
295
|
+
accountId = fromFlag;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const accountInfo = loadAccountInfo(cwd);
|
|
299
|
+
if (!accountId && accountInfo) {
|
|
300
|
+
accountId = Number(accountIdFromAccountInfo(accountInfo));
|
|
301
|
+
try { updateAccountRepoIndex(cwd); } catch (_) { /* best-effort */ }
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const requestedBaseUrl = flags['base-url'] ? normalizeBaseUrl(flags['base-url']) : null;
|
|
305
|
+
const requestedDataMode = hasExplicitDataModeFlag(flags) ? resolveDataMode(flags, null) : null;
|
|
306
|
+
const session = readSession({
|
|
307
|
+
accountId,
|
|
308
|
+
baseUrl: requestedBaseUrl,
|
|
309
|
+
dataMode: requestedDataMode
|
|
310
|
+
}, {
|
|
311
|
+
strictBaseUrl: Boolean(requestedBaseUrl),
|
|
312
|
+
strictDataMode: Boolean(requestedDataMode)
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
if (!accountId && session && session.accountId) {
|
|
316
|
+
accountId = Number(session.accountId);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const dataMode = requestedDataMode || resolveDataMode(flags, session);
|
|
320
|
+
const branchName = flags.branch || flags.branchName || currentBranch(cwd);
|
|
321
|
+
const user = session && session.user ? session.user : {};
|
|
322
|
+
const repoName = accountNameFromAccountInfo(accountInfo);
|
|
323
|
+
const localAccountInfoAccountId = accountInfo ? Number(accountIdFromAccountInfo(accountInfo)) : null;
|
|
324
|
+
const sessionResolutionWarning = session
|
|
325
|
+
? buildSessionResolutionWarning(accountId, requestedBaseUrl, session)
|
|
326
|
+
: null;
|
|
327
|
+
|
|
328
|
+
return {
|
|
329
|
+
authenticated: Boolean(session && session.token),
|
|
330
|
+
accountId: accountId || (session && session.accountId) || null,
|
|
331
|
+
accountName: (session && session.account && session.account.name) || null,
|
|
332
|
+
localAccountName: repoName,
|
|
333
|
+
localAccountInfoAccountId: Number.isFinite(localAccountInfoAccountId) ? localAccountInfoAccountId : null,
|
|
334
|
+
userId: user.id || session?.userId || null,
|
|
335
|
+
userName: user.name || user.username || user.email || null,
|
|
336
|
+
branchName,
|
|
337
|
+
dataMode,
|
|
338
|
+
baseUrl: normalizeBaseUrl((session && session.baseUrl) || requestedBaseUrl || DEFAULT_BASE_URL),
|
|
339
|
+
updatedAt: session ? session.updatedAt : null,
|
|
340
|
+
sessionResolutionWarning
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function printSessionIdentity(identity, options = {}) {
|
|
345
|
+
if (options.json) {
|
|
346
|
+
console.log(JSON.stringify(identity, null, 2));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (!identity.authenticated) {
|
|
351
|
+
console.log('Active session: not authenticated');
|
|
352
|
+
console.log('Account ID:', identity.accountId || 'unresolved');
|
|
353
|
+
console.log('User ID:', 'unresolved');
|
|
354
|
+
console.log('Branch:', identity.branchName || 'unresolved');
|
|
355
|
+
console.log('Data mode:', identity.dataMode || DEFAULT_DATA_MODE);
|
|
356
|
+
console.log('Base URL:', identity.baseUrl);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
console.log('Active session:');
|
|
361
|
+
console.log(' Account ID:', identity.accountId);
|
|
362
|
+
if (identity.accountName) {
|
|
363
|
+
console.log(' Account:', identity.accountName);
|
|
364
|
+
}
|
|
365
|
+
if (identity.localAccountName) {
|
|
366
|
+
let localDetails = identity.localAccountInfoAccountId ? 'id ' + identity.localAccountInfoAccountId : '';
|
|
367
|
+
if (identity.localAccountInfoAccountId && identity.accountId &&
|
|
368
|
+
Number(identity.localAccountInfoAccountId) !== Number(identity.accountId)) {
|
|
369
|
+
localDetails += '; command targets account ' + identity.accountId;
|
|
370
|
+
}
|
|
371
|
+
console.log(' Local repo account:', identity.localAccountName + (localDetails ? ' (' + localDetails + ')' : ''));
|
|
372
|
+
}
|
|
373
|
+
console.log(' User ID:', identity.userId || 'unknown');
|
|
374
|
+
if (identity.userName) {
|
|
375
|
+
console.log(' User:', identity.userName);
|
|
376
|
+
}
|
|
377
|
+
console.log(' Branch:', identity.branchName);
|
|
378
|
+
console.log(' Data mode:', identity.dataMode);
|
|
379
|
+
console.log(' Base URL:', identity.baseUrl);
|
|
380
|
+
if (identity.updatedAt) {
|
|
381
|
+
console.log(' Session updated:', identity.updatedAt);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
281
385
|
// Tools/actions whose names signal they mutate state rather than only reading it. Used solely to make
|
|
282
386
|
// data-lane banners precise — never to block or permit anything.
|
|
283
387
|
const MUTATING_TOOL_PATTERN = /(^|_)(patch|edit|create|commit|update|delete|remove|write|set|assign|run|execute|send|pause|unpause|interrupt|restore|repair|migrate|sync)(_|$)/i;
|
|
@@ -5333,8 +5437,28 @@ async function waitForListenerStopped(timeoutMs = 5000) {
|
|
|
5333
5437
|
return !isListenerRunning();
|
|
5334
5438
|
}
|
|
5335
5439
|
|
|
5336
|
-
async function listenStatusCommand() {
|
|
5440
|
+
async function listenStatusCommand(flags = {}) {
|
|
5441
|
+
const wantsJson = flagEnabled(flags.json);
|
|
5337
5442
|
const state = readServiceState();
|
|
5443
|
+
const identity = resolveSessionIdentity(process.cwd(), flags);
|
|
5444
|
+
|
|
5445
|
+
if (wantsJson) {
|
|
5446
|
+
console.log(JSON.stringify({
|
|
5447
|
+
service: {
|
|
5448
|
+
running: isListenerRunning(),
|
|
5449
|
+
pid: isListenerRunning() && fs.existsSync(LISTENER_PID_FILE)
|
|
5450
|
+
? fs.readFileSync(LISTENER_PID_FILE, 'utf8').trim()
|
|
5451
|
+
: null,
|
|
5452
|
+
dashboardUrl: state.dashboardUrl || null,
|
|
5453
|
+
indexedRepos: state.discovery && Number.isFinite(state.discovery.repoCount)
|
|
5454
|
+
? state.discovery.repoCount
|
|
5455
|
+
: null
|
|
5456
|
+
},
|
|
5457
|
+
session: identity
|
|
5458
|
+
}, null, 2));
|
|
5459
|
+
return;
|
|
5460
|
+
}
|
|
5461
|
+
|
|
5338
5462
|
if (isListenerRunning()) {
|
|
5339
5463
|
const pid = fs.readFileSync(LISTENER_PID_FILE, 'utf8').trim();
|
|
5340
5464
|
console.log('remits-cli service is running (pid: ' + pid + ')');
|
|
@@ -5347,6 +5471,14 @@ async function listenStatusCommand() {
|
|
|
5347
5471
|
} else {
|
|
5348
5472
|
console.log('remits-cli service is not running.');
|
|
5349
5473
|
}
|
|
5474
|
+
printSessionResolutionWarning(identity);
|
|
5475
|
+
printSessionIdentity(identity);
|
|
5476
|
+
}
|
|
5477
|
+
|
|
5478
|
+
async function whoamiCommand(flags = {}) {
|
|
5479
|
+
const identity = resolveSessionIdentity(process.cwd(), flags);
|
|
5480
|
+
printSessionResolutionWarning(identity);
|
|
5481
|
+
printSessionIdentity(identity, { json: flagEnabled(flags.json) });
|
|
5350
5482
|
}
|
|
5351
5483
|
|
|
5352
5484
|
function npmCommand() {
|
|
@@ -5618,7 +5750,7 @@ async function main() {
|
|
|
5618
5750
|
|
|
5619
5751
|
// Auto-start the background service if not already running.
|
|
5620
5752
|
// Skip for lifecycle subcommands and help.
|
|
5621
|
-
const isLifecycleCmd = command === 'listen' || command === 'start' || command === 'stop' || command === 'status';
|
|
5753
|
+
const isLifecycleCmd = command === 'listen' || command === 'start' || command === 'stop' || command === 'status' || command === 'whoami';
|
|
5622
5754
|
const isHelpCmd = !command || command === 'help' || command === '--help' || wantsHelp;
|
|
5623
5755
|
if (!wantsJson && !isHelpCmd && !isLifecycleCmd && !isListenerRunning()) {
|
|
5624
5756
|
try {
|
|
@@ -5647,7 +5779,8 @@ async function main() {
|
|
|
5647
5779
|
console.log(' remits-cli config [set] [--agent claude|codex|gemini]');
|
|
5648
5780
|
console.log(' remits-cli start [--foreground true] [--port 8787]');
|
|
5649
5781
|
console.log(' remits-cli stop');
|
|
5650
|
-
console.log(' remits-cli status');
|
|
5782
|
+
console.log(' remits-cli status [--base-url URL] [--account-id ID] [--data-mode test|prod] [--json]');
|
|
5783
|
+
console.log(' remits-cli whoami [--base-url URL] [--account-id ID] [--data-mode test|prod] [--json]');
|
|
5651
5784
|
console.log(' remits-cli listen [stop|status] [--foreground true] # compatibility alias');
|
|
5652
5785
|
console.log(' remits-cli data-mode [set test|prod]');
|
|
5653
5786
|
console.log(' remits-cli install --skills [--target codex|claude|gemini|all] [--overwrite true]');
|
|
@@ -5759,7 +5892,7 @@ async function main() {
|
|
|
5759
5892
|
return;
|
|
5760
5893
|
}
|
|
5761
5894
|
if (subcommand === 'status') {
|
|
5762
|
-
await listenStatusCommand();
|
|
5895
|
+
await listenStatusCommand(args);
|
|
5763
5896
|
return;
|
|
5764
5897
|
}
|
|
5765
5898
|
await listenCommand(args);
|
|
@@ -5777,7 +5910,12 @@ async function main() {
|
|
|
5777
5910
|
}
|
|
5778
5911
|
|
|
5779
5912
|
if (command === 'status') {
|
|
5780
|
-
await listenStatusCommand();
|
|
5913
|
+
await listenStatusCommand(args);
|
|
5914
|
+
return;
|
|
5915
|
+
}
|
|
5916
|
+
|
|
5917
|
+
if (command === 'whoami') {
|
|
5918
|
+
await whoamiCommand(args);
|
|
5781
5919
|
return;
|
|
5782
5920
|
}
|
|
5783
5921
|
|
package/package.json
CHANGED
|
@@ -2448,6 +2448,11 @@ remits-cli sessions remove --account-id 42 --base-url http://localhost:8080
|
|
|
2448
2448
|
|
|
2449
2449
|
You can work in multiple account repos simultaneously across different terminal windows — each uses its own session. You can also be authenticated against different base URLs (e.g., localhost for development and production) for the same account at the same time.
|
|
2450
2450
|
|
|
2451
|
+
Use `remits-cli whoami` when you need a compact proof of the active target before a sensitive operation.
|
|
2452
|
+
It prints the resolved Account ID, User ID, current git branch, data mode, and base URL. `remits-cli status`
|
|
2453
|
+
prints the same session tuple after the service/dashboard status. Pass `--base-url`, `--account-id`, and
|
|
2454
|
+
`--data-mode` when host or lane matters; do not infer those values from the repo directory or account name.
|
|
2455
|
+
|
|
2451
2456
|
## Persistent Service, Control Center, and Agent Dispatch
|
|
2452
2457
|
|
|
2453
2458
|
The current mental model is a **background remits-cli service**, not just a listener.
|
|
@@ -2463,6 +2468,7 @@ That service does three jobs:
|
|
|
2463
2468
|
remits-cli start
|
|
2464
2469
|
remits-cli start --foreground true
|
|
2465
2470
|
remits-cli status
|
|
2471
|
+
remits-cli whoami
|
|
2466
2472
|
remits-cli stop
|
|
2467
2473
|
```
|
|
2468
2474
|
|
|
@@ -2586,7 +2592,8 @@ remits-cli sessions [list|remove] [--account-id ID]
|
|
|
2586
2592
|
remits-cli config [set] [--agent claude|codex|gemini]
|
|
2587
2593
|
remits-cli start [--foreground true] [--port 8787]
|
|
2588
2594
|
remits-cli stop
|
|
2589
|
-
remits-cli status
|
|
2595
|
+
remits-cli status [--base-url URL] [--account-id ID] [--data-mode test|prod] [--json]
|
|
2596
|
+
remits-cli whoami [--base-url URL] [--account-id ID] [--data-mode test|prod] [--json]
|
|
2590
2597
|
remits-cli listen [stop|status] [--foreground true] # compatibility alias
|
|
2591
2598
|
remits-cli data-mode [set test|prod]
|
|
2592
2599
|
remits-cli components stage [--branch <name>] [--data-mode test|prod] [--json|--verbose]
|