lakebed 0.0.21 → 0.0.23-staging.26699880384

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/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "lakebed",
3
- "version": "0.0.21",
3
+ "version": "0.0.23-staging.26699880384",
4
4
  "description": "Agent-native CLI and runtime for building and deploying Lakebed capsules.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "homepage": "https://lakebed.dev",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/pingdotgg/span.git",
10
+ "url": "git+https://github.com/pingdotgg/lakebed.git",
11
11
  "directory": "packages/lakebed"
12
12
  },
13
13
  "keywords": [
@@ -26,6 +26,7 @@
26
26
  "src/cli.js",
27
27
  "src/client.d.ts",
28
28
  "src/client.js",
29
+ "src/release.js",
29
30
  "src/runtime.js",
30
31
  "src/server.d.ts",
31
32
  "src/server.js",
@@ -55,6 +56,9 @@
55
56
  "publishConfig": {
56
57
  "access": "public"
57
58
  },
59
+ "scripts": {
60
+ "check": "node --check src/cli.js && node --check src/runtime.js && node --check src/server.js && node --check src/client.js && node --check src/release.js && node --check src/source-store.js && node --check src/source-runtime.js && node --check src/source-runtime-worker.js && node --check src/source-runtime-loader.mjs && node --check src/anonymous.js && node --check src/anonymous-server.js && node --check src/auth.js && node --check src/version.js && node --check src/services/all-in-one.js && node --check src/services/api-dashboard.js && node --check src/services/capsule-runner.js"
61
+ },
58
62
  "dependencies": {
59
63
  "esbuild": "^0.27.1",
60
64
  "pg": "^8.16.3",
@@ -63,8 +67,5 @@
63
67
  },
64
68
  "devDependencies": {
65
69
  "@types/ws": "^8.18.1"
66
- },
67
- "scripts": {
68
- "check": "node --check src/cli.js && node --check src/runtime.js && node --check src/server.js && node --check src/client.js && node --check src/source-store.js && node --check src/source-runtime.js && node --check src/source-runtime-worker.js && node --check src/source-runtime-loader.mjs && node --check src/anonymous.js && node --check src/anonymous-server.js && node --check src/auth.js && node --check src/version.js && node --check src/services/all-in-one.js && node --check src/services/api-dashboard.js && node --check src/services/capsule-runner.js"
69
70
  }
70
- }
71
+ }
@@ -111,6 +111,15 @@ function sendText(res, status, value, headers = {}) {
111
111
  res.end(value);
112
112
  }
113
113
 
