@hypersocial/decks-cli 0.1.3 → 0.1.5

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 CHANGED
@@ -61,7 +61,7 @@ share rm <token>
61
61
  share url <token>
62
62
 
63
63
  recipient archive|unarchive <name>
64
- skills install [--path <dir>] [--force]
64
+ skills install [--agent codex,claude-code] [--all-agents]
65
65
  activity [--deck <slug>] [--limit <n>] [--json]
66
66
  ```
67
67
 
@@ -76,3 +76,6 @@ Use dev only for local implementation/testing:
76
76
  decks --dev --convex https://your-dev.convex.cloud --broker https://decks.localhost whoami
77
77
  HSDECKS_PROD=0 HSDECKS_CONVEX_URL=https://your-dev.convex.cloud HSDECKS_BROKER_BASE=https://decks.localhost decks whoami
78
78
  ```
79
+
80
+ Legacy unauthenticated dev access is available with `--admin` or
81
+ `HSDECKS_ADMIN=1`. It is rejected for production.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypersocial/decks-cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Command-line client for Hypersocial Decks live analytics and share management.",
5
5
  "type": "module",
6
6
  "main": "./src/commands.mjs",
package/src/commands.mjs CHANGED
@@ -155,14 +155,15 @@ commands:
155
155
  deck list|stats|open
156
156
  share new|list|on|off|rm|url
157
157
  recipient archive|unarchive
158
- skill install [--path <dir>] [--force]
159
- skills install [--path <dir>] [--force]
158
+ skill install [--agent codex,claude-code] [--all-agents]
159
+ skills install [--agent codex,claude-code] [--all-agents]
160
160
  activity [--deck <slug>] [--limit <n>] [--json]
161
161
 
162
162
  global:
163
163
  --json
164
164
  --prod production target (default)
165
165
  --dev development target (requires Convex URL)
166
+ --admin legacy unauthenticated dev access
166
167
  --broker URL override auth broker URL
167
168
  `);
168
169
  }
@@ -195,8 +196,8 @@ export async function runCli(argv = process.argv.slice(2)) {
195
196
  "share url": () => shareUrl(rest, opts),
196
197
  "recipient archive": () => recipientArchive(rest, opts, true),
197
198
  "recipient unarchive": () => recipientArchive(rest, opts, false),
198
- "skill install": () => installHyperdecksSkill(opts),
199
- "skills install": () => installHyperdecksSkill(opts),
199
+ "skill install": () => installHyperdecksSkill(opts, rest),
200
+ "skills install": () => installHyperdecksSkill(opts, rest),
200
201
  activity: () => activity(pos.slice(1), opts),
201
202
  };
202
203
 
package/src/runtime.mjs CHANGED
@@ -1,14 +1,14 @@
1
- import { execFile } from "node:child_process";
1
+ import { execFile, spawnSync } from "node:child_process";
2
2
  import { createHash, randomBytes } from "node:crypto";
3
3
  import { createServer } from "node:http";
4
- import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
6
  import { dirname, join } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { ConvexHttpClient } from "convex/browser";
9
9
  import { makeFunctionReference } from "convex/server";
10
10
 
11
- export const VERSION = "0.1.3";
11
+ export const VERSION = "0.1.5";
12
12
 
13
13
  export const PROD = {
14
14
  name: "prod",
@@ -38,12 +38,12 @@ export const api = {
38
38
  },
39
39
  };
40
40
 
41
- const BOOL = new Set(["prod", "dev", "json", "require-email", "help", "version", "force"]);
41
+ const BOOL = new Set(["prod", "dev", "admin", "json", "require-email", "help", "version", "all-agents", "global", "project"]);
42
42
 
43
43
  export const CRED_DIR = join(homedir(), ".config", "hypersocial-decks");
44
44
  export const CRED_FILE = join(CRED_DIR, "credentials.json");
45
45
  const SRC_DIR = dirname(fileURLToPath(import.meta.url));
46
- const PACKAGED_SKILL_DIR = join(SRC_DIR, "..", "skills", "hyperdecks");
46
+ const PACKAGED_SKILLS_DIR = join(SRC_DIR, "..", "skills");
47
47
 
48
48
  export function parse(args) {
49
49
  const opts = {};
@@ -53,7 +53,10 @@ export function parse(args) {
53
53
  if (a.startsWith("--")) {
54
54
  const k = a.slice(2);
55
55
  if (BOOL.has(k)) opts[k] = true;
56
- else opts[k] = args[++i];
56
+ else {
57
+ const v = args[++i];
58
+ opts[k] = k === "agent" && opts[k] ? `${opts[k]},${v}` : v;
59
+ }
57
60
  } else {
58
61
  pos.push(a);
59
62
  }
@@ -79,11 +82,12 @@ export function target(opts = {}) {
79
82
  if (!convexUrl) {
80
83
  throw new Error("dev target needs --convex <url>, HSDECKS_CONVEX_URL, or CONVEX_URL");
81
84
  }
85
+ const brokerBase = normalizeBase(opts.broker || process.env.HSDECKS_BROKER_BASE || "http://localhost:3000");
82
86
  return {
83
87
  name: "dev",
84
88
  convexUrl,
85
- brokerBase: normalizeBase(opts.broker || process.env.HSDECKS_BROKER_BASE || "http://localhost:3000"),
86
- shareBase: normalizeBase(process.env.HSDECKS_SHARE_BASE || "https://decks.localhost"),
89
+ brokerBase,
90
+ shareBase: normalizeBase(process.env.HSDECKS_SHARE_BASE || brokerBase),
87
91
  };
88
92
  }
89
93
 
@@ -156,9 +160,17 @@ async function jwtFor(brokerBase, refreshToken) {
156
160
  export async function client(opts = {}) {
157
161
  const t = target(opts);
158
162
  const c = new ConvexHttpClient(t.convexUrl);
163
+ const admin = opts.admin || process.env.HSDECKS_ADMIN === "1";
164
+ if (admin) {
165
+ if (t.name === "prod") throw new Error("legacy --admin is dev-only; run `decks login` for prod");
166
+ return c;
167
+ }
159
168
  const refreshToken = resolveRefreshToken(t, opts);
160
169
  if (!refreshToken) {
161
- throw new Error(`not authenticated for ${t.name} - run \`decks login${t.name === "dev" ? " --dev" : ""}\``);
170
+ throw new Error(
171
+ `not authenticated for ${t.name} - run \`decks login${t.name === "dev" ? " --dev" : ""}\`` +
172
+ (t.name === "dev" ? " (or pass --admin for legacy unauthenticated dev access)" : ""),
173
+ );
162
174
  }
