local-commander-agent 0.3.45 → 0.3.46
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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/bin/posix.mjs +66 -66
- package/package.json +4 -4
- package/runtime/JobHost.exe +0 -0
- package/runtime/LocalCommanderAgent.exe +0 -0
- package/runtime/OwnerBridge.exe +0 -0
- package/runtime/agent.mjs +418 -236
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Change history
|
|
2
2
|
|
|
3
|
+
## 0.3.46 - 2026-10-22
|
|
4
|
+
|
|
5
|
+
- Simpler setup on macOS and Linux: the approval page opens in your browser by itself, and on a Mac access is one click in a window (Full Access, or Choose Folder). Linux asks one question in the terminal: press Enter for Full Access or type a folder.
|
|
6
|
+
- Fixed: on macOS, updates keep access to the agent's key in the Keychain.
|
|
7
|
+
- Includes everything in 0.3.45.
|
|
8
|
+
|
|
3
9
|
## 0.3.45 - 2026-10-22
|
|
4
10
|
|
|
5
11
|
- New: macOS 14 or later on Apple Silicon, and Linux x64 or arm64 with a systemd user session. Run the same `npx local-commander-agent@latest` in Terminal; npm downloads only the runtime for your computer. Setup pairs the computer, asks what may be used in the terminal, and runs the agent as a background service that starts when you sign in.
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Use **Windows 11 x64**, **macOS 14 or later on Apple Silicon**, or **Linux with
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
2. The installer opens a browser. Sign in to [Local Commander](https://localcmd.app), check the displayed pairing code, and approve this computer. Approve only a pairing you just started yourself.
|
|
22
|
-
3. Choose access in the local
|
|
22
|
+
3. Choose access in the local window (on Windows and macOS; Linux asks one question in the terminal):
|
|
23
23
|
- **Full access - all connected drives (default):** approve the available drive letters, file reads/writes, installed commands and localhost services at once. There is no folder picker or separate approval for Node.
|
|
24
24
|
- **Selected folders:** choose one folder in the folder picker. It starts read/write; more folders and write permission can be added later.
|
|
25
25
|
|
package/bin/posix.mjs
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
// macOS and Linux: the runtime ships in a per-platform package (an optional dependency, so npm installs only the
|
|
2
|
-
// matching one). Its lifecycle accepts only a private, owner-only artifact directory, so the files are copied from the
|
|
3
|
-
// npx cache into a fresh private directory and the lifecycle installs from there into its own versions directory.
|
|
4
|
-
import { constants } from "node:fs";
|
|
5
|
-
import fs from "node:fs/promises";
|
|
6
|
-
import os from "node:os";
|
|
7
|
-
import path from "node:path";
|
|
8
|
-
import { spawnSync } from "node:child_process";
|
|
9
|
-
import { createRequire } from "node:module";
|
|
10
|
-
|
|
11
|
-
const PACKAGES = { "darwin-arm64": "local-commander-agent-darwin-arm64", "linux-x64": "local-commander-agent-linux-x64", "linux-arm64": "local-commander-agent-linux-arm64" };
|
|
12
|
-
// npm command -> lifecycle command. The default (`npx local-commander-agent@latest`) is setup, as on Windows.
|
|
13
|
-
const COMMANDS = { bootstrap: "setup", install: "setup", setup: "setup", update: "update", pair: "pair", access: "access", "configure-access": "access",
|
|
14
|
-
start: "start", stop: "stop", status: "status", rollback: "rollback", uninstall: "uninstall" };
|
|
15
|
-
const EXECUTABLES = new Set(["node", "posix-host", "owner-store"]);
|
|
16
|
-
|
|
17
|
-
function fail(code) { const error = new Error(code); error.code = code; throw error; }
|
|
18
|
-
|
|
19
|
-
export function posixHelp() {
|
|
20
|
-
return [
|
|
21
|
-
"Local Commander",
|
|
22
|
-
"",
|
|
23
|
-
" npx local-commander-agent@latest set up this computer, pair it and choose access",
|
|
24
|
-
" npx local-commander-agent@latest update install this version, keeping pairing and access",
|
|
25
|
-
" npx local-commander-agent@latest status|start|stop|pair|access|rollback",
|
|
26
|
-
" npx local-commander-agent@latest uninstall [--purge-state]",
|
|
27
|
-
""
|
|
28
|
-
].join("\n");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function runPosix(argv, version) {
|
|
32
|
-
const name = PACKAGES[process.platform + "-" + process.arch];
|
|
33
|
-
if (!name) fail(process.platform === "darwin" ? "MACOS_APPLE_SILICON_REQUIRED" : process.platform === "linux" ? "LINUX_X64_OR_ARM64_REQUIRED" : "PLATFORM_UNSUPPORTED");
|
|
34
|
-
const command = argv[0] || "bootstrap", args = argv.slice(1);
|
|
35
|
-
if (command === "-h" || command === "--help" || command === "help") { process.stdout.write(posixHelp()); return; }
|
|
36
|
-
const lifecycle = COMMANDS[command];
|
|
37
|
-
if (!lifecycle) fail("ARGUMENT_INVALID");
|
|
38
|
-
if (lifecycle === "uninstall" ? args.length > 1 || (args.length === 1 && args[0] !== "--purge-state") : args.length) fail("ARGUMENT_INVALID");
|
|
39
|
-
if (typeof process.getuid === "function" && process.getuid() === 0) fail("POSIX_OWNER_REQUIRED");
|
|
40
|
-
|
|
41
|
-
let packageJson;
|
|
42
|
-
try { packageJson = createRequire(import.meta.url).resolve(name + "/package.json"); } catch { fail("PLATFORM_PACKAGE_MISSING"); }
|
|
43
|
-
const meta = JSON.parse(await fs.readFile(packageJson, "utf8"));
|
|
44
|
-
if (meta.name !== name || meta.version !== version) fail("PLATFORM_PACKAGE_MISMATCH");
|
|
45
|
-
const source = path.join(path.dirname(packageJson), "runtime");
|
|
46
|
-
const manifest = JSON.parse(await fs.readFile(path.join(source, "manifest.json"), "utf8"));
|
|
47
|
-
const files = Object.keys(manifest?.files ?? {});
|
|
48
|
-
if (manifest?.platform !== process.platform || manifest?.arch !== process.arch || !files.length || files.some(file => !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(file))) fail("PLATFORM_PACKAGE_INVALID");
|
|
49
|
-
|
|
50
|
-
// Canonical parent: on macOS os.tmpdir() is under /var, a symlink to /private/var, and the lifecycle rejects aliases.
|
|
51
|
-
const stage = await fs.mkdtemp(path.join(await fs.realpath(os.tmpdir()), "local-commander-"));
|
|
52
|
-
try {
|
|
53
|
-
await fs.chmod(stage, 0o700);
|
|
54
|
-
for (const file of [...files, "manifest.json"]) {
|
|
55
|
-
const target = path.join(stage, file);
|
|
56
|
-
await fs.copyFile(path.join(source, file), target, constants.COPYFILE_EXCL);
|
|
57
|
-
await fs.chmod(target, EXECUTABLES.has(file) ? 0o700 : 0o600);
|
|
58
|
-
}
|
|
59
|
-
// The lifecycle verifies every file against the manifest, then copies them into its own versions directory.
|
|
60
|
-
const result = spawnSync(path.join(stage, "node"), [path.join(stage, "lifecycle.mjs"), lifecycle, ...args], { stdio: "inherit" });
|
|
61
|
-
if (result.error) throw result.error;
|
|
62
|
-
process.exitCode = result.status ?? 1;
|
|
63
|
-
} finally {
|
|
64
|
-
await fs.rm(stage, { recursive: true, force: true });
|
|
65
|
-
}
|
|
66
|
-
}
|
|
1
|
+
// macOS and Linux: the runtime ships in a per-platform package (an optional dependency, so npm installs only the
|
|
2
|
+
// matching one). Its lifecycle accepts only a private, owner-only artifact directory, so the files are copied from the
|
|
3
|
+
// npx cache into a fresh private directory and the lifecycle installs from there into its own versions directory.
|
|
4
|
+
import { constants } from "node:fs";
|
|
5
|
+
import fs from "node:fs/promises";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
|
|
11
|
+
const PACKAGES = { "darwin-arm64": "local-commander-agent-darwin-arm64", "linux-x64": "local-commander-agent-linux-x64", "linux-arm64": "local-commander-agent-linux-arm64" };
|
|
12
|
+
// npm command -> lifecycle command. The default (`npx local-commander-agent@latest`) is setup, as on Windows.
|
|
13
|
+
const COMMANDS = { bootstrap: "setup", install: "setup", setup: "setup", update: "update", pair: "pair", access: "access", "configure-access": "access",
|
|
14
|
+
start: "start", stop: "stop", status: "status", rollback: "rollback", uninstall: "uninstall" };
|
|
15
|
+
const EXECUTABLES = new Set(["node", "posix-host", "owner-store"]);
|
|
16
|
+
|
|
17
|
+
function fail(code) { const error = new Error(code); error.code = code; throw error; }
|
|
18
|
+
|
|
19
|
+
export function posixHelp() {
|
|
20
|
+
return [
|
|
21
|
+
"Local Commander",
|
|
22
|
+
"",
|
|
23
|
+
" npx local-commander-agent@latest set up this computer, pair it and choose access",
|
|
24
|
+
" npx local-commander-agent@latest update install this version, keeping pairing and access",
|
|
25
|
+
" npx local-commander-agent@latest status|start|stop|pair|access|rollback",
|
|
26
|
+
" npx local-commander-agent@latest uninstall [--purge-state]",
|
|
27
|
+
""
|
|
28
|
+
].join("\n");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function runPosix(argv, version) {
|
|
32
|
+
const name = PACKAGES[process.platform + "-" + process.arch];
|
|
33
|
+
if (!name) fail(process.platform === "darwin" ? "MACOS_APPLE_SILICON_REQUIRED" : process.platform === "linux" ? "LINUX_X64_OR_ARM64_REQUIRED" : "PLATFORM_UNSUPPORTED");
|
|
34
|
+
const command = argv[0] || "bootstrap", args = argv.slice(1);
|
|
35
|
+
if (command === "-h" || command === "--help" || command === "help") { process.stdout.write(posixHelp()); return; }
|
|
36
|
+
const lifecycle = COMMANDS[command];
|
|
37
|
+
if (!lifecycle) fail("ARGUMENT_INVALID");
|
|
38
|
+
if (lifecycle === "uninstall" ? args.length > 1 || (args.length === 1 && args[0] !== "--purge-state") : args.length) fail("ARGUMENT_INVALID");
|
|
39
|
+
if (typeof process.getuid === "function" && process.getuid() === 0) fail("POSIX_OWNER_REQUIRED");
|
|
40
|
+
|
|
41
|
+
let packageJson;
|
|
42
|
+
try { packageJson = createRequire(import.meta.url).resolve(name + "/package.json"); } catch { fail("PLATFORM_PACKAGE_MISSING"); }
|
|
43
|
+
const meta = JSON.parse(await fs.readFile(packageJson, "utf8"));
|
|
44
|
+
if (meta.name !== name || meta.version !== version) fail("PLATFORM_PACKAGE_MISMATCH");
|
|
45
|
+
const source = path.join(path.dirname(packageJson), "runtime");
|
|
46
|
+
const manifest = JSON.parse(await fs.readFile(path.join(source, "manifest.json"), "utf8"));
|
|
47
|
+
const files = Object.keys(manifest?.files ?? {});
|
|
48
|
+
if (manifest?.platform !== process.platform || manifest?.arch !== process.arch || !files.length || files.some(file => !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(file))) fail("PLATFORM_PACKAGE_INVALID");
|
|
49
|
+
|
|
50
|
+
// Canonical parent: on macOS os.tmpdir() is under /var, a symlink to /private/var, and the lifecycle rejects aliases.
|
|
51
|
+
const stage = await fs.mkdtemp(path.join(await fs.realpath(os.tmpdir()), "local-commander-"));
|
|
52
|
+
try {
|
|
53
|
+
await fs.chmod(stage, 0o700);
|
|
54
|
+
for (const file of [...files, "manifest.json"]) {
|
|
55
|
+
const target = path.join(stage, file);
|
|
56
|
+
await fs.copyFile(path.join(source, file), target, constants.COPYFILE_EXCL);
|
|
57
|
+
await fs.chmod(target, EXECUTABLES.has(file) ? 0o700 : 0o600);
|
|
58
|
+
}
|
|
59
|
+
// The lifecycle verifies every file against the manifest, then copies them into its own versions directory.
|
|
60
|
+
const result = spawnSync(path.join(stage, "node"), [path.join(stage, "lifecycle.mjs"), lifecycle, ...args], { stdio: "inherit" });
|
|
61
|
+
if (result.error) throw result.error;
|
|
62
|
+
process.exitCode = result.status ?? 1;
|
|
63
|
+
} finally {
|
|
64
|
+
await fs.rm(stage, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-commander-agent",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.46",
|
|
4
4
|
"description": "Computer companion for Local Commander: connect AI clients to local files, approved commands and localhost. Requires https://localcmd.app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"arm64"
|
|
17
17
|
],
|
|
18
18
|
"optionalDependencies": {
|
|
19
|
-
"local-commander-agent-darwin-arm64": "0.3.
|
|
20
|
-
"local-commander-agent-linux-arm64": "0.3.
|
|
21
|
-
"local-commander-agent-linux-x64": "0.3.
|
|
19
|
+
"local-commander-agent-darwin-arm64": "0.3.46",
|
|
20
|
+
"local-commander-agent-linux-arm64": "0.3.46",
|
|
21
|
+
"local-commander-agent-linux-x64": "0.3.46"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
24
|
"node": ">=20.0.0"
|
package/runtime/JobHost.exe
CHANGED
|
Binary file
|
|
Binary file
|
package/runtime/OwnerBridge.exe
CHANGED
|
Binary file
|