@easybits.cloud/cli 0.19.1 → 0.20.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 (3) hide show
  1. package/README.md +11 -0
  2. package/dist/index.js +63 -36
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -131,6 +131,8 @@ easybits crons create "Heads-up" --at 23:00 --url https://my-app.com/api/notice
131
131
  easybits crons create "Heads-up" --in 2h --url https://my-app.com/api/notice --method POST # once; --until/--times end repeating ones
132
132
  easybits crons create "Review" --at 23:00 --run "python3 asc.py submit" --file scripts/asc.py \
133
133
  --secret-file ASC_P8:~/.appstoreconnect/private_keys/AuthKey_X.p8 # a command in a throwaway box; the .p8 only this cron reads
134
+ easybits crons create "Daily signups" --cron "0 9 * * *" --run "python3 count.py" --file count.py \
135
+ --machine my-app # runs with my-app's env and secrets (its DATABASE_URL), resolved each run
134
136
  easybits crons get "Review" # what it does, how it notifies you, next run (--json: all of it)
135
137
  easybits crons runs "Review" --logs --limit 5 # exit code + stdout/stderr
136
138
  easybits crons wait "Review" --timeout 2h # blocks until it runs; exits with its exit code
@@ -167,6 +169,7 @@ easybits db query leads "SELECT * FROM leads" --json
167
169
  easybits db rename leads prospects --dry-run # which agent prompts name it
168
170
  easybits db rm leads --dry-run # tables and rows that would be lost
169
171
  easybits db rm leads --yes
172
+ easybits db attach clave # the database your machine opens at /v1/db/clave/
170
173
 
171
174
  # Agents
172
175
  easybits agents ls
@@ -310,6 +313,14 @@ Host *.ghosty
310
313
 
311
314
  Full reference: https://www.easybits.cloud/docs#cli · https://www.easybits.cloud/en/docs/cli.md
312
315
 
316
+ ## Changes in 0.20.0
317
+
318
+ - `db attach <name> [--description <text>]`: adds to your account the database one of your machines
319
+ already uses (`DATABASE_URL=http://172.20.0.1:8090/v1/db/<name>/`). Nothing is created or copied;
320
+ from then on `db query|tables|ls` work on it. It does not count toward your plan's database limit,
321
+ and `db rm` only removes it from your list: the machine keeps its data. New API:
322
+ `POST /api/v2/databases { name, attach: true }`.
323
+
313
324
  ## Changes in 0.17.1
314
325
 
315
326
  - `easybits crons ls|runs|run|pause|resume`: EasyBits' scheduled jobs, the same as the
package/dist/index.js CHANGED
@@ -3797,6 +3797,22 @@ var db = {
3797
3797
  emit(ctx, d, () => console.log(t(`Created ${d.name} (${d.id})`, `Creada ${d.name} (${d.id})`)));
3798
3798
  }
3799
3799
  },
3800
+ attach: {
3801
+ summary: "Add to your account the database one of your machines already uses",
3802
+ usage: "easybits db attach <name> [--description <text>]",
3803
+ options: { description: { type: "string", value: "text", description: "What it is for" } },
3804
+ examples: [
3805
+ "easybits db attach clave # the machine's DATABASE_URL ends in /v1/db/clave/",
3806
+ 'easybits db query clave "SELECT count(*) FROM users" --json'
3807
+ ],
3808
+ // No crea nada: el servidor deriva el namespace de tu cuenta + nombre y exige que exista.
3809
+ // Desde ahí sirven query/tables/export; `db rm` sólo la quita de la lista.
3810
+ async run(ctx) {
3811
+ const name = need(ctx, 0, "name", this.usage);
3812
+ const d = await api(ctx, "POST", "/databases", { name, attach: true, description: str(ctx, "description") });
3813
+ emit(ctx, d, () => console.log(t(`Attached ${d.name} (${d.id})`, `Adjunta ${d.name} (${d.id})`)));
3814
+ }
3815
+ },
3800
3816
  rm: {
3801
3817
  aliases: ["delete", "drop"],
3802
3818
  summary: "Delete a database (irreversible)",
@@ -3826,7 +3842,13 @@ var db = {
3826
3842
  const hit = await findDb(ctx, ref2);
3827
3843
  await confirm(ctx, t(`Delete database ${hit.name} (${hit.id}) and all its data?`, `\xBFBorrar la base ${hit.name} (${hit.id}) con todos sus datos?`), { typeName: hit.name });
3828
3844
  const r = await eb.deleteDatabase(hit.id);
3829
- emit(ctx, { ...r, id: hit.id, name: hit.name }, () => console.log(t(`Deleted ${hit.name} (${hit.id})`, `Borrada ${hit.name} (${hit.id})`)));
3845
+ emit(
3846
+ ctx,
3847
+ { ...r, id: hit.id, name: hit.name },
3848
+ () => console.log(
3849
+ r.detached ? t(`Removed ${hit.name} from your list; its machine keeps the data`, `${hit.name} sali\xF3 de tu lista; su m\xE1quina conserva los datos`) : t(`Deleted ${hit.name} (${hit.id})`, `Borrada ${hit.name} (${hit.id})`)
3850
+ )
3851
+ );
3830
3852
  }
3831
3853
  },