163
175
  c.setAuth(await jwtFor(t.brokerBase, refreshToken));
164
176
  return c;
@@ -170,29 +182,41 @@ export function openBrowser(url) {
170
182
  execFile(cmd, args, () => {});
171
183
  }
172
184
 
173
- export function defaultSkillRoot() {
174
- return process.env.CODEX_HOME ? join(process.env.CODEX_HOME, "skills") : join(homedir(), ".codex", "skills");
185
+ function splitAgents(value) {
186
+ return String(value || "").split(/[,\s]+/).filter(Boolean);
175
187
  }
176
188
 
177
- export function installHyperdecksSkill(opts = {}) {
178
- const root = opts.path || opts.dir || defaultSkillRoot();
179
- const dest = join(root, "hyperdecks");
180
- if (!existsSync(PACKAGED_SKILL_DIR)) {
181
- throw new Error(`packaged hyperdecks skill not found at ${PACKAGED_SKILL_DIR}`);
189
+ export function installHyperdecksSkill(opts = {}, extraArgs = []) {
190
+ const skillDir = join(PACKAGED_SKILLS_DIR, "hyperdecks");
191
+ if (!existsSync(skillDir)) {
192
+ throw new Error(`packaged hyperdecks skill not found at ${skillDir}`);
182
193
  }
183
- if (existsSync(dest)) {
184
- if (!opts.force) {
185
- console.log(`hyperdecks skill already installed at ${dest}`);
186
- console.log("Run `hyperdecks skills install --force` to refresh it.");
187
- return { installed: false, path: dest };
188
- }
189
- rmSync(dest, { recursive: true, force: true });
194
+ if (opts.path || opts.dir) {
195
+ throw new Error("skills install now uses `npx skills add`; use --agent instead of --path");
196
+ }
197
+ if (opts.project) {
198
+ throw new Error("project-local skill installs are not supported yet; use the default global install");
199
+ }
200
+ if (opts["all-agents"] && (opts.agent || extraArgs.length)) {
201
+ throw new Error("use either --all-agents or --agent, not both");
202
+ }
203
+ if (!opts.agent && extraArgs.length) {
204
+ throw new Error(`unexpected argument(s): ${extraArgs.join(" ")}; pass agent ids with --agent`);
205
+ }
206
+
207
+ const agents = opts["all-agents"]
208
+ ? ["*"]
209
+ : [...splitAgents(opts.agent || "codex,claude-code"), ...extraArgs.flatMap(splitAgents)];
210
+ const args = ["-y", "skills@latest", "add", PACKAGED_SKILLS_DIR, "-g"];
211
+ args.push("-a", ...agents, "-s", "hyperdecks", "--copy", "-y", "--full-depth");
212
+
213
+ const command = process.platform === "win32" ? "npx.cmd" : "npx";
214
+ const result = spawnSync(command, args, { stdio: "inherit" });
215
+ if (result.error) throw result.error;
216
+ if (result.status !== 0) {
217
+ throw new Error(`skills add failed with exit code ${result.status}`);
190
218
  }
191
- mkdirSync(root, { recursive: true });
192
- cpSync(PACKAGED_SKILL_DIR, dest, { recursive: true });
193
- console.log(`OK installed hyperdecks skill to ${dest}`);
194
- console.log("Restart Codex or start a new session if the skill list is already loaded.");
195
- return { installed: true, path: dest };
219
+ return { installed: true };
196
220
  }
197
221
 
198
222
  async function verifyAndStampEmail(t, opts) {