114
+ function healthReleaseMetadata(env = process.env) {
115
+ return {
116
+ environment: env.RAILWAY_ENVIRONMENT_NAME ?? null,
117
+ gitSha: env.RAILWAY_GIT_COMMIT_SHA ?? null,
118
+ service: env.RAILWAY_SERVICE_NAME ?? null,
119
+ version: LAKEBED_VERSION
120
+ };
121
+ }
122
+
114
123
  function redirect(res, location, headers = {}) {
115
124
  res.writeHead(302, {
116
125
  Location: location,
@@ -436,6 +445,48 @@ function isApiDashboardRoute(pathname) {
436
445
  );
437
446
  }
438
447
 
448
+ function isDashboardBrowserRoute(pathname) {
449
+ return (
450
+ pathname === "/" ||
451
+ pathname === "/deploys" ||
452
+ pathname === "/dashboard" ||
453
+ pathname === "/auth" ||
454
+ pathname.startsWith("/auth/") ||
455
+ pathname === "/admin" ||
456
+ pathname.startsWith("/admin/") ||
457
+ pathname.startsWith("/claim/")
458
+ );
459
+ }
460
+
461
+ function normalizedUrlHost(value) {
462
+ try {
463
+ return new URL(value).host.toLowerCase();
464
+ } catch {
465
+ return "";
466
+ }
467
+ }
468
+
469
+ function dashboardRedirectLocation({ dashboardRootUrl, requestUrl }) {
470
+ const pathname = requestUrl.pathname === "/" ? "/deploys" : requestUrl.pathname;
471
+ const target = new URL(pathname, dashboardRootUrl);
472
+ target.search = requestUrl.search;
473
+ return target.href;
474
+ }
475
+
476
+ function shouldRedirectToDashboardHost({ dashboardRootUrl, host, publicRootUrl, requestUrl }) {
477
+ if (!isDashboardBrowserRoute(requestUrl.pathname)) {
478
+ return false;
479
+ }
480
+
481
+ const publicHost = normalizedUrlHost(publicRootUrl);
482
+ const dashboardHost = normalizedUrlHost(dashboardRootUrl);
483
+ if (!publicHost || !dashboardHost || publicHost === dashboardHost) {
484
+ return false;
485
+ }
486
+
487
+ return String(host).toLowerCase() === publicHost;
488
+ }
489
+
439
490
  function appUrlForSlug({ appBaseDomain, slug }) {
440
491
  if (!appBaseDomain) {
441
492
  throw new Error("LAKEBED_APP_BASE_DOMAIN is required to create hosted deploy URLs.");
@@ -6213,7 +6264,23 @@ export async function startAnonymousServer({
6213
6264
 
6214
6265
  try {
6215
6266
  if (req.method === "GET" && requestUrl.pathname === "/healthz") {
6216
- sendJson(res, 200, { ok: true });
6267
+ sendJson(res, 200, {
6268
+ ok: true,
6269
+ release: healthReleaseMetadata()
6270
+ });
6271
+ return;
6272
+ }
6273
+
6274
+ if (
6275
+ servesApiDashboard &&
6276
+ shouldRedirectToDashboardHost({
6277
+ dashboardRootUrl: resolvedDashboardRootUrl,
6278
+ host,
6279
+ publicRootUrl: resolvedPublicRootUrl,
6280
+ requestUrl
6281
+ })
6282
+ ) {
6283
+ redirect(res, dashboardRedirectLocation({ dashboardRootUrl: resolvedDashboardRootUrl, requestUrl }));
6217
6284
  return;
6218
6285
  }
6219
6286
 
package/src/cli.js CHANGED
@@ -23,6 +23,11 @@ import {
23
23
  } from "./anonymous.js";
24
24
  import { startAnonymousServer } from "./anonymous-server.js";
25
25
  import { authFromUrl as resolveAuthFromUrl, createGuestAuth, requestOrigin, shooBaseUrlFromEnv } from "./auth.js";
26
+ import {
27
+ LAKEBED_APP_BASE_DOMAIN as defaultHostedAppBaseDomain,
28
+ LAKEBED_DEPLOY_API_URL as defaultDeployApiUrl,
29
+ LAKEBED_RELEASE_CHANNEL
30
+ } from "./release.js";
26
31
  import { LogBuffer, StateCell } from "./runtime.js";
27
32
  import { MemorySourceStore, createMemorySourceStoreFromDirectory, sourcePathDirname, sourcePathJoin } from "./source-store.js";
28
33
 
@@ -30,7 +35,10 @@ const root = process.cwd();
30
35
  const packageDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
31
36
  const packageNodeModules = resolve(packageDir, "node_modules");
32
37
  const sourceNamespace = "lakebed-source";
33
- const defaultDeployApiUrl = "https://api.lakebed.dev";
38
+ const cliPackageSpec = LAKEBED_RELEASE_CHANNEL === "staging" ? "lakebed@staging" : "lakebed";
39
+ const cliCommand = `npx ${cliPackageSpec}`;
40
+ const productionDeployApiUrl = "https://api.lakebed.dev";
41
+ const legacyDeployApiUrl = "https://api.lakebed.app";
34
42
  const execFileAsync = promisify(execFile);
35
43
  const endpointBodyMaxBytes = 2 * 1024 * 1024;
36
44
 
@@ -38,21 +46,21 @@ function usage() {
38
46
  console.log(`lakebed
39
47
 
40
48
  Usage:
41
- npx lakebed new [name] [--template todo] [--no-git]
42
- npx lakebed create [name] [--template todo] [--no-git]
43
- npx lakebed dev [capsule-dir] [--port 3000]
44
- npx lakebed build [capsule-dir] --target anonymous [--out .lakebed/artifacts/app.json] [--json]
45
- npx lakebed deploy [capsule-dir] [--api <url>] [--public-inspect] [--json]
46
- npx lakebed claim [capsule-dir] [--api <url>] [--json]
47
- npx lakebed domains add <subdomain.lakebed.app> [--api <url>] [--json]
48
- npx lakebed anonymous-server [--port 8787] [--public-root-url <url>] [--dashboard-root-url <url>] [--app-base-domain <domain>] [--role all|api-dashboard|runner]
49
- npx lakebed inspect <deploy-id-or-url> [--api <url>] [--inspect-token <token>] [--json]
50
- npx lakebed run-many [capsule-dir] [--count 20] [--base-port 4000]
51
- npx lakebed auth as <name>
52
- npx lakebed auth reset
53
- npx lakebed db list [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
54
- npx lakebed db dump [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
55
- npx lakebed logs [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
49
+ ${cliCommand} new [name] [--template todo] [--no-git]
50
+ ${cliCommand} create [name] [--template todo] [--no-git]
51
+ ${cliCommand} dev [capsule-dir] [--port 3000]
52
+ ${cliCommand} build [capsule-dir] --target anonymous [--out .lakebed/artifacts/app.json] [--json]
53
+ ${cliCommand} deploy [capsule-dir] [--api <url>] [--public-inspect] [--json]
54
+ ${cliCommand} claim [capsule-dir] [--api <url>] [--json]
55
+ ${cliCommand} domains add <subdomain.${defaultHostedAppBaseDomain}> [--api <url>] [--json]
56
+ ${cliCommand} anonymous-server [--port 8787] [--public-root-url <url>] [--dashboard-root-url <url>] [--app-base-domain <domain>] [--role all|api-dashboard|runner]
57
+ ${cliCommand} inspect <deploy-id-or-url> [--api <url>] [--inspect-token <token>] [--json]
58
+ ${cliCommand} run-many [capsule-dir] [--count 20] [--base-port 4000]
59
+ ${cliCommand} auth as <name>
60
+ ${cliCommand} auth reset
61
+ ${cliCommand} db list [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
62
+ ${cliCommand} db dump [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
63
+ ${cliCommand} logs [deploy-id-or-url] [--port 3000] [--inspect-token <token>]
56
64
  `);
57
65
  }
58
66
 
@@ -1096,7 +1104,7 @@ export default capsule({
1096
1104
  <p className="text-sm font-semibold uppercase tracking-wide text-cyan-300">Lakebed deploy</p>
1097
1105
  <h1 className="mt-3 text-3xl font-semibold">Claim required</h1>
1098
1106
  <p className="mt-4 text-neutral-300">
1099
- This capsule uses ${feature}. Claim this deploy, then run npx lakebed deploy again to publish the app.
1107
+ This capsule uses ${feature}. Claim this deploy, then run ${cliCommand} deploy again to publish the app.
1100
1108
  </p>
1101
1109
  </section>
1102
1110
  </main>
@@ -1193,16 +1201,16 @@ function claimTokenFromDeployResponse(deployed) {
1193
1201
  return null;
1194
1202
  }
1195
1203
 
1196
- function claimUrlFromDeployMetadata(metadata) {
1204
+ function claimUrlFromDeployMetadata(metadata, api = metadata?.api) {
1197
1205
  if (!metadata?.api || !metadata?.deployId || !metadata?.claimToken) {
1198
1206
  return null;
1199
1207
  }
1200
1208
 
1201
- return `${String(metadata.api).replace(/\/+$/g, "")}/claim/${encodeURIComponent(metadata.deployId)}/${encodeURIComponent(metadata.claimToken)}`;
1209
+ return `${normalizeHostedUrl(api)}/claim/${encodeURIComponent(metadata.deployId)}/${encodeURIComponent(metadata.claimToken)}`;
1202
1210
  }
1203
1211
 
1204
1212
  function claimCommandText({ api, capsuleArg }) {
1205
- const parts = ["npx", "lakebed", "claim"];
1213
+ const parts = ["npx", cliPackageSpec, "claim"];
1206
1214
  if (capsuleArg) {
1207
1215
  parts.push(capsuleArg);
1208
1216
  }
@@ -1219,7 +1227,7 @@ function normalizeDomainCommandHostname(value) {
1219
1227
  }
1220
1228
 
1221
1229
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw) || raw.includes("/") || raw.includes("\\") || raw.includes(":")) {
1222
- throw new Error("Enter a domain like my-app.lakebed.app, without a scheme, port, or path.");
1230
+ throw new Error(`Enter a domain like my-app.${defaultHostedAppBaseDomain}, without a scheme, port, or path.`);
1223
1231
  }
1224
1232
 
1225
1233
  const hostname = domainToASCII(raw.replace(/\.$/, "").toLowerCase());
@@ -1330,6 +1338,15 @@ function normalizeHostedUrl(value) {
1330
1338
  }
1331
1339
  }
1332
1340
 
1341
+ function canonicalDeployApiUrl(value) {
1342
+ const normalized = normalizeHostedUrl(value);
1343
+ return normalized === legacyDeployApiUrl ? productionDeployApiUrl : normalized;
1344
+ }
1345
+
1346
+ function deployApiUrlsMatch(left, right) {
1347
+ return canonicalDeployApiUrl(left) === canonicalDeployApiUrl(right);
1348
+ }
1349
+
1333
1350
  async function readResponseJson(response) {
1334
1351
  const body = await response.text();
1335
1352
  if (!response.ok) {
@@ -1340,7 +1357,7 @@ async function readResponseJson(response) {
1340
1357
 
1341
1358
  async function deployCommand(args) {
1342
1359
  if (args.some((arg) => arg === "--ttl" || arg.startsWith("--ttl="))) {
1343
- throw new Error("npx lakebed deploy no longer accepts --ttl. Deploy expiry is set by the server.");
1360
+ throw new Error(`${cliCommand} deploy no longer accepts --ttl. Deploy expiry is set by the server.`);
1344
1361
  }
1345
1362
 
1346
1363
  const [capsuleArg] = positionals(args);
@@ -1354,7 +1371,7 @@ async function deployCommand(args) {
1354
1371
  const inspectPolicy = hasFlag(args, "--public-inspect") ? "public" : undefined;
1355
1372
  const metadata = await readDeployMetadata(capsuleDir);
1356
1373
  const canUpdate =
1357
- metadata?.api === api && typeof metadata?.deployId === "string" && typeof metadata?.claimToken === "string";
1374
+ deployApiUrlsMatch(metadata?.api, api) && typeof metadata?.deployId === "string" && typeof metadata?.claimToken === "string";
1358
1375
  let currentDeploy = null;
1359
1376
  if (canUpdate) {
1360
1377
  const currentResponse = await fetch(`${api}/v1/deploys/${encodeURIComponent(metadata.deployId)}`);
@@ -1367,7 +1384,7 @@ async function deployCommand(args) {
1367
1384
  if (!currentDeploy?.claimed && hasServerEnvValues) {
1368
1385
  if (canUpdate && currentDeploy) {
1369
1386
  throw new Error(
1370
- `This capsule defines server env in ${SERVER_ENV_FILE}.\n\nThis deploy is still anonymous. Claim it first, then run npx lakebed deploy again to sync server env.`
1387
+ `This capsule defines server env in ${SERVER_ENV_FILE}.\n\nThis deploy is still anonymous. Claim it first, then run ${cliCommand} deploy again to sync server env.`
1371
1388
  );
1372
1389
  }
1373
1390
  try {
@@ -1384,7 +1401,7 @@ async function deployCommand(args) {
1384
1401
  } catch (error) {
1385
1402
  if (error instanceof AnonymousCompilerError && canUpdate && currentDeploy && !currentDeploy.claimed) {
1386
1403
  throw new Error(
1387
- `${error.message}\n\nThis deploy is still anonymous. Claim it first, then run npx lakebed deploy again to use server-side fetch.`
1404
+ `${error.message}\n\nThis deploy is still anonymous. Claim it first, then run ${cliCommand} deploy again to use server-side fetch.`
1388
1405
  );
1389
1406
  }
1390
1407
  if ((!canUpdate || !currentDeploy) && canDeployAfterClaim(error)) {
@@ -1466,7 +1483,7 @@ async function deployCommand(args) {
1466
1483
  if (deployed.claimUrl) {
1467
1484
  console.log(`Claim: ${claimCommandText({ api, capsuleArg })}`);
1468
1485
  }
1469
- console.log(`Inspect: npx lakebed inspect ${deployed.deployId}`);
1486
+ console.log(`Inspect: ${cliCommand} inspect ${deployed.deployId}`);
1470
1487
  if (deployed.inspectPolicy === "public") {
1471
1488
  console.log("Inspect policy: public - data and logs are readable by anyone with the app URL.");
1472
1489
  }
@@ -1484,7 +1501,7 @@ async function deployCommand(args) {
1484
1501
  }
1485
1502
  if (envelope.claimRequired) {
1486
1503
  console.log("\nThis app needs a claimed deploy before server-side fetch or server env can run.");
1487
- console.log(`Run ${claimCommandText({ api, capsuleArg })}, then run npx lakebed deploy again.`);
1504
+ console.log(`Run ${claimCommandText({ api, capsuleArg })}, then run ${cliCommand} deploy again.`);
1488
1505
  }
1489
1506
  }
1490
1507
 
@@ -1495,14 +1512,14 @@ async function claimCommand(args) {
1495
1512
  const metadata = await readDeployMetadata(capsuleDir);
1496
1513
 
1497
1514
  if (!metadata) {
1498
- throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run npx lakebed deploy from this project first.`);
1515
+ throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run ${cliCommand} deploy from this project first.`);
1499
1516
  }
1500
1517
 
1501
- if (metadata.api !== api) {
1518
+ if (!deployApiUrlsMatch(metadata.api, api)) {
1502
1519
  throw new Error(`Saved deploy metadata is for ${metadata.api}, but this command is using ${api}. Pass --api ${metadata.api} to claim it.`);
1503
1520
  }
1504
1521
 
1505
- const claimUrl = claimUrlFromDeployMetadata(metadata);
1522
+ const claimUrl = claimUrlFromDeployMetadata(metadata, api);
1506
1523
  if (!claimUrl) {
1507
1524
  throw new Error("This project does not have a saved claim token. Redeploy to create a new claim URL.");
1508
1525
  }
@@ -1559,9 +1576,9 @@ async function domainsCommand(args) {
1559
1576
  const api = deployApiUrl(args);
1560
1577
  const metadata = await readDeployMetadata(capsuleDir);
1561
1578
  if (!metadata) {
1562
- throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run npx lakebed deploy from this project first.`);
1579
+ throw new Error(`No Lakebed deploy metadata found at ${deployMetadataPath(capsuleDir)}. Run ${cliCommand} deploy from this project first.`);
1563
1580
  }
1564
- if (metadata.api !== api) {
1581
+ if (!deployApiUrlsMatch(metadata.api, api)) {
1565
1582
  throw new Error(`Saved deploy metadata is for ${metadata.api}, but this command is using ${api}. Pass --api ${metadata.api} to use it.`);
1566
1583
  }
1567
1584
  if (!metadata.deployId || !metadata.claimToken) {
@@ -1603,7 +1620,7 @@ async function anonymousServerCommand(args) {
1603
1620
 
1604
1621
  function deployLookupApiUrl(target, args, metadata) {
1605
1622
  if (!hasExplicitOption(args, "--api") && metadata?.api && metadata.deployId === target) {
1606
- return String(metadata.api).replace(/\/+$/g, "");
1623
+ return canonicalDeployApiUrl(metadata.api);
1607
1624
  }
1608
1625
 
1609
1626
  return deployApiUrl(args);
@@ -1841,7 +1858,7 @@ Your role is to build software within this capsule. Lakebed is the runtime, the
1841
1858
  ## Hard rules
1842
1859
 
1843
1860
  - No installing node modules. You can use the built-in APIs. Write TypeScript for anything that is not included.
1844
- - Lakebed CLI should always be run with \`npx lakebed [command]\`. It is not a global. Launch with \`npx\` always.
1861
+ - Lakebed CLI should always be run with \`${cliCommand} [command]\`. It is not a global. Launch with \`npx\` always.
1845
1862
  - All client code goes in the \`client\` directory, and all server code goes in the \`server\` directory. Shared code can go in \`shared\`.
1846
1863
  - Use \`lakebed/server\` only from \`server/*.ts\`.
1847
1864
  - Use \`lakebed/client\` only from \`client/*.tsx\`.
@@ -1855,7 +1872,7 @@ Your role is to build software within this capsule. Lakebed is the runtime, the
1855
1872
  - Read server-only environment variables through \`ctx.env\`; define them in \`.env.lakebed.server\`.
1856
1873
  - Auth can be added with a Google sign-in using \`<SignInWithGoogle />\` or \`signInWithGoogle()\` from \`lakebed/client\`.
1857
1874
  - Keep \`shared/\` free of DOM, Node, env, and Lakebed runtime imports.
1858
- - Environment variables are only available on the server, and must be defined in \`.env.lakebed.server\`. They are not available during build time. If you need build-time environment variables, define them in code and do conditional logic based on them. They will be synced with production on \`npx lakebed deploy\`.
1875
+ - Environment variables are only available on the server, and must be defined in \`.env.lakebed.server\`. They are not available during build time. If you need build-time environment variables, define them in code and do conditional logic based on them. They will be synced with ${LAKEBED_RELEASE_CHANNEL} on \`${cliCommand} deploy\`.
1859
1876
 
1860
1877
  ## Default project structure
1861
1878
 
@@ -1868,21 +1885,21 @@ Your role is to build software within this capsule. Lakebed is the runtime, the
1868
1885
  Run locally:
1869
1886
 
1870
1887
  \`\`\`sh
1871
- npx lakebed dev
1888
+ ${cliCommand} dev
1872
1889
  \`\`\`
1873
1890
 
1874
1891
  Deploy:
1875
1892
 
1876
1893
  \`\`\`sh
1877
- npx lakebed deploy
1894
+ ${cliCommand} deploy
1878
1895
  \`\`\`
1879
1896
 
1880
- Inspect local state while \`npx lakebed dev\` is running:
1897
+ Inspect local state while \`${cliCommand} dev\` is running:
1881
1898
 
1882
1899
  \`\`\`sh
1883
- npx lakebed db list --port 3000
1884
- npx lakebed db dump --port 3000
1885
- npx lakebed logs --port 3000
1900
+ ${cliCommand} db list --port 3000
1901
+ ${cliCommand} db dump --port 3000
1902
+ ${cliCommand} logs --port 3000
1886
1903
  \`\`\`
1887
1904
 
1888
1905
  ## External endpoints
@@ -1902,8 +1919,8 @@ Use \`endpoint({ method, path }, handler)\` from \`lakebed/server\` when the app
1902
1919
  - No file storage.
1903
1920
  - No outbound fetch in anonymous deploys. Claim the deploy before using server-side fetch.
1904
1921
  - Non-empty \`.env.lakebed.server\` files sync only after a deploy is claimed.
1905
- - Local state resets when \`npx lakebed dev\` restarts.
1906
- - All production deploys are on 'lakebed.app'
1922
+ - Local state resets when \`${cliCommand} dev\` restarts.
1923
+ - All ${LAKEBED_RELEASE_CHANNEL} deploys are on '${defaultHostedAppBaseDomain}'
1907
1924
  `;
1908
1925
  }
1909
1926
 
@@ -2091,7 +2108,7 @@ export function cleanTodoText(value: string): string {
2091
2108
  Run this Lakebed capsule:
2092
2109
 
2093
2110
  \`\`\`sh
2094
- npx lakebed dev
2111
+ ${cliCommand} dev
2095
2112
  \`\`\`
2096
2113
 
2097
2114
  The starter app includes two client routes:
@@ -2138,12 +2155,19 @@ async function newCommand(args) {
2138
2155
  const gitStatus = shouldInitGit ? await initializeGitRepository(targetDir) : "Skipped git setup (--no-git).";
2139
2156
  console.log(gitStatus);
2140
2157
  console.log(`
2158
+ Project files:
2159
+ AGENTS.md contains the Lakebed-specific instructions for agents working in this capsule.
2160
+ CLAUDE.md mirrors AGENTS.md for Claude-based workflows.
2161
+
2141
2162
  Next:
2142
2163
  cd ${shellQuote(name)}
2143
- npx lakebed dev
2164
+ ${cliCommand} dev
2165
+
2166
+ Deploy:
2167
+ ${cliCommand} deploy
2144
2168
 
2145
- deploy instantly for free with:
2146
- npx lakebed deploy`);
2169
+ Notice to agents who run this command:
2170
+ make sure to read AGENTS.md before changing files in this capsule.`);
2147
2171
  }
2148
2172
 
2149
2173
  async function initializeGitRepository(targetDir) {
package/src/release.js ADDED
@@ -0,0 +1,3 @@
1
+ export const LAKEBED_RELEASE_CHANNEL = "staging";
2
+ export const LAKEBED_DEPLOY_API_URL = "https://api.staging.lakebed.dev";
3
+ export const LAKEBED_APP_BASE_DOMAIN = "staging.lakebed.app";
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export const LAKEBED_VERSION = "0.0.21";
1
+ export const LAKEBED_VERSION = "0.0.23-staging.26699880384";