speculos-toolkit 1.1.1 → 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/README.md CHANGED
@@ -17,7 +17,7 @@ host never runs your build.
17
17
 
18
18
  > **Frontend hosting is free; every Speculos account includes one backend app free.** Sign in
19
19
  > once with `speculos-toolkit login` and a detected backend deploys too (sign up at
20
- > https://deploy.speculos.ai). Without an account the backend is skipped and the frontend still
20
+ > https://unified.speculos.ai). Without an account the backend is skipped and the frontend still
21
21
  > ships free.
22
22
 
23
23
  ## Who can see your app
@@ -26,7 +26,7 @@ host never runs your build.
26
26
  |---|---|
27
27
  | **No account** | the app is **public** — anyone with the link. A private app checks who the visitor is when they open it, and there is no account to check against yet. |
28
28
  | **Signed in** | a new app is **private** by default. `--public` shares it, `--org` opens it to your org. |
29
- | **Already deployed anonymously?** | `speculos-toolkit login` links this machine and your existing apps come with it — then redeploy with `--private`, or flip it on the [dashboard](https://deploy.speculos.ai/dashboard). |
29
+ | **Already deployed anonymously?** | `speculos-toolkit login` links this machine and your existing apps come with it — then redeploy with `--private`, or flip it on the [dashboard](https://unified.speculos.ai/?tab=deploys). |
30
30
 
31
31
  `--private` or `--org` without an account fails the deploy (`LOGIN_REQUIRED`)
32
32
  rather than publishing something public that you asked to keep private.
@@ -79,6 +79,6 @@ speculos-toolkit teardown --slug <s> remove a deployment
79
79
  --env KEY=VAL --env-file <file> --api <url> --timeout <sec> --json
80
80
  ```
81
81
 
82
- Docs: https://deploy.speculos.ai · Source: https://github.com/speculosai/agent_deploy_infra
82
+ Docs: https://unified.speculos.ai · Source: https://github.com/speculosai/unified_platform
83
83
 
84
84
  MIT
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "speculos-toolkit",
3
- "version": "1.1.1",
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.",
3
+ "version": "1.2.0",
4
+ "description": "The Speculos toolkit for coding agents \u2014 deploy any frontend/backend to a live URL and build against your linked data connectors (BigQuery, Postgres, Snowflake, Salesforce, \u2026). Built for Claude Code, Codex, Cursor, and friends.",
5
5
  "bin": {
6
6
  "speculos-toolkit": "bin/speculos-toolkit.js"
7
7
  },
@@ -28,9 +28,10 @@
28
28
  "speculos"
29
29
  ],
30
30
  "license": "MIT",
31
- "homepage": "https://deploy.speculos.ai",
31
+ "homepage": "https://unified.speculos.ai",
32
32
  "repository": {
33
33
  "type": "git",
34
- "url": "git+https://github.com/speculosai/agent_deploy_infra.git"
34
+ "url": "git+https://github.com/speculosai/unified_platform.git",
35
+ "directory": "deploy_plane/packages/cli"
35
36
  }
36
37
  }
package/skill/SKILL.md CHANGED
@@ -29,7 +29,7 @@ with `--frontend`/`--backend` in step 4 (or force a build dir to serve as-is wit
29
29
  ### If the project has a backend, ASK the user how to deploy (before you build)
30
30
 
31
31
  Frontends are **free** and need no account; **every Speculos account includes one backend
32
- app free** (sign in at https://deploy.speculos.ai). So when `detect` finds a backend, DON'T silently
32
+ app free** (sign in at https://unified.speculos.ai). So when `detect` finds a backend, DON'T silently
33
33
  skip it — ask the user with your question UI (e.g. AskUserQuestion). Tailor the “what won't
34
34
  work” line to THIS app (a counter button, a form, login, saved data…). For example:
35
35
 
@@ -151,7 +151,7 @@ The last stdout line is `{ ok, brokerUrl, connectors: [{ alias, name, kind, acco
151
151
  drop the flag (the app ships public) and lock it down after linking.
152
152
  - `ok:true` with empty `connectors` → nothing linked (or nothing granted to this user).
153
153
  If the app clearly wants external data, tell the user to link a source (or ask their org
154
- admin for access) at **https://deploy.speculos.ai/dashboard**, then **re-run the list** —
154
+ admin for access) at **https://unified.speculos.ai/?tab=deploys**, then **re-run the list** —
155
155
  access is resolved server-side on every call, so a source linked or granted seconds ago
156
156
  shows up immediately with no re-login and no session restart. Never block a deploy on this.
157
157
  - A `403 NO_ACCESS` on execute means an org admin hasn't granted that source to this user —
@@ -306,7 +306,7 @@ Builds run locally (this machine already has the toolchain); only static output
306
306
  `speculos-toolkit login`, then deploy again.
307
307
  - Already deployed anonymously and now want it private? `speculos-toolkit login`
308
308
  links this machine and its existing apps come with it — then redeploy with
309
- `--private`, or flip it at https://deploy.speculos.ai/dashboard.
309
+ `--private`, or flip it at https://unified.speculos.ai/?tab=deploys.
310
310
  - A redeploy never changes the visibility of an app that is already live.
311
311
 
312
312
  The **last line of stdout is one JSON object**:
@@ -320,16 +320,16 @@ On `ok:false`, read `error`/`logTail`, fix the cause **once**, and re-run. Do no
320
320
  > limit (one is included; more come with Team plans). In both cases the deploy still **ships
321
321
  > the frontend** and returns `ok:true` with a `backendNote` — so the user already has a live
322
322
  > URL. To ship the backend: for `BACKEND_DISABLED`, sign in; for `TOO_MANY`, take an app
323
- > offline at https://deploy.speculos.ai/dashboard, redeploy an existing backend app, or talk
323
+ > offline at https://unified.speculos.ai/?tab=deploys, redeploy an existing backend app, or talk
324
324
  > to our team at https://calendar.app.google/VMGTvK3FmyDMAsix6 about more capacity. Always write the URL as
325
- > **https://deploy.speculos.ai** — never `speculos.ai`. Don't retry the backend; once signed
325
+ > **https://unified.speculos.ai** — never `speculos.ai`. Don't retry the backend; once signed
326
326
  > in / under the limit, re-running `deploy` ships it. Redeploying an app that already has a
327
327
  > backend never counts against the limit (it reuses its sandbox).
328
328
 
329
329
  ## 5. Report + verify
330
330
 
331
331
  - Give the user `urls.frontend` (and `urls.backend` if deployed). They can manage their
332
- published apps and take them offline anytime at https://deploy.speculos.ai/dashboard. The public URL is
332
+ published apps and take them offline anytime at https://unified.speculos.ai/?tab=deploys. The public URL is
333
333
  `user-deployed.speculos.ai/<username>/<app-slug>/`, and BOTH segments are renameable there:
334
334
  "Edit link" changes an app's slug (the second segment), and the account's "your link name"
335
335
  changes the first segment (default a random id) for every app on that device. Accounts on
@@ -349,10 +349,10 @@ On `ok:false`, read `error`/`logTail`, fix the cause **once**, and re-run. Do no
349
349
  ## Notes
350
350
 
351
351
  - Until the user signs in, the backend is skipped (frontend-only). Run `speculos-toolkit login`,
352
- or point users to https://deploy.speculos.ai.
352
+ or point users to https://unified.speculos.ai.
353
353
  - Permission is granted once at skill install, so the deploy command runs without prompting.
354
354
  - To remove a deployment: `npx -y speculos-toolkit@latest teardown --slug <slug>` (or use the
355
- dashboard at https://deploy.speculos.ai/dashboard).
355
+ dashboard at https://unified.speculos.ai/?tab=deploys).
356
356
  - **Already have this skill from before connectors existed?** Re-run
357
357
  `npx -y speculos-toolkit@latest install-skill` to refresh it (safe to run repeatedly — it
358
358
  overwrites the skill file and re-grants the command). The CLI itself is always current
package/src/client.js CHANGED
@@ -1,8 +1,10 @@
1
- // HTTP client to the Speculos orchestrator (management API). Holds no platform
2
- // secrets. The orchestrator runs self-hosted behind the Cloudflare forwarding
3
- // deploy-orch-38hd4.speculos.ai; it drives Daytona backends and pushes frontends
4
- // to the EC2 host that serves them at user-deployed.speculos.ai.
5
- const DEFAULT_API = process.env.SPECULOS_API || "https://deploy-orch-38hd4.speculos.ai";
1
+ // HTTP client to the Speculos platform gateway (management API). Holds no
2
+ // platform secrets. The gateway proxies these calls to the deploy orchestrator
3
+ // on the same box and files every deploy in the console's shared history, so a
4
+ // CLI deploy and a console publish sit in one list under one identity. The
5
+ // orchestrator's own hostname (deploy-orch-38hd4.speculos.ai) still answers and
6
+ // can be selected with --api; deployed apps keep calling the broker there.
7
+ const DEFAULT_API = process.env.SPECULOS_API || "https://unified-api.speculos.ai/toolkit";
6
8
 
7
9
  function base(opts) { return (opts.api || DEFAULT_API).replace(/\/$/, ""); }
8
10
 
package/src/index.js CHANGED
@@ -98,11 +98,11 @@ WHO CAN SEE IT
98
98
  Already
99
99
  deployed? run 'speculos-toolkit login' to link this machine — your existing
100
100
  apps come with it — then deploy again with --private, or flip it
101
- on https://deploy.speculos.ai/dashboard.
101
+ on https://unified.speculos.ai/?tab=deploys.
102
102
 
103
103
  A redeploy never changes the visibility of an app that is already live.
104
104
  Every Speculos account includes one backend app free (an isolated sandbox per app) —
105
- sign up at https://deploy.speculos.ai and run 'speculos-toolkit login'.
105
+ sign up at https://unified.speculos.ai and run 'speculos-toolkit login'.
106
106
  Without an account a detected backend is skipped (frontend still ships free).
107
107
 
108
108
  OPTIONS
@@ -129,7 +129,7 @@ OPTIONS
129
129
  --args <json> connectors exec: tool arguments as inline JSON
130
130
  --args-file <f> connectors exec: tool arguments from a JSON file (preferred
131
131
  in agents — inline JSON with $ ( ) etc. may need approval)
132
- --api <url> orchestrator base url (default https://deploy-orch-38hd4.speculos.ai)
132
+ --api <url> platform API base (default https://unified-api.speculos.ai/toolkit)
133
133
  --timeout <sec> max seconds to wait for the backend (default 600)
134
134
  --json machine-readable only (auto-on when non-TTY/CI)
135
135
 
@@ -144,6 +144,11 @@ VITE_API_URL / NEXT_PUBLIC_API_URL / API_URL (build) or window.SPECULOS_API_URL.
144
144
 
145
145
  async function cmdDetect(root, opts) {
146
146
  const d = detect(root, opts);
147
+ // `detect` derives a slug from the directory name; a project that has already
148
+ // been deployed has its real slug in .speculos.json, and deploy honours it.
149
+ // Reporting the derived one made `detect` disagree with what `deploy` would do.
150
+ const saved = creds.load(root);
151
+ if (!opts.slug && saved && saved.slug) d.slug = saved.slug;
147
152
  if (!opts.json) {
148
153
  log(opts, `slug: ${d.slug}`);
149
154
  log(opts, `frontend: ${d.frontend ? `${path.relative(root, d.frontend.dir) || "."} (${d.frontend.kind}${d.frontend.framework ? "/" + d.frontend.framework : ""})` : "none"}`);
@@ -184,7 +189,7 @@ async function cmdDeploy(root, opts) {
184
189
  d.backend = null;
185
190
  }
186
191
  if (!d.frontend && !d.backend) {
187
- if (hadBackend) { emit({ ok: false, error: `nothing to deploy: Speculos hosts frontends free, but this project is backend-only — sign in to deploy the backend (every Speculos account includes one free backend app). Run \`speculos-toolkit login\` (https://deploy.speculos.ai), or add a frontend.`, code: "BETA_BACKEND_ONLY" }); return 2; }
192
+ if (hadBackend) { emit({ ok: false, error: `nothing to deploy: Speculos hosts frontends free, but this project is backend-only — sign in to deploy the backend (every Speculos account includes one free backend app). Run \`speculos-toolkit login\` (https://unified.speculos.ai), or add a frontend.`, code: "BETA_BACKEND_ONLY" }); return 2; }
188
193
  emit({ ok: false, error: `could not detect a frontend in ${root}. Pass --frontend <dir>.`, code: "DETECT" });
189
194
  return 2;
190
195
  }
@@ -305,6 +310,7 @@ async function cmdDeploy(root, opts) {
305
310
  if (alloc && alloc.visibilityNote) log(opts, ` note: ${alloc.visibilityNote}`);
306
311
  const out = { ok: true, slug: d.slug, userId, urls };
307
312
  if (visibility) out.visibility = visibility;
313
+ if (alloc && alloc.visibilityNote) out.visibilityNote = alloc.visibilityNote;
308
314
  if (backendNote) out.backendNote = backendNote;
309
315
  emit({ ...out });
310
316
  return 0;
@@ -343,7 +349,7 @@ async function cmdLogin(opts) {
343
349
  // to a different account, incl. moving a personal-linked device onto an org).
344
350
  const existing = creds.loadIdentity();
345
351
  if (existing && existing.accountToken && !opts.relink && !opts.pasteToken) {
346
- log(opts, `✓ this device is already linked to your Speculos account. Pass --relink to link a different account. Manage deployments at https://deploy.speculos.ai/dashboard.`);
352
+ log(opts, `✓ this device is already linked to your Speculos account. Pass --relink to link a different account. Manage deployments at https://unified.speculos.ai/?tab=deploys.`);
347
353
  emit({ ok: true, alreadyLinked: true });
348
354
  return 0;
349
355
  }
@@ -369,7 +375,7 @@ async function cmdLogin(opts) {
369
375
  } catch { /* links on next deploy via the token */ }
370
376
  }
371
377
  if (reparented) process.stderr.write(`\n⚠ This device's deployments moved from ${previousEmail || "another account"} to ${who.email || "this account"}.\n`);
372
- log(opts, `✓ this device is linked${who.email ? ` to ${who.email}` : ""}${who.org ? ` (org: ${who.org})` : ""} — manage at https://deploy.speculos.ai/dashboard.`);
378
+ log(opts, `✓ this device is linked${who.email ? ` to ${who.email}` : ""}${who.org ? ` (org: ${who.org})` : ""} — manage at https://unified.speculos.ai/?tab=deploys.`);
373
379
  emit({ ok: true, linked: true, account: who.email || null, org: who.org || null, reparented, previousAccount: previousEmail });
374
380
  return 0;
375
381
  }
@@ -383,7 +389,7 @@ async function cmdLogin(opts) {
383
389
  // And on stderr (even in --json) for a human watching.
384
390
  process.stderr.write(`\nLink this machine to your Speculos account to enable backend hosting:\n`);
385
391
  process.stderr.write(`\n 1. Open: ${start.url}\n`);
386
- process.stderr.write(` (or go to https://deploy.speculos.ai/link and enter code ${start.code})\n`);
392
+ process.stderr.write(` (or go to https://unified.speculos.ai/link and enter code ${start.code})\n`);
387
393
  process.stderr.write(` 2. Sign in / sign up, then click Approve.\n\n`);
388
394
  process.stderr.write(`Waiting for approval…\n`);
389
395
 
@@ -411,7 +417,7 @@ async function cmdLogin(opts) {
411
417
  if (reparented) {
412
418
  process.stderr.write(`\n⚠ This device's deployments moved from ${previousEmail || "another account"} to ${approvedEmail || "this account"}. They now appear only in the new account's dashboard.\n`);
413
419
  }
414
- log(opts, `✓ this device is linked${approvedEmail ? ` to ${approvedEmail}` : ""} — manage your deployments at https://deploy.speculos.ai/dashboard.`);
420
+ log(opts, `✓ this device is linked${approvedEmail ? ` to ${approvedEmail}` : ""} — manage your deployments at https://unified.speculos.ai/?tab=deploys.`);
415
421
  emit({ ok: true, linked, account: approvedEmail, reparented, previousAccount: previousEmail });
416
422
  return 0;
417
423
  }
@@ -451,7 +457,7 @@ async function cmdConnectors(opts) {
451
457
  const identity = creds.loadIdentity();
452
458
  const token = identity && identity.accountToken;
453
459
  if (!token) {
454
- emit({ ok: false, code: "NO_TOKEN", error: "not signed in — run `npx -y speculos-toolkit@latest login`, then link data sources at https://deploy.speculos.ai/dashboard" });
460
+ emit({ ok: false, code: "NO_TOKEN", error: "not signed in — run `npx -y speculos-toolkit@latest login`, then link data sources at https://unified.speculos.ai/?tab=deploys" });
455
461
  return 1;
456
462
  }
457
463
  const sub = opts._[1] || "list";
@@ -462,8 +468,14 @@ async function cmdConnectors(opts) {
462
468
  catch (e) { emit({ ok: false, error: e.message, code: e.code || "CONNECTORS" }); return 1; }
463
469
  const conns = r.connectors || [];
464
470
  if (!opts.json) {
465
- if (!conns.length) log(opts, "no data sources linked — link one at https://deploy.speculos.ai/dashboard");
466
- for (const c of conns) log(opts, ` ${c.alias} (${c.name}${c.accountIdentifier ? " · " + c.accountIdentifier : ""}) — ${(c.tools || []).length} tools`);
471
+ if (!conns.length) log(opts, "no data sources linked — link one at https://unified.speculos.ai/?tab=deploys");
472
+ for (const c of conns) {
473
+ // Say which product a source came from: the deploy plane and the
474
+ // Cloud console hold separate connections, often to the same SaaS,
475
+ // and running a tool against the wrong one is silent and wrong.
476
+ const scope = c.orgWide ? " · org" : "";
477
+ log(opts, ` ${c.alias} (${c.name}${c.accountIdentifier ? " · " + c.accountIdentifier : ""}${scope}) — ${(c.tools || []).length} tools`);
478
+ }
467
479
  }
468
480
  emit({ ok: true, brokerUrl: client.base(opts) + "/api/connectors", connectors: conns });
469
481
  return 0;