3832
3854
  rename: {
@@ -4918,7 +4940,7 @@ async function updateNotice(current2) {
4918
4940
  }
4919
4941
 
4920
4942
  // src/commands/doctor.ts
4921
- var VERSION = true ? "0.19.1" : "dev";
4943
+ var VERSION = true ? "0.20.0" : "dev";
4922
4944
  var doctor2 = {
4923
4945
  name: "doctor",
4924
4946
  group: "Account",
@@ -5444,7 +5466,7 @@ function describeCron(c) {
5444
5466
  const state = c.enabled ? t("active", "activo") : c.done ? t("done", "terminado") : t("paused", "en pausa");
5445
5467
  return [
5446
5468
  `${c.id} \xAB${c.name}\xBB (${state})`,
5447
- `${t("Schedule", "Horario")}: ${c.schedule} (${c.timezone})${c.until ? ` ${t("until", "hasta")} ${c.until}` : ""}${c.timesLeft != null ? ` \xB7 ${t("runs left", "corridas restantes")}: ${c.timesLeft}` : ""}`,
5469
+ `${t("Schedule", "Horario")}: ${c.schedule} (${c.timezone})${c.until ? ` ${t("until", "hasta")} ${c.until}` : ""}${c.timesLeft != null ? ` \xB7 ${t("runs left", "ejecuciones restantes")}: ${c.timesLeft}` : ""}`,
5448
5470
  `${t("Next run", "Pr\xF3xima")}: ${c.enabled && c.nextRunLocal ? `${c.nextRunLocal} (${c.in})` : "\u2014"}`,
5449
5471
  `${t("Does", "Hace")}: ${describeCronAction(c.action)}`,
5450
5472
  `${t("Notifies", "Avisa")}: ${chans ? `${chans} (${n.on === "always" ? t("always", "siempre") : t("on failure", "si falla")})` : "\u2014"}`,
@@ -5477,7 +5499,8 @@ var ACTION_OPTIONS = {
5477
5499
  file: { type: "string", multiple: true, value: "local[=remote]", description: "File mounted for --run, next to the command by default (repeatable)" },
5478
5500
  "secret-file": { type: "string", multiple: true, value: "NAME:local[=remote]", description: "Upload a local file as a secret only this cron can read, written at the same ~ path in the box (repeatable; e.g. a .p8)" },
5479
5501
  template: { type: "string", value: "python|node|bun|ubuntu", description: "Box image for --run (default python)" },
5480
- timeout: { type: "string", value: "seconds", description: "Time limit for --run (default 300, max 600)" }
5502
+ timeout: { type: "string", value: "seconds", description: "Time limit for --run (default 300, max 600)" },
5503
+ machine: { type: "string", value: "id|name", description: "Run --run with that machine's config (its env and secrets, e.g. DATABASE_URL), resolved on every run" }
5481
5504
  };
5482
5505
  function remotePathFor(local, home = homedir7()) {
5483
5506
  const abs = resolve3(local.replace(/^~(?=\/)/, home));
@@ -5512,7 +5535,8 @@ function execFromFlags(f, read, home = homedir7()) {
5512
5535
  ...files3.length ? { files: files3 } : {},
5513
5536
  ...secrets2.length ? { secrets: secrets2 } : {},
5514
5537
  ...f.template ? { template: f.template } : {},
5515
- ...f.timeout ? { timeoutSeconds: Number(f.timeout) } : {}
5538
+ ...f.timeout ? { timeoutSeconds: Number(f.timeout) } : {},
5539
+ ...f.machine ? { machine: f.machine } : {}
5516
5540
  },
5517
5541
  ...Object.keys(secretValues).length ? { secretValues } : {}
5518
5542
  };
@@ -5592,7 +5616,7 @@ var whenOf = (ctx) => ({
5592
5616
  times: str(ctx, "times"),
5593
5617
  tz: str(ctx, "tz")
5594
5618
  });
5595
- var nextLine = (c) => c.nextRunLocal ? t(`next ${c.nextRunLocal} ${c.timezone} (in ${c.in})`, `pr\xF3xima ${c.nextRunLocal} ${c.timezone} (en ${c.in})`) : t("no next run", "sin pr\xF3xima corrida");
5619
+ var nextLine = (c) => c.nextRunLocal ? t(`next ${c.nextRunLocal} ${c.timezone} (in ${c.in})`, `pr\xF3xima ${c.nextRunLocal} ${c.timezone} (en ${c.in})`) : t("no next run", "sin pr\xF3xima ejecuci\xF3n");
5596
5620
  var flagsOf = (ctx) => ({
5597
5621
  url: str(ctx, "url"),
5598
5622
  method: str(ctx, "method"),
@@ -5607,7 +5631,7 @@ function actionOf(ctx) {
5607
5631
  if (run && (str(ctx, "url") || str(ctx, "agent"))) return { error: "--run, --url and --agent are exclusive" };
5608
5632
  if (run) {
5609
5633
  return execFromFlags(
5610
- { run, files: list(ctx, "file"), secrets: list(ctx, "secret"), secretFiles: list(ctx, "secret-file"), template: str(ctx, "template"), timeout: str(ctx, "timeout") },
5634
+ { run, files: list(ctx, "file"), secrets: list(ctx, "secret"), secretFiles: list(ctx, "secret-file"), template: str(ctx, "template"), timeout: str(ctx, "timeout"), machine: str(ctx, "machine") },
5611
5635
  (p) => {
5612
5636
  try {
5613
5637
  return readFileSync18(p, "utf8");
@@ -5625,10 +5649,10 @@ var STATUS = {
5625
5649
  tarde: ["late", "tarde"],
5626
5650
  fallo: ["failed", "fall\xF3"],
5627
5651
  pausado: ["paused", "pausado"],
5628
- nuevo: ["no runs yet", "sin corridas"]
5652
+ nuevo: ["no runs yet", "sin ejecuciones"]
5629
5653
  };
5630
5654
  function cronStatus(c) {
5631
- if (c.running) return t("running", "corriendo");
5655
+ if (c.running) return t("running", "en ejecuci\xF3n");
5632
5656
  const s = STATUS[c.status];
5633
5657
  return s ? t(s[0], s[1]) : c.status;
5634
5658
  }
@@ -5732,14 +5756,14 @@ var crons = {
5732
5756
  table(
5733
5757
  items.map((r) => ({
5734
5758
  at: fmtDate(r.startedAt),
5735
- ok: r.ok == null ? t("running", "corriendo") : r.ok ? "ok" : t("failed", "fall\xF3"),
5759
+ ok: r.ok == null ? t("running", "en ejecuci\xF3n") : r.ok ? "ok" : t("failed", "fall\xF3"),
5736
5760
  status: r.exitCode != null ? `exit ${r.exitCode}` : r.status ?? "\u2014",
5737
5761
  took: duration(r.durationMs),
5738
5762
  trigger: r.trigger,
5739
5763
  summary: (r.error ?? r.summary ?? "").slice(0, 80)
5740
5764
  })),
5741
5765
  [["at", "STARTED"], ["ok", "RESULT"], ["status", "HTTP"], ["took", "TOOK"], ["trigger", "TRIGGER"], ["summary", "SUMMARY"]],
5742
- t("No runs yet.", "Todav\xEDa no hay corridas.")
5766
+ t("No runs yet.", "Todav\xEDa no hay ejecuciones.")
5743
5767
  );
5744
5768
  if (withLogs) {
5745
5769
  const last = items.find((r) => r.logs);
@@ -5786,7 +5810,7 @@ ${failed.error}`);
5786
5810
  }
5787
5811
  if (Date.now() >= deadline) {
5788
5812
  throw new CliError(
5789
- t(`Gave up waiting for \xAB${mine.name}\xBB${r.nextRunLocal ? ` (next run ${r.nextRunLocal})` : ""}.`, `Me cans\xE9 de esperar \xAB${mine.name}\xBB${r.nextRunLocal ? ` (pr\xF3xima corrida ${r.nextRunLocal})` : ""}.`),
5813
+ t(`Gave up waiting for \xAB${mine.name}\xBB${r.nextRunLocal ? ` (next run ${r.nextRunLocal})` : ""}.`, `Me cans\xE9 de esperar \xAB${mine.name}\xBB${r.nextRunLocal ? ` (pr\xF3xima ejecuci\xF3n ${r.nextRunLocal})` : ""}.`),
5790
5814
  EXIT.API,
5791
5815
  `easybits crons wait ${mine.id} --timeout 2h`,
5792
5816
  "timeout"
@@ -5835,7 +5859,7 @@ ${failed.error}`);
5835
5859
  create: {
5836
5860
  aliases: ["add"],
5837
5861
  summary: "Create a cron: call a public https URL, send a turn to one of your agents or run a command in a throwaway box, repeating (at most every 5 min) or once",
5838
- usage: 'easybits crons create <name> (--cron "<5 fields>" [--until <when>] [--times N] | --at <when> | --in <duration>) [--tz <IANA>] (--url <https-url> [--method] [--body] [--secret NAME] | --agent <id> --prompt <text> | --run <cmd> [--file f]\u2026 [--secret NAME]\u2026 [--secret-file NAME:path]\u2026 [--template] [--timeout]) [--dry-run]',
5862
+ usage: 'easybits crons create <name> (--cron "<5 fields>" [--until <when>] [--times N] | --at <when> | --in <duration>) [--tz <IANA>] (--url <https-url> [--method] [--body] [--secret NAME] | --agent <id> --prompt <text> | --run <cmd> [--file f]\u2026 [--secret NAME]\u2026 [--secret-file NAME:path]\u2026 [--template] [--timeout] [--machine id|name]) [--dry-run]',
5839
5863
  options: {
5840
5864
  cron: { type: "string", value: "expr", description: 'Cron of 5 fields, e.g. "30 8 * * *" = daily 8:30' },
5841
5865
  ...WHEN_OPTIONS,
@@ -5867,7 +5891,7 @@ ${failed.error}`);
5867
5891
  emit(ctx, p, () => {
5868
5892
  console.log(t(`OK, nothing created. \xAB${name}\xBB \u2014 ${p.schedule}`, `V\xE1lido, no se cre\xF3 nada. \xAB${name}\xBB \u2014 ${p.schedule}`));
5869
5893
  for (const r of p.nextRuns) console.log(` ${r.local} ${p.timezone} (${r.at})`);
5870
- if (p.in) console.log(t(`First run in ${p.in}.`, `La primera corre en ${p.in}.`));
5894
+ if (p.in) console.log(t(`First run in ${p.in}.`, `La primera se ejecuta en ${p.in}.`));
5871
5895
  });
5872
5896
  return;
5873
5897
  }
@@ -5922,7 +5946,7 @@ ${failed.error}`);
5922
5946
  const mine = await resolveUserCron(ctx, ref2);
5923
5947
  if (!mine) throw new CliError(t(`You have no cron "${ref2}".`, `No tienes un cron "${ref2}".`), EXIT.API, "easybits crons ls", "not_found", 404);
5924
5948
  requireYesIfHeadless(ctx);
5925
- await confirm(ctx, t(`Delete cron \xAB${mine.name}\xBB? It stops running right away.`, `\xBFBorrar el cron \xAB${mine.name}\xBB? Deja de correr de inmediato.`));
5949
+ await confirm(ctx, t(`Delete cron \xAB${mine.name}\xBB? It stops running right away.`, `\xBFBorrar el cron \xAB${mine.name}\xBB? Deja de ejecutarse de inmediato.`));
5926
5950
  const r = await api(ctx, "DELETE", `/crons/${mine.id}`);
5927
5951
  emit(ctx, r, () => console.log(t(`Deleted \xAB${mine.name}\xBB`, `Borrado \xAB${mine.name}\xBB`)));
5928
5952
  }
@@ -7016,7 +7040,7 @@ var HELP_ES = {
7016
7040
  "Compute": "C\xF3mputo",
7017
7041
  "Firecracker microVMs (alias: sb)": "MicroVMs Firecracker (alias: sb)",
7018
7042
  "List your sandboxes": "Enlista tus sandboxes",
7019
- "Create a sandbox and wait until it is running": "Crea un sandbox y espera a que est\xE9 corriendo",
7043
+ "Create a sandbox and wait until it is running": "Crea un sandbox y espera a que est\xE9 en marcha",
7020
7044
  "Base template (default ubuntu): ubuntu, python, node, code-interpreter\u2026": "Template base (default ubuntu): ubuntu, python, node, code-interpreter\u2026",
7021
7045
  "Human label (lets you `ssh <name>.ghosty`)": "Nombre para personas (permite `ssh <nombre>.ghosty`)",
7022
7046
  "Time to live before auto-destroy (was --timeout)": "Tiempo de vida antes de autodestruirse (antes --timeout)",
@@ -7025,7 +7049,7 @@ var HELP_ES = {
7025
7049
  "KEY=VALUE lines (dotenv); - reads stdin. Use it for secrets": "Renglones KEY=VALUE (dotenv); - lee stdin. \xDAsalo para secretos",
7026
7050
  "Return right away instead of waiting for running": "Regresa de inmediato en vez de esperar a que corra",
7027
7051
  "Show one sandbox": "Muestra un sandbox",
7028
- "Run a shell command inside a sandbox": "Corre un comando de shell dentro de un sandbox",
7052
+ "Run a shell command inside a sandbox": "Ejecuta un comando de shell dentro de un sandbox",
7029
7053
  "Working directory": "Directorio de trabajo",
7030
7054
  "Kill the command after this long": "Mata el comando despu\xE9s de este tiempo",
7031
7055
  "Read the sandbox journal (optionally one systemd unit)": "Lee el journal del sandbox (opcionalmente de una unit de systemd)",
@@ -7043,7 +7067,7 @@ var HELP_ES = {
7043
7067
  "Skip the confirmation (required without a terminal or with --json)": "Salta la confirmaci\xF3n (obligatorio sin terminal o con --json)",
7044
7068
  "Capture a copy-on-write snapshot without stopping the box": "Toma un snapshot copy-on-write sin detener la caja",
7045
7069
  "Snapshot label": "Nombre del snapshot",
7046
- "Agents running in their own sandbox": "Agentes que corren en su propio sandbox",
7070
+ "Agents running in their own sandbox": "Agentes que viven en su propio sandbox",
7047
7071
  "List your agents": "Enlista tus agentes",
7048
7072
  "Show one agent: record, prompt, MCP servers, skills and files": "Muestra un agente: registro, prompt, servidores MCP, skills y archivos",
7049
7073
  "Only these fields: agentId, name, template, status, lastError, sandboxId, agentUrl, embedToken, createdAt, expiresAt, systemPrompt, systemPromptMode, mcpServers, skills, files": "S\xF3lo estos campos: agentId, name, template, status, lastError, sandboxId, agentUrl, embedToken, createdAt, expiresAt, systemPrompt, systemPromptMode, mcpServers, skills, files",
@@ -7189,6 +7213,8 @@ var HELP_ES = {
7189
7213
  "SQL databases (libSQL)": "Bases de datos SQL (libSQL)",
7190
7214
  "List your databases": "Enlista tus bases de datos",
7191
7215
  "Create a database": "Crea una base de datos",
7216
+ "Add to your account the database one of your machines already uses": "Agrega a tu cuenta la base que ya usa una de tus m\xE1quinas",
7217
+ "the machine's DATABASE_URL ends in /v1/db/clave/": "el DATABASE_URL de la m\xE1quina termina en /v1/db/clave/",
7192
7218
  "What it is for": "Para qu\xE9 es",
7193
7219
  "Delete a database (irreversible)": "Borra una base de datos (irreversible)",
7194
7220
  "Show its tables and rows; delete nothing": "Ense\xF1a sus tablas y filas; no borra nada",
@@ -7200,7 +7226,7 @@ var HELP_ES = {
7200
7226
  "asks you to type the name": "te pide teclear el nombre",
7201
7227
  "scripts and agents": "scripts y agentes",
7202
7228
  "List tables with row counts and columns, and how many links are permanent": "Enlista las tablas con sus filas y columnas, y cu\xE1ntas ligas son permanentes",
7203
- "Run one SQL statement (by database id or name)": "Corre una sentencia SQL (por id o nombre de la base)",
7229
+ "Run one SQL statement (by database id or name)": "Ejecuta una sentencia SQL (por id o nombre de la base)",
7204
7230
  "Positional ? parameter (repeatable)": "Par\xE1metro ? posicional (repetible)",
7205
7231
  "Storage": "Almacenamiento",
7206
7232
  "Your files in EasyBits storage": "Tus archivos en el almacenamiento de EasyBits",
@@ -7283,24 +7309,25 @@ var HELP_ES = {
7283
7309
  "Release a machine: stops billing, takes a last backup and destroys it": "Libera una m\xE1quina: deja de cobrarse, toma un \xFAltimo respaldo y la destruye",
7284
7310
  "The hosting catalog: sizes and monthly prices in MXN": "El cat\xE1logo de hosting: tama\xF1os y precio mensual en MXN",
7285
7311
  // crons (tuyos y de la plataforma)
7286
- "Your scheduled jobs (call a URL, message an agent or run a command; repeating or once) and, for admins, the platform's": "Tus tareas programadas (pegarle a una URL, escribirle a un agente o correr un comando; repetidas o de una sola vez) y, para admins, las de la plataforma",
7312
+ "Your scheduled jobs (call a URL, message an agent or run a command; repeating or once) and, for admins, the platform's": "Tus tareas programadas (pegarle a una URL, escribirle a un agente o ejecutar un comando; repetidas o de una sola vez) y, para admins, las de la plataforma",
7287
7313
  "List your crons (or, with --platform, the platform's scheduled jobs)": "Enlista tus crons (o, con --platform, las tareas de la plataforma)",
7288
7314
  "Platform jobs (backups, purges\u2026; platform admins only)": "Tareas de la plataforma (respaldos, purgas\u2026; s\xF3lo admins)",
7289
- "Show the last runs of one of your crons (id or name) or of a platform job, with the full error": "Muestra las \xFAltimas corridas de un cron tuyo (id o nombre) o de una tarea de la plataforma, con el error completo",
7290
- "Run one of your crons or a platform job now, in the background (trigger manual)": "Corre ya un cron tuyo o una tarea de la plataforma, en segundo plano (manual)",
7315
+ "Show the last runs of one of your crons (id or name) or of a platform job, with the full error": "Muestra las \xFAltimas ejecuciones de un cron tuyo (id o nombre) o de una tarea de la plataforma, con el error completo",
7316
+ "Run one of your crons or a platform job now, in the background (trigger manual)": "Ejecuta ya un cron tuyo o una tarea de la plataforma, en segundo plano (manual)",
7291
7317
  "Pause one of your crons or a platform job until you resume it": "Pausa un cron tuyo o una tarea de la plataforma hasta que lo reanudes",
7292
7318
  "Resume one of your crons or a platform job": "Reanuda un cron tuyo o una tarea de la plataforma",
7293
- "Create a cron: call a public https URL, send a turn to one of your agents or run a command in a throwaway box, repeating (at most every 5 min) or once": "Crea un cron: pegarle a una URL https p\xFAblica, mandarle un turno a uno de tus agentes o correr un comando en una caja desechable, repetido (como mucho cada 5 min) o de una sola vez",
7319
+ "Create a cron: call a public https URL, send a turn to one of your agents or run a command in a throwaway box, repeating (at most every 5 min) or once": "Crea un cron: pegarle a una URL https p\xFAblica, mandarle un turno a uno de tus agentes o ejecutar un comando en una caja desechable, repetido (como mucho cada 5 min) o de una sola vez",
7294
7320
  "Vault secret: a header with --url (default Authorization: Bearer); an env var with --run (repeatable)": "Secreto de la b\xF3veda: header con --url (default Authorization: Bearer); variable de entorno con --run (repetible)",
7295
- "Run this shell command in a throwaway box instead (python, files and secrets included; success = exit 0)": "Correr este comando de shell en una caja desechable (con python, tus archivos y secretos; \xE9xito = exit 0)",
7321
+ "Run this shell command in a throwaway box instead (python, files and secrets included; success = exit 0)": "Ejecutar este comando de shell en una caja desechable (con python, tus archivos y secretos; \xE9xito = exit 0)",
7296
7322
  "File mounted for --run, next to the command by default (repeatable)": "Archivo que se monta para --run, junto al comando por default (repetible)",
7297
7323
  "Upload a local file as a secret only this cron can read, written at the same ~ path in the box (repeatable; e.g. a .p8)": "Sube un archivo local como secreto que s\xF3lo este cron puede leer; se escribe en la misma ruta ~ dentro de la caja (repetible; p. ej. un .p8)",
7298
7324
  "Box image for --run (default python)": "Imagen de la caja para --run (default python)",
7299
7325
  "Time limit for --run (default 300, max 600)": "Tiempo l\xEDmite de --run (default 300, m\xE1ximo 600)",
7300
- "Also print stdout/stderr of --run crons (last 64 KB per run)": "Muestra tambi\xE9n stdout/stderr de los crons --run (\xFAltimos 64 KB por corrida)",
7301
- "Wait for the next run of one of your crons to finish and exit with its result (exec: its exit code)": "Espera a que termine la siguiente corrida de un cron tuyo y sale con su resultado (exec: su c\xF3digo de salida)",
7326
+ "Run --run with that machine's config (its env and secrets, e.g. DATABASE_URL), resolved on every run": "Corre --run con la configuraci\xF3n de esa m\xE1quina (su env y sus secretos, p. ej. DATABASE_URL), resuelta en cada ejecuci\xF3n",
7327
+ "Also print stdout/stderr of --run crons (last 64 KB per run)": "Muestra tambi\xE9n stdout/stderr de los crons --run (\xFAltimos 64 KB por ejecuci\xF3n)",
7328
+ "Wait for the next run of one of your crons to finish and exit with its result (exec: its exit code)": "Espera a que termine la siguiente ejecuci\xF3n de un cron tuyo y sale con su resultado (exec: su c\xF3digo de salida)",
7302
7329
  "Give up after this long (default 30m; 10m, 2h\u2026)": "Se rinde despu\xE9s de este tiempo (default 30m; 10m, 2h\u2026)",
7303
- "Tell you after each run: push to the Ghosty app (vault secret GHOSTY_PUSH_TOKEN), email to your account and/or an event in one of your inboxes; none removes it": "Te avisa tras cada corrida: push a la app de Ghosty (secreto GHOSTY_PUSH_TOKEN de la b\xF3veda), correo a tu cuenta y/o un evento en uno de tus buzones; none lo quita",
7330
+ "Tell you after each run: push to the Ghosty app (vault secret GHOSTY_PUSH_TOKEN), email to your account and/or an event in one of your inboxes; none removes it": "Te avisa tras cada ejecuci\xF3n: push a la app de Ghosty (secreto GHOSTY_PUSH_TOKEN de la b\xF3veda), correo a tu cuenta y/o un evento en uno de tus buzones; none lo quita",
7304
7331
  // inbox (buzones de eventos)
7305
7332
  "Event inboxes: your own webhook URL whose events reach your terminal live or wait for you to read them": "Buzones de eventos: tu propia URL de webhook; lo que llega te alcanza en la terminal en vivo o te espera para que lo leas",
7306
7333
  "List your inboxes with their URL and unread events": "Enlista tus buzones con su URL y los eventos sin leer",
@@ -7318,22 +7345,22 @@ var HELP_ES = {
7318
7345
  "New name, unique in your account": "Nombre nuevo, \xFAnico en tu cuenta",
7319
7346
  "Days events are kept (1-30)": "D\xEDas que se guardan los eventos (1-30)",
7320
7347
  "Give an inbox a new URL and print it; the old one stops accepting writes right away (stored events stay)": "Le da al buz\xF3n una URL nueva y la imprime; la vieja deja de aceptar escrituras de inmediato (los eventos guardados se quedan)",
7321
- "Show one of your crons: what it does, how it notifies you and when it runs (--json: the whole object)": "Muestra un cron tuyo: qu\xE9 hace, c\xF3mo te avisa y cu\xE1ndo corre (--json: el objeto completo)",
7322
- "At most N runs of one of your crons (1-50, default 50)": "Como m\xE1ximo N corridas de un cron tuyo (1-50, default 50)",
7348
+ "Show one of your crons: what it does, how it notifies you and when it runs (--json: the whole object)": "Muestra un cron tuyo: qu\xE9 hace, c\xF3mo te avisa y cu\xE1ndo se ejecuta (--json: el objeto completo)",
7349
+ "At most N runs of one of your crons (1-50, default 50)": "Como m\xE1ximo N ejecuciones de un cron tuyo (1-50, default 50)",
7323
7350
  "When to notify (default failure)": "Cu\xE1ndo avisar (default failure: s\xF3lo si falla)",
7324
- 'Run ONCE at this time: ISO ("2026-10-18T23:00", read in --tz) or "23:00" (today)': 'Correr UNA SOLA VEZ a esta hora: ISO ("2026-10-18T23:00", en la zona de --tz) o "23:00" (hoy)',
7325
- "Run ONCE after this long: 10m, 2h, 1h30m, 1d": "Correr UNA SOLA VEZ dentro de: 10m, 2h, 1h30m, 1d",
7351
+ 'Run ONCE at this time: ISO ("2026-10-18T23:00", read in --tz) or "23:00" (today)': 'Ejecutar UNA SOLA VEZ a esta hora: ISO ("2026-10-18T23:00", en la zona de --tz) o "23:00" (hoy)',
7352
+ "Run ONCE after this long: 10m, 2h, 1h30m, 1d": "Ejecutar UNA SOLA VEZ dentro de: 10m, 2h, 1h30m, 1d",
7326
7353
  "A repeating cron stops after this date": "Un cron que se repite se detiene despu\xE9s de esta fecha",
7327
- "A repeating cron stops after N more runs": "Un cron que se repite se detiene tras N corridas m\xE1s",
7328
- "Validate and show the next 3 runs without creating anything": "Valida y muestra las pr\xF3ximas 3 corridas sin crear nada",
7354
+ "A repeating cron stops after N more runs": "Un cron que se repite se detiene tras N ejecuciones m\xE1s",
7355
+ "Validate and show the next 3 runs without creating anything": "Valida y muestra las pr\xF3ximas 3 ejecuciones sin crear nada",
7329
7356
  'Cron of 5 fields, e.g. "30 8 * * *" = daily 8:30': 'Cron de 5 campos, p. ej. "30 8 * * *" = diario 8:30',
7330
7357
  "IANA time zone (default America/Mexico_City)": "Zona horaria IANA (default America/Mexico_City)",
7331
- "Call this public https URL on each run": "Pegarle a esta URL https p\xFAblica en cada corrida",
7358
+ "Call this public https URL on each run": "Pegarle a esta URL https p\xFAblica en cada ejecuci\xF3n",
7332
7359
  "HTTP method (default GET)": "M\xE9todo HTTP (default GET)",
7333
7360
  "Request body (not with GET)": "Cuerpo de la petici\xF3n (no con GET)",
7334
7361
  "Header for --secret": "Header para --secret",
7335
7362
  "Send a turn to this fleet agent instead of calling a URL": "Mandarle un turno a este agente de la flota en vez de pegarle a una URL",
7336
- "What the agent is told on each run (with --agent)": "Lo que se le dice al agente en cada corrida (con --agent)",
7363
+ "What the agent is told on each run (with --agent)": "Lo que se le dice al agente en cada ejecuci\xF3n (con --agent)",
7337
7364
  "Change one of your crons (only what you pass)": "Cambia un cron tuyo (s\xF3lo lo que pases)",
7338
7365
  "New name": "Nombre nuevo",
7339
7366
  "New schedule": "Horario nuevo",
@@ -7653,7 +7680,7 @@ function normalizeArgs(input) {
7653
7680
  }
7654
7681
 
7655
7682
  // src/index.ts
7656
- var VERSION2 = true ? "0.19.1" : "dev";
7683
+ var VERSION2 = true ? "0.20.0" : "dev";
7657
7684
  var GLOBAL_OPTIONS = {
7658
7685
  json: { type: "boolean" },
7659
7686
  token: { type: "string" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easybits.cloud/cli",
3
- "version": "0.19.1",
3
+ "version": "0.20.0",
4
4
  "description": "Official CLI for EasyBits, the cloud for AI agents — sandboxes, hosting, domains, databases, agents and files from your terminal",
5
5
  "type": "module",
6
6
  "bin": {