@zgeoff/atc 2.10.2 → 2.10.4
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zgeoff/atc",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.4",
|
|
4
4
|
"description": "Terminal control tower for coding-agent sessions",
|
|
5
5
|
"homepage": "https://github.com/zgeoff/atc#readme",
|
|
6
6
|
"bugs": "https://github.com/zgeoff/atc/issues",
|
|
@@ -27,9 +27,10 @@
|
|
|
27
27
|
"deadcode": "knip",
|
|
28
28
|
"lint": "oxlint --type-aware --type-check --report-unused-disable-directives-severity error",
|
|
29
29
|
"lint:fix": "oxlint --type-aware --type-check --report-unused-disable-directives-severity error --fix",
|
|
30
|
-
"test": "bun test",
|
|
31
|
-
"test:binary": "bun test --timeout 20000 test/daemon-e2e.test.ts",
|
|
32
|
-
"test:atc-bridge": "bash scripts/test-atc-bridge.sh",
|
|
30
|
+
"test": "bash scripts/with-test-home.sh bun test",
|
|
31
|
+
"test:binary": "bash scripts/with-test-home.sh bun test --timeout 20000 test/daemon-e2e.test.ts",
|
|
32
|
+
"test:atc-bridge": "bash scripts/with-test-home.sh bash scripts/test-atc-bridge.sh",
|
|
33
|
+
"test:isolation": "bash scripts/check-test-isolation.sh",
|
|
33
34
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
34
35
|
"format": "oxfmt . && format-codemod --quiet .",
|
|
35
36
|
"format:check": "oxfmt --check . && format-codemod --check --quiet .",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { homedir } from 'node:os';
|
|
2
1
|
import { join } from 'node:path';
|
|
2
|
+
import { resolveHomeDir } from '../shared/resolve-home-dir';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* An agent CLI's home directory: the named environment variable when it is
|
|
@@ -9,5 +9,5 @@ import { join } from 'node:path';
|
|
|
9
9
|
export function resolveAgentHome(envVar: string, defaultDirName: string): string {
|
|
10
10
|
const home = process.env[envVar];
|
|
11
11
|
|
|
12
|
-
return home !== undefined && home !== '' ? home : join(
|
|
12
|
+
return home !== undefined && home !== '' ? home : join(resolveHomeDir(), defaultDirName);
|
|
13
13
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { stateDir } from '../shared/config';
|
|
5
4
|
import { isRecord } from '../shared/report';
|
|
5
|
+
import { resolveHomeDir } from '../shared/resolve-home-dir';
|
|
6
6
|
import { buildHookSettings } from './build-hook-settings';
|
|
7
7
|
import type { HookSettingsProfile } from './build-hook-settings';
|
|
8
8
|
|
|
@@ -26,7 +26,7 @@ export function writeHookSettings(profile: HookSettingsProfile): string {
|
|
|
26
26
|
*/
|
|
27
27
|
function readStatuslinePadding(): number {
|
|
28
28
|
try {
|
|
29
|
-
const raw = readFileSync(join(
|
|
29
|
+
const raw = readFileSync(join(resolveHomeDir(), '.claude', 'settings.json'), 'utf8');
|
|
30
30
|
const user: unknown = JSON.parse(raw);
|
|
31
31
|
const statusLine = isRecord(user) ? user['statusLine'] : undefined;
|
|
32
32
|
const padding = isRecord(statusLine) ? statusLine['padding'] : undefined;
|
package/src/cli.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { defineCommand, runMain } from 'citty';
|
|
4
4
|
import pkg from '../package.json';
|
|
5
5
|
import { collectRedirectURIs } from './collect-redirect-uris';
|
|
6
|
+
import { normalizeCLIArgs } from './normalize-cli-args';
|
|
6
7
|
import { parsePort } from './parse-port';
|
|
7
8
|
import { getBuild } from './shared/get-build';
|
|
8
9
|
|
|
@@ -134,7 +135,7 @@ const main = defineCommand({
|
|
|
134
135
|
meta: {
|
|
135
136
|
name: 'grants',
|
|
136
137
|
description:
|
|
137
|
-
'List the grants atc mcp --http clients hold, or revoke one with --revoke
|
|
138
|
+
'List the grants atc mcp --http clients hold, or revoke one with --revoke=<id>',
|
|
138
139
|
},
|
|
139
140
|
args: {
|
|
140
141
|
revoke: { type: 'string', description: 'The ID of a grant to revoke' },
|
|
@@ -342,4 +343,4 @@ const main = defineCommand({
|
|
|
342
343
|
},
|
|
343
344
|
});
|
|
344
345
|
|
|
345
|
-
await runMain(main);
|
|
346
|
+
await runMain(main, { rawArgs: normalizeCLIArgs(process.argv.slice(2)) });
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Joins `--revoke <value>` into `--revoke=<value>` before the argument
|
|
3
|
+
* parser sees it. A grant id can start with a dash, and the parser reads a
|
|
4
|
+
* separate dash-led value as a group of short flags; an underscore among
|
|
5
|
+
* them overwrites its positional list and crashes it. Inline, the value
|
|
6
|
+
* stays the option's whatever it starts with.
|
|
7
|
+
*/
|
|
8
|
+
export function normalizeCLIArgs(args: readonly string[]): string[] {
|
|
9
|
+
const normalized: string[] = [];
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < args.length; i++) {
|
|
12
|
+
const arg = args[i];
|
|
13
|
+
const next = args[i + 1];
|
|
14
|
+
|
|
15
|
+
if (arg === '--') {
|
|
16
|
+
normalized.push(...args.slice(i));
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (arg === '--revoke' && next !== undefined) {
|
|
21
|
+
normalized.push(`--revoke=${next}`);
|
|
22
|
+
|
|
23
|
+
i++;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (arg !== undefined) {
|
|
28
|
+
normalized.push(arg);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
package/src/shared/config.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { z } from 'zod';
|
|
5
4
|
import { buildOptionalString } from './build-optional-string';
|
|
@@ -9,6 +8,7 @@ import { collectGateways } from './collect-gateways';
|
|
|
9
8
|
import type { GatewayConfig } from './collect-gateways';
|
|
10
9
|
import { collectHooks } from './collect-hooks';
|
|
11
10
|
import type { HooksConfig } from './collect-hooks';
|
|
11
|
+
import { resolveHomeDir } from './resolve-home-dir';
|
|
12
12
|
|
|
13
13
|
export interface Config {
|
|
14
14
|
claudeBin: string;
|
|
@@ -49,10 +49,10 @@ const DEFAULTS: Config = {
|
|
|
49
49
|
leader: { code: 0, label: '^Space' },
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
const configDir = join(
|
|
52
|
+
const configDir = join(resolveHomeDir(), '.config', 'atc');
|
|
53
53
|
|
|
54
54
|
export const configFile = join(configDir, 'config.json');
|
|
55
|
-
export const stateDir = join(
|
|
55
|
+
export const stateDir = join(resolveHomeDir(), '.local', 'state', 'atc');
|
|
56
56
|
export const socketPath = join(process.env['XDG_RUNTIME_DIR'] ?? stateDir, 'atc.sock');
|
|
57
57
|
export const daemonSocketPath = join(process.env['XDG_RUNTIME_DIR'] ?? stateDir, 'atc-daemon.sock');
|
|
58
58
|
export const eventsSocketPath = join(process.env['XDG_RUNTIME_DIR'] ?? stateDir, 'atc-events.sock');
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The user's home directory: `$HOME` when it is set, which is how Node's
|
|
5
|
+
* `os.homedir()` resolves it, otherwise the account's home. Bun's
|
|
6
|
+
* `os.homedir()` reads `$HOME` once at startup, so this reads it on every
|
|
7
|
+
* call, and a test preload that points `$HOME` at a temp directory moves
|
|
8
|
+
* every path derived from it.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveHomeDir(): string {
|
|
11
|
+
const home = process.env['HOME'];
|
|
12
|
+
|
|
13
|
+
return home !== undefined && home !== '' ? home : homedir();
|
|
14
|
+
}
|