agentradar-cli 0.3.16 → 0.3.17

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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { readFileSync } from "node:fs";
2
+ import { readFileSync, statSync } from "node:fs";
3
3
  import { createRequire } from "node:module";
4
4
  import { homedir } from "node:os";
5
5
  import { resolve } from "node:path";
@@ -23,9 +23,13 @@ export const runArgs = (raw) => raw[0] !== "run" ? raw
23
23
  : ["call", ...raw.slice(1)];
24
24
  // The join link carries the secret that claims the agent's key, and ps shows argv to every user on the machine:
25
25
  // `--link-file <path>` or `-` (stdin) keeps it off. `again` is how the CLI's own "run it again" lines name it.
26
- export const joinLink = (urls, linkFile, stdin = () => readFileSync(0, "utf8")) => linkFile ? { link: readFileSync(linkFile, "utf8").trim(), again: `--link-file ${resolve(linkFile)}` }
27
- : urls[0] === "-" ? { link: stdin().trim(), again: "-" }
28
- : { link: urls[0], again: undefined };
26
+ export const joinLink = (urls, linkFile, stdin = () => readFileSync(0, "utf8"), warn = console.error) => {
27
+ if (linkFile && statSync(linkFile).mode & 0o077)
28
+ warn(`Warning: ${linkFile} is readable by other users on this machine; chmod 600 it.`);
29
+ return linkFile ? { link: readFileSync(linkFile, "utf8").trim(), again: `--link-file ${resolve(linkFile)}` }
30
+ : urls[0] === "-" ? { link: stdin().trim(), again: "-" }
31
+ : { link: urls[0], again: undefined };
32
+ };
29
33
  const USAGE = [
30
34
  "Usage: agentradar <noun> [<sub-noun>] <verb> [--<flag> <value> | --<flag>-file <path> ...] [--dry-run] [--json] [--runner <id>]",
31
35
  " Every agent command comes from the server. agentradar --help lists the groups (as $AR_CLI_RUNNER_ID),",
@@ -38,7 +42,7 @@ const USAGE = [
38
42
  " Exit codes: 0 done; 1 refused or unreachable (the reason is on stderr); 2 the command was wrong.",
39
43
  "Local commands:",
40
44
  " agentradar join <join-link> | --link-file <path> | - (link on stdin) [--name <n>] [--model <m>] [--runtime claude|codex|other] [--trust] [--attach-tmux <pane> | --attach-current] [--session <id>] [--no-service | --service]",
41
- " agentradar join cancel <join-link|request-id>",
45
+ " agentradar join cancel <request-id> | --link-file <path> | - (link on stdin) | <join-link>",
42
46
  " agentradar setup [--trust] [--harness claude|codex]",
43
47
  " agentradar leave <runner-id>",
44
48
  " agentradar channel <runner-id>",
@@ -126,12 +130,13 @@ async function main() {
126
130
  return;
127
131
  }
128
132
  if (args[0] === "join" && args[1] === "cancel") {
129
- if (args.length !== 3 || args[2].startsWith("-")) {
130
- console.error("Usage: agentradar join cancel <join-link|request-id>");
133
+ const fromFile = args.length === 4 && args[2] === "--link-file";
134
+ if (!fromFile && (args.length !== 3 || (args[2].startsWith("-") && args[2] !== "-"))) {
135
+ console.error("Usage: agentradar join cancel <request-id> | --link-file <path> | - (link on stdin) | <join-link>");
131
136
  process.exitCode = 1;
132
137
  return;
133
138
  }
134
- process.exitCode = await cancelJoin(args[2]);
139
+ process.exitCode = await cancelJoin(fromFile || args[2] === "-" ? joinLink([args[2]], fromFile ? args[3] : undefined).link : args[2]);
135
140
  return;
136
141
  }
137
142
  if (args[0] === "join") {
package/dist/setup.js CHANGED
@@ -1138,7 +1138,8 @@ export async function cancelJoin(target, deps = {}) {
1138
1138
  }
1139
1139
  }
1140
1140
  if (!state || !statePath) {
1141
- log(`No join request from this machine for ${target}.`);
1141
+ // A link carries the claim token; never echo it.
1142
+ log(`No join request from this machine for ${/^https?:\/\//.test(target) ? "that join link" : target}.`);
1142
1143
  return 1;
1143
1144
  }
1144
1145
  if (state.agentId) {
@@ -1148,7 +1149,7 @@ export async function cancelJoin(target, deps = {}) {
1148
1149
  // The secret goes only back to the AgentRadar host that issued it.
1149
1150
  const origin = token ? new URL(target).origin : state.approvalUrl ? new URL(state.approvalUrl).origin : "";
1150
1151
  if (!origin || !trustedMcpEndpoint(origin)) {
1151
- log("Pass the join link instead of the request id: agentradar join cancel <join-link>");
1152
+ log("Pass the join link instead of the request id: agentradar join cancel --link-file <path>");
1152
1153
  return 1;
1153
1154
  }
1154
1155
  const response = await postJson(fetchImpl, new URL(`/api/join-requests/${encodeURIComponent(state.requestId)}/cancel`, origin), { claimSecret: state.claimSecret });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentradar-cli",
3
- "version": "0.3.16",
3
+ "version": "0.3.17",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },