speculos-toolkit 1.0.0 → 1.1.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +21 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speculos-toolkit",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "The Speculos toolkit for coding agents — deploy any frontend/backend to a live URL and build against your linked data connectors (BigQuery, Postgres, Snowflake, Salesforce, …). Built for Claude Code, Codex, Cursor, and friends.",
5
5
  "bin": {
6
6
  "speculos-toolkit": "bin/speculos-toolkit.js"
package/src/index.js CHANGED
@@ -35,6 +35,11 @@ function parseArgs(argv) {
35
35
  else if (a === "--static" || a === "--no-build") opts.static = true;
36
36
  else if (a === "--relink" || a === "--force") opts.relink = true;
37
37
  else if (a === "--project") opts.project = true;
38
+ // Who can open the deployed app. A new app is private unless told
39
+ // otherwise; these also re-set an existing app on redeploy.
40
+ else if (a === "--private") opts.visibility = "private";
41
+ else if (a === "--org") opts.visibility = "org";
42
+ else if (a === "--public") opts.visibility = "public";
38
43
  else if (a === "--no-backend") opts.noBackend = true;
39
44
  else if (a === "--no-frontend") opts.noFrontend = true;
40
45
  else if (a === "--json") opts.json = true;
@@ -83,6 +88,8 @@ USAGE
83
88
  (read-only discovery, live queries)
84
89
 
85
90
  Frontends are hosted FREE at user-deployed.speculos.ai/<userId>/<slugUuid>.
91
+ A NEW app is PRIVATE — deploy with --public (or flip it on the dashboard) to
92
+ share it. A redeploy never changes the visibility of an app that is already live.
86
93
  Every Speculos account includes one backend app free (an isolated sandbox per app) —
87
94
  sign up at https://deploy.speculos.ai and run 'speculos-toolkit login'.
88
95
  Without an account a detected backend is skipped (frontend still ships free).
@@ -96,6 +103,9 @@ OPTIONS
96
103
  --build force the frontend through its build step (vs serve as static)
97
104
  --static serve the frontend dir as-is even if it has a build script
98
105
  --no-backend frontend-only: skip backend even if one is detected
106
+ --private only you can open the deployed app (DEFAULT for a new app)
107
+ --org anyone in your org can open it
108
+ --public anyone with the link can open it, no sign-in
99
109
  --no-frontend backend-only: skip frontend even if one is detected
100
110
  --output <dir> frontend build output dir (dist/build/out — auto-detected)
101
111
  --override <pw> admin override password to deploy a backend without an account
@@ -176,7 +186,7 @@ async function cmdDeploy(root, opts) {
176
186
  // ---- identity + slug allocation (mints a machine identity on first use) ----
177
187
  let alloc;
178
188
  try {
179
- alloc = await client.allocate({ userId: identity && identity.userId, userKey: identity && identity.userKey, slug: d.slug }, opts);
189
+ alloc = await client.allocate({ userId: identity && identity.userId, userKey: identity && identity.userKey, slug: d.slug, visibility: opts.visibility }, opts);
180
190
  } catch (e) { emit({ ok: false, error: e.message, code: e.code || "ALLOCATE" }); return 1; }
181
191
  if (alloc.userKey) { // freshly minted on the server
182
192
  identity = { userId: alloc.userId, userKey: alloc.userKey };
@@ -266,7 +276,17 @@ async function cmdDeploy(root, opts) {
266
276
  if (urls.frontend) log(opts, ` frontend: ${urls.frontend}`);
267
277
  if (urls.backend) log(opts, ` backend: ${urls.backend}`);
268
278
  if (backendNote) log(opts, ` note: ${backendNote}`);
279
+ // Say who can open it. A new app is private now, and a URL printed with no
280
+ // word about visibility is the kind of thing people paste into Slack and
281
+ // then wonder why nobody can see it - or worse, assume it is private when
282
+ // they chose --public.
283
+ const visibility = alloc && alloc.visibility;
284
+ if (visibility === "private") log(opts, ` visibility: private — only you. Share with --public, --org, or the dashboard.`);
285
+ else if (visibility === "org") log(opts, ` visibility: org — anyone in your org can open it.`);
286
+ else if (visibility === "public") log(opts, ` visibility: public — anyone with the link.`);
287
+ if (alloc && alloc.visibilityNote) log(opts, ` note: ${alloc.visibilityNote}`);
269
288
  const out = { ok: true, slug: d.slug, userId, urls };
289
+ if (visibility) out.visibility = visibility;
270
290
  if (backendNote) out.backendNote = backendNote;
271
291
  emit({ ...out });
272
292
  return 0;