@retasc/cli 1.1.2 → 1.2.0

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/api.js CHANGED
@@ -14,6 +14,10 @@ const fns = {
14
14
  mintKey: makeFunctionReference("manage:mintKey"),
15
15
  rotateKey: makeFunctionReference("manage:rotateKey"),
16
16
  revokeKey: makeFunctionReference("manage:revokeKey"),
17
+ createInvite: makeFunctionReference("manage:createInvite"),
18
+ acceptInvite: makeFunctionReference("manage:acceptInvite"),
19
+ listInvites: makeFunctionReference("manage:listInvites"),
20
+ revokeInvite: makeFunctionReference("manage:revokeInvite"),
17
21
  };
18
22
  function client() {
19
23
  const cfg = loadConfig();
@@ -32,4 +36,8 @@ export const api = {
32
36
  mintKey: (args) => client().action(fns.mintKey, args),
33
37
  rotateKey: (args) => client().action(fns.rotateKey, args),
34
38
  revokeKey: (args) => client().mutation(fns.revokeKey, args),
39
+ createInvite: (args) => client().action(fns.createInvite, args),
40
+ acceptInvite: (args) => client().mutation(fns.acceptInvite, args),
41
+ listInvites: (args) => client().query(fns.listInvites, args),
42
+ revokeInvite: (args) => client().mutation(fns.revokeInvite, args),
35
43
  };
package/dist/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import { readFileSync } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ import { dirname, join } from "node:path";
3
6
  import { loadConfig, patchConfig, saveConfig, configPath, isLoggedIn } from "./config.js";
4
7
  import { installMcp, normalizeScope } from "./commands/mcp.js";
5
8
  import { installGate } from "./commands/gate.js";
@@ -11,11 +14,16 @@ import { tidyAction, doneAction } from "./commands/tidy.js";
11
14
  import { runProxy } from "./proxy.js";
12
15
  import { deviceLogin } from "./auth.js";
13
16
  import { api } from "./api.js";
17
+ // Single source of truth for the version: read package.json at runtime from the
18
+ // compiled file's location (dist/index.js -> ../package.json). A JSON import won't
19
+ // work here — tsconfig has rootDir "src", so importing ../package.json is outside
20
+ // rootDir and fails tsc.
21
+ const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"));
14
22
  const program = new Command();
15
23
  program
16
24
  .name("retasc")
17
25
  .description("Retasc — sign in, create projects, mint agent API keys, and wire your agent to the MCP server.")
18
- .version("1.1.1");
26
+ .version(pkg.version);
19
27
  function requireLogin() {
20
28
  if (!isLoggedIn()) {
21
29
  console.error("Not signed in. Run `retasc login` first.");
@@ -280,6 +288,76 @@ key
280
288
  fail(e);
281
289
  }
282
290
  });
291
+ // --- members / invites -----------------------------------------------------
292
+ // An owner invites a human to their org with a single-use, expiring code; the
293
+ // invitee redeems it with `retasc join <code>` (authed as themselves via GitHub —
294
+ // no email needed). RTSC-137.
295
+ const members = program.command("members").description("Invite people to an org and manage invites.");
296
+ members
297
+ .command("invite")
298
+ .description("Mint a single-use invite code for an org (owner only). Shown once.")
299
+ .requiredOption("--org-id <id>")
300
+ .option("--expires-days <n>", "Days until the code expires (1–30, default 7)", (v) => parseInt(v, 10))
301
+ .action(async (opts) => {
302
+ requireLogin();
303
+ try {
304
+ const res = (await api.createInvite({ orgId: opts.orgId, expiresInDays: opts.expiresDays }));
305
+ console.log(`✓ Invite code: ${res.code}`);
306
+ console.log(` Expires ${new Date(res.expiresAt).toISOString().slice(0, 10)}. Single-use — shown once.`);
307
+ console.log(` Share it; they run: retasc login && retasc join ${res.code}`);
308
+ }
309
+ catch (e) {
310
+ fail(e);
311
+ }
312
+ });
313
+ members
314
+ .command("list")
315
+ .description("List an org's invites and their status (owner only).")
316
+ .requiredOption("--org-id <id>")
317
+ .action(async (opts) => {
318
+ requireLogin();
319
+ try {
320
+ const res = await api.listInvites({ orgId: opts.orgId });
321
+ console.log(JSON.stringify(res, null, 2));
322
+ }
323
+ catch (e) {
324
+ fail(e);
325
+ }
326
+ });
327
+ members
328
+ .command("revoke")
329
+ .description("Revoke an unused invite (owner only).")
330
+ .requiredOption("--invite-id <id>")
331
+ .action(async (opts) => {
332
+ requireLogin();
333
+ try {
334
+ await api.revokeInvite({ inviteId: opts.inviteId });
335
+ console.log("✓ Revoked.");
336
+ }
337
+ catch (e) {
338
+ fail(e);
339
+ }
340
+ });
341
+ program
342
+ .command("join")
343
+ .description("Redeem an invite code to join an org (as the signed-in GitHub user).")
344
+ .argument("<code>", "The invite code you were given")
345
+ .action(async (code) => {
346
+ requireLogin();
347
+ try {
348
+ const res = (await api.acceptInvite({ code }));
349
+ const where = res.slug ? ` "${res.slug}"` : "";
350
+ if (res.alreadyMember) {
351
+ console.log(`• You're already a member of org${where} (${res.role}). Nothing to do.`);
352
+ }
353
+ else {
354
+ console.log(`✓ Joined org${where} as ${res.role}. It'll show up in \`retasc whoami\`.`);
355
+ }
356
+ }
357
+ catch (e) {
358
+ fail(e);
359
+ }
360
+ });
283
361
  // --- mcp wiring ------------------------------------------------------------
284
362
  const mcp = program.command("mcp").description("Wire the Retasc MCP server into your agent.");
285
363
  mcp
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retasc/cli",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "Retasc CLI — sign in with GitHub, create projects, mint agent API keys, and wire your agent to the Retasc MCP server in one command.",
5
5
  "type": "module",
6
6
  "bin": {