{"_id":"88eggs-cli","_rev":"6-8877880d1ba7762f98dd1c2d898c05f8","name":"88eggs-cli","dist-tags":{"latest":"0.9.0"},"versions":{"0.1.0":{"name":"88eggs-cli","version":"0.1.0","license":"MIT","_id":"88eggs-cli@0.1.0","maintainers":[{"name":"nangkon","email":"nangkon@gmail.com"}],"homepage":"https://github.com/ptk-studio/88eggs-cli#readme","bugs":{"url":"https://github.com/ptk-studio/88eggs-cli/issues"},"bin":{"88eggs":"dist/index.js"},"dist":{"shasum":"33f1b43e01ad3a9dfdd3cacee66f1ccb7e72bad5","tarball":"https://registry.npmjs.org/88eggs-cli/-/88eggs-cli-0.1.0.tgz","fileCount":12,"integrity":"sha512-fCtLPuN1Fao60rJ8UBBpH3dXwmGSUp8604zKh7bUEdVHwQGwYZfTIw04K/Tnh66BNFKngLD9HXiHGCGjSNodwg==","signatures":[{"sig":"MEQCIDA1QAu8iJtLBZm9+v+Hgxe0lmVgoH7rsjr5Lbv0kSdDAiBw4PMhGyOq9FeR76hZ3Me/gM2TiKHNp0ceQaXRAwZrlQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18803},"type":"module","engines":{"node":">=20"},"gitHead":"809014e0fbfaf7077d46457252b4865cbe64e5f3","scripts":{"dev":"tsx src/index.ts","lint":"eslint .","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"nangkon","email":"nangkon@gmail.com"},"repository":{"url":"git+https://github.com/ptk-studio/88eggs-cli.git","type":"git"},"_npmVersion":"11.17.0","description":"CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.","directories":{},"_nodeVersion":"26.4.0","dependencies":{"open":"^10.1.0","commander":"^12.1.0","@supabase/supabase-js":"^2.58.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","eslint":"^9.17.0","vitest":"^2.1.8","@eslint/js":"^10.0.1","typescript":"^5.7.2","@types/node":"^22.10.2","typescript-eslint":"^8.62.1"},"_npmOperationalInternal":{"tmp":"tmp/88eggs-cli_0.1.0_1783399927598_0.07789087525593441","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"88eggs-cli","version":"0.4.0","license":"MIT","_id":"88eggs-cli@0.4.0","maintainers":[{"name":"nangkon","email":"nangkon@gmail.com"}],"homepage":"https://github.com/ptk-studio/88eggs-cli#readme","bugs":{"url":"https://github.com/ptk-studio/88eggs-cli/issues"},"bin":{"88eggs":"dist/index.js"},"dist":{"shasum":"849e2720e44a900085ac8ad21a5c4f387b894074","tarball":"https://registry.npmjs.org/88eggs-cli/-/88eggs-cli-0.4.0.tgz","fileCount":17,"integrity":"sha512-lYo9qcbW/6R08xVEOEuhtFmPSRYUu4OKq3yOhuDDT1zRAKeoPJnVRmt7PQPpc2lWISrb37ty/FjszAFDhV1iNg==","signatures":[{"sig":"MEQCIGpuX23mg8GalAyqJZyAHG8aC+65+e6xVKkjJtIIUd6TAiB/S9WVDJ++59LYlEbywsBQKCftBu2537mrEYM1JweZlg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":44784},"type":"module","engines":{"node":">=20"},"gitHead":"cec8a274d0eccd0561ddacfc6bf2c58b6265ba8a","scripts":{"dev":"tsx src/index.ts","lint":"eslint .","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"nangkon","email":"nangkon@gmail.com"},"repository":{"url":"git+https://github.com/ptk-studio/88eggs-cli.git","type":"git"},"_npmVersion":"11.16.0","description":"CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"open":"^10.1.0","commander":"^12.1.0","@supabase/supabase-js":"^2.58.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","eslint":"^9.17.0","vitest":"^2.1.8","@eslint/js":"^10.0.1","typescript":"^5.7.2","@types/node":"^22.10.2","typescript-eslint":"^8.62.1"},"_npmOperationalInternal":{"tmp":"tmp/88eggs-cli_0.4.0_1783894531364_0.394010090968528","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"88eggs-cli","version":"0.6.0","license":"MIT","_id":"88eggs-cli@0.6.0","maintainers":[{"name":"nangkon","email":"nangkon@gmail.com"}],"homepage":"https://github.com/ptk-studio/88eggs-cli#readme","bugs":{"url":"https://github.com/ptk-studio/88eggs-cli/issues"},"bin":{"88eggs":"dist/index.js"},"dist":{"shasum":"17675ac2e96d84484df4c8fdf42b89f6d27ffb7d","tarball":"https://registry.npmjs.org/88eggs-cli/-/88eggs-cli-0.6.0.tgz","fileCount":21,"integrity":"sha512-PDRpa9BYMWKOFLqmcybP1bW3Honk3WV5Wd/wZ29NOlTJS2SPs0LxtHkvxPO1v8XrYmH9Pd6C/X0nDa1kuGXcfA==","signatures":[{"sig":"MEYCIQC2z0X3/hXhGsRBrgwvMlVeqvKeXjzaTzr6aSH37O+jfAIhALKIulvfTOgygExzjqepyjOVJty04ylU6BokOdK+hs9W","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74908},"type":"module","engines":{"node":">=20"},"gitHead":"78f9e4ba2ddab8ba5775a2f950b8cc9baf5798bb","scripts":{"dev":"tsx src/index.ts","lint":"eslint .","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"nangkon","email":"nangkon@gmail.com"},"repository":{"url":"git+https://github.com/ptk-studio/88eggs-cli.git","type":"git"},"_npmVersion":"11.16.0","description":"CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"open":"^10.1.0","commander":"^12.1.0","@supabase/supabase-js":"^2.58.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","eslint":"^9.17.0","vitest":"^2.1.8","@eslint/js":"^10.0.1","typescript":"^5.7.2","@types/node":"^22.10.2","typescript-eslint":"^8.62.1"},"_npmOperationalInternal":{"tmp":"tmp/88eggs-cli_0.6.0_1784383671625_0.5553397570086749","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"88eggs-cli","version":"0.7.0","license":"MIT","_id":"88eggs-cli@0.7.0","maintainers":[{"name":"nangkon","email":"nangkon@gmail.com"}],"homepage":"https://github.com/ptk-studio/88eggs-cli#readme","bugs":{"url":"https://github.com/ptk-studio/88eggs-cli/issues"},"bin":{"88eggs":"dist/index.js"},"dist":{"shasum":"9c157c2c050d6d68d61ccb17d029f562ccf7a965","tarball":"https://registry.npmjs.org/88eggs-cli/-/88eggs-cli-0.7.0.tgz","fileCount":29,"integrity":"sha512-O8Lu5buDIrYjcL876dirIwvCIG36CG5vvxx78U9tCRXJq2fbqz4d8jI26/EhbIoIPcXmb4RVmbzxrBMDlkZkjA==","signatures":[{"sig":"MEUCIDoxasn2EoPGt60EgAFWeeYx78j1krT7U5VeTP3ZYfjMAiEAoqaKKIAQlrj8/gADpxcBq8y96S1LqzA9Td6rUk2p72M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":111475},"type":"module","engines":{"node":">=20"},"gitHead":"841ccad7151171f051ac033b37a4956de556b0a8","scripts":{"dev":"tsx src/index.ts","lint":"eslint .","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"nangkon","email":"nangkon@gmail.com"},"repository":{"url":"git+https://github.com/ptk-studio/88eggs-cli.git","type":"git"},"_npmVersion":"11.16.0","description":"CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"open":"^10.1.0","commander":"^12.1.0","@supabase/supabase-js":"^2.58.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","eslint":"^9.17.0","vitest":"^2.1.8","@eslint/js":"^10.0.1","typescript":"^5.7.2","@types/node":"^22.10.2","typescript-eslint":"^8.62.1"},"_npmOperationalInternal":{"tmp":"tmp/88eggs-cli_0.7.0_1784394278122_0.27350370215355113","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"88eggs-cli","version":"0.8.0","license":"MIT","_id":"88eggs-cli@0.8.0","maintainers":[{"name":"nangkon","email":"nangkon@gmail.com"}],"homepage":"https://github.com/ptk-studio/88eggs-cli#readme","bugs":{"url":"https://github.com/ptk-studio/88eggs-cli/issues"},"bin":{"88eggs":"dist/index.js"},"dist":{"shasum":"d87901be69afb1ae034c0162bd36a39e05e029e9","tarball":"https://registry.npmjs.org/88eggs-cli/-/88eggs-cli-0.8.0.tgz","fileCount":30,"integrity":"sha512-bFL+3qbZtei4ZXZObbuX9kKCfu91nPqaK62/yf3IMDQegS3xxdytXwU/ZFsTtQEAbKgDOQCKJx6uQ27X+Or36g==","signatures":[{"sig":"MEYCIQDUoYpEIgM9Y2gg94ovEnrFJ/sN8LwwYu0uCKxlJKGhIgIhAPiNdKSY0W0ZUwUklw3Jc3BC7G7a2xfdxKfxIdGwhObV","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":110712},"type":"module","engines":{"node":">=20"},"gitHead":"0f367bf3df91897655c5bdbf7df72282ae78fe0e","scripts":{"dev":"tsx src/index.ts","lint":"eslint .","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"nangkon","email":"nangkon@gmail.com"},"repository":{"url":"git+https://github.com/ptk-studio/88eggs-cli.git","type":"git"},"_npmVersion":"11.16.0","description":"CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.","directories":{},"_nodeVersion":"24.18.0","dependencies":{"open":"^10.1.0","commander":"^12.1.0","@supabase/supabase-js":"^2.58.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","eslint":"^9.17.0","vitest":"^2.1.8","@eslint/js":"^10.0.1","typescript":"^5.7.2","@types/node":"^22.10.2","typescript-eslint":"^8.62.1"},"_npmOperationalInternal":{"tmp":"tmp/88eggs-cli_0.8.0_1784827898428_0.9075205352873588","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"88eggs-cli","version":"0.9.0","description":"CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/ptk-studio/88eggs-cli.git"},"homepage":"https://github.com/ptk-studio/88eggs-cli#readme","bugs":{"url":"https://github.com/ptk-studio/88eggs-cli/issues"},"type":"module","bin":{"88eggs":"dist/index.js"},"scripts":{"build":"tsc","dev":"tsx src/index.ts","lint":"eslint .","test":"vitest run","typecheck":"tsc --noEmit"},"dependencies":{"@supabase/supabase-js":"^2.58.0","commander":"^12.1.0","open":"^10.1.0"},"devDependencies":{"@eslint/js":"^10.0.1","@types/node":"^22.10.2","eslint":"^9.17.0","tsx":"^4.19.2","typescript":"^5.7.2","typescript-eslint":"^8.62.1","vitest":"^2.1.8"},"engines":{"node":">=20"},"gitHead":"a4f3d0d5c6836611f937a99e9d60b91986a9ed09","_id":"88eggs-cli@0.9.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-3OAO3C2ZSS2gO96wQ9S8z0FtO1y3ZN9FoL2ha7Sry57M0joHfm8MJYLZi4perofQwpU/pWbckRAYHMkFccElhg==","shasum":"caa659a5b00ee4cc2c5f2207d82263bd2d28e54e","tarball":"https://registry.npmjs.org/88eggs-cli/-/88eggs-cli-0.9.0.tgz","fileCount":28,"unpackedSize":108330,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGWgzRZszbOP+mpXldYPJKM/cHONwUrH0Qaur2+eXZKaAiAXQbEHgXc0oMn4oJSCvNoyzeImEpAL+/FUoa7LVYP2WQ=="}]},"_npmUser":{"name":"nangkon","email":"nangkon@gmail.com"},"directories":{},"maintainers":[{"name":"nangkon","email":"nangkon@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/88eggs-cli_0.9.0_1784924841437_0.8545935892005554"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-07T04:52:07.538Z","modified":"2026-07-24T20:27:21.744Z","0.1.0":"2026-07-07T04:52:07.758Z","0.4.0":"2026-07-12T22:15:31.499Z","0.6.0":"2026-07-18T14:07:51.768Z","0.7.0":"2026-07-18T17:04:38.271Z","0.8.0":"2026-07-23T17:31:38.573Z","0.9.0":"2026-07-24T20:27:21.576Z"},"bugs":{"url":"https://github.com/ptk-studio/88eggs-cli/issues"},"license":"MIT","homepage":"https://github.com/ptk-studio/88eggs-cli#readme","repository":{"type":"git","url":"git+https://github.com/ptk-studio/88eggs-cli.git"},"description":"CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.","maintainers":[{"name":"nangkon","email":"nangkon@gmail.com"}],"readme":"# 88eggs-cli\n\nCLI for 88eggs. Signs in with your Google account (the same one you'd\nuse on the 88eggs frontend) and talks to `88eggs-backend` on your\nbehalf. (`88eggs-frontend`/`88eggs-backend` are private repos, not\nlinked here.)\n\nThis exists so [`88eggs-skills`](https://github.com/ptk-studio/88eggs-skills)\nhas something to drive, mirroring how `vercel-labs/agent-skills`' deploy\nskill drives the `vercel` CLI and `supabase/agent-skills` drives the\n`supabase` CLI — a skill shells out to `88eggs`, `88eggs` owns its own\nlogin, and no skill ever handles a raw token itself.\n\n## Install\n\nPublished on npm as [`88eggs-cli`](https://www.npmjs.com/package/88eggs-cli):\n\n```bash\nnpm install -g 88eggs-cli\n```\n\nOr from source, for local development on the CLI itself:\n\n```bash\npnpm install\npnpm build\nnpm link   # makes the `88eggs` command available globally\n```\n\n## Commands\n\n```bash\n88eggs login           # sign in with Google via your browser\n88eggs logout          # sign out, remove stored credentials\n88eggs whoami           # show the currently signed-in account\n88eggs projects list    # list your projects (--scope mine|shared|all)\n\n88eggs assets list --project <projectId>   # list a project's assets (--name, --type, --page, --limit)\n88eggs assets show <assetId>               # one item, incl. a signed URL\n88eggs assets move <assetId> <projectId>   # move to a different project\n\n88eggs tasks list                          # the task catalog\n88eggs tasks show <slug>                    # one task's detail + parameter spec\n88eggs tasks start <slug> [--project <projectId>] [--name <name>] [--param key=value ...]\n                                            # start a task run; unset parameters use the task's\n                                            # own defaults; omit --project to use your oldest one;\n                                            # omit --name to get \"<task name> <random word>\"\n88eggs task-runs list [--project <projectId>]  # list task runs (every accessible project, or one)\n                                            # (--page, --limit)\n88eggs task-runs status <taskRunId>        # poll a task run's status (model, cost, outputs, result asset)\n\n88eggs pipelines list [--project <projectId>]   # the pipeline catalog\n88eggs pipelines show <slug>               # one pipeline's detail + parameter spec\n88eggs pipelines start <slug> [--project <projectId>] [--name <name>] [--param key=value ...]\n                                            # start a pipeline run; unset parameters use the\n                                            # pipeline's own defaults\n88eggs pipeline-runs list [--project <projectId>]\n                                            # list pipeline runs (--page, --limit)\n88eggs pipeline-runs status <pipelineRunId>  # full state: status, per-step timeline, review gates\n88eggs pipeline-runs review <pipelineRunId> --approve [--field key=value ...]\n88eggs pipeline-runs review <pipelineRunId> --reject\n                                            # work the current review gate (approve, optionally\n                                            # overriding the gate's prefilled fields; reject re-rolls)\n88eggs pipeline-runs retry <pipelineRunId>   # resume a failed pipeline run from its failed step\n\n88eggs events types                        # the known event types (the live catalog)\n88eggs events list [--project <projectId>] # list events (every accessible project, or one)\n                                            # (--type <eventTypeKey>, --page, --limit)\n\n88eggs apps catalog                        # the installable app catalog (App Store)\n88eggs apps install <slug> --project <projectId> [--name <name>]\n                                            # install a catalog app into a project\n88eggs apps list --project <projectId>     # a project's installed apps\n88eggs apps show <appId>                    # one installed app\n88eggs apps uninstall <appId>               # uninstall (archive) an app; its pages are kept\n88eggs apps pages <appId> [--archived]      # an installed app's pages\n\n88eggs data-tables list [--project <projectId>] [--archived]\n                                            # data tables (all accessible projects, or one)\n88eggs data-tables show <tableId>          # one table's schema (columns)\n88eggs data-tables create <name> [--project <projectId>] [--column key:type[:label] ...]\n                                            # create a table; column type is\n                                            # text|textarea|number|boolean|asset; Id + status\n                                            # columns are built in\n88eggs data-tables update <tableId> [--name <name>] [--column key:type[:label] ...]\n                                            # [--status-option <value> ...] [--archive|--restore]\n88eggs data-tables publish <tableId> [--name <name>]\n                                            # publish the schema to Templates (rows not shared)\n88eggs data-tables rows list <tableId> [--column <key> --value <value>] [--page --limit]\n88eggs data-tables rows show <tableId> <rowId>\n88eggs data-tables rows add <tableId> [--cell key=value ...] [--status <status>]\n88eggs data-tables rows update <tableId> <rowId> [--cell key=value ...] [--status <status>]\n88eggs data-tables rows delete <tableId> <rowId>\n88eggs data-tables delete <tableId>        # delete a table (rows cascade)\n\n88eggs notes list --project <projectId> [--roots | --parent <path>] [--archived|--all] [--q <text>]\n                                            # a project's notes (flat, or one level of the tree)\n88eggs notes show <noteId>                  # one note (metadata + markdown content)\n88eggs notes by-path --project <projectId> --path <slug>\n                                            # resolve one note by its path slug\n88eggs notes create <name> --project <projectId> --path <slug> [--content <md>|--content-file <file>] [--parent <path>]\n                                            # path is a unique slug: ^[a-z0-9_-]+$; --parent nests it\n88eggs notes update <noteId> [--name] [--path] [--content|--content-file] [--parent <path>|--top-level] [--archive|--restore]\n                                            # rename re-links children; --archive cascades to descendants\n\n88eggs projects show <projectId>           # detail + your permissions\n88eggs projects create <name> [--description <text>] [--team <teamId>]\n88eggs projects update <projectId> [--name] [--description] [--team]\n88eggs projects delete <projectId>         # 409 if it still has assets\n\n88eggs pipelines clone <slug>              # duplicate within its project\n88eggs pipelines publish <slug> [--name] [--description]\n88eggs pipelines archive <slug> | restore <slug>\n\n88eggs schedules list [--project <projectId>]\n88eggs schedules show <scheduleId>\n88eggs schedules create --definition <slug> --cron \"<expr>\" --name <name>\n                                            # [--timezone <tz>] [--project <id>] [--param k=v ...] [--disabled]\n88eggs schedules update <scheduleId> [--name] [--cron] [--timezone] [--enable|--disable] [--param k=v ...]\n88eggs schedules delete <scheduleId>\n\n88eggs templates list [--type <type>] [--q <query>]\n88eggs templates show <templateId>\n88eggs templates clone <templateId> [--project <projectId>] [--name <name>]\n\n88eggs task-inputs list [--project <projectId>]  # saved input presets\n88eggs task-inputs show <templateId>\n88eggs task-inputs save <taskRunId> --name <name> [--description <text>]\n\n88eggs teams list | show <teamId> | create <name> | update <teamId> --name <name> | delete <teamId>\n88eggs teams members <teamId> | remove-member <teamId> <userId>\n88eggs teams invitations <teamId> | invite <teamId> <email> | revoke-invitation <teamId> <invitationId>\n88eggs invitations accept <invitationId> | decline <invitationId>\n\n88eggs partner-profiles list | show <id> | create --name --slug --email | tasks <id>\n88eggs partners show <slug> | tasks <slug>\n\n88eggs apps page create <appId> --title <title> [--slug <slug>]\n88eggs apps page show <appId> <pageId>\n88eggs apps page update <appId> <pageId> [--title] [--slug] [--archive|--restore]\n88eggs apps public-page <slug>             # a public page's metadata\n\n88eggs events show <eventId>               # one event's detail\n88eggs models                              # the supported-model catalog\n88eggs profile show | update [--name] [--description]\n88eggs messages list | read <messageId>\n```\n\n## Using this with an agent\n\nInstall [`88eggs-skills`](https://github.com/ptk-studio/88eggs-skills)\nto let an agent (Claude Code, etc.) drive this CLI on your behalf:\n\n```bash\nnpx skills add ptk-studio/88eggs-skills --skill list-projects\n```\n\nThe skill checks `88eggs whoami` first and only runs `88eggs login`\nafter asking you — since that opens your browser for a real Google\nsign-in — so `88eggs-cli` still needs to be installed and on your\n`PATH` (see **Install** above) before the skill can do anything.\n\n## How auth works\n\n`88eggs login` runs a real OAuth flow against the same Supabase project\n`88eggs-backend`/`88eggs-frontend` already use — there's no separate\n88eggs-specific auth server, and no new backend feature was needed for\nthis to work:\n\n1. Opens your browser to Supabase's `/auth/v1/authorize?provider=google`\n   (the same endpoint the frontend's \"Continue with Google\" button\n   hits), with `redirect_to` pointed at a local callback server this CLI\n   starts on a fixed port (`127.0.0.1:51820`).\n2. You approve in the browser (or, if already signed in and previously\n   consented, this happens instantly with no visible prompt).\n3. Supabase redirects back to the local server with an authorization\n   code; the CLI exchanges it for a real session (access + refresh\n   token) via Supabase's PKCE flow.\n4. The session is written to `~/.88eggs/credentials.json` (mode `600`)\n   — never printed, never handled by anything other than this file.\n\nEvery other command reads that file, refreshing the access token via\nthe stored refresh token when it's near expiry, and calls\n`88eggs-backend` with it as a normal `Authorization: Bearer` header —\nexactly what the frontend already sends, just from a CLI instead of a\nbrowser tab. `requireUser()` on the backend doesn't know or care which\none it came from.\n\n**Note on the redirect URL**: this worked against production without\nadding `http://127.0.0.1:51820/callback` to Supabase's redirect-URL\nallowlist first — empirically, Supabase appears to treat loopback\n(`127.0.0.1`/`localhost`) redirects as implicitly trusted for this kind\nof installed-app flow (matching the general pattern in\n[RFC 8252](https://www.rfc-editor.org/rfc/rfc8252) for native/CLI OAuth\nclients), rather than requiring an exact allowlist entry the way a\nhosted redirect URL would. Flagging this as observed behavior, not\nsomething confirmed against Supabase's own docs — if a fresh project\never rejects the redirect, add `http://127.0.0.1:51820/callback` to\n**Authentication → URL Configuration → Redirect URLs** in the Supabase\ndashboard.\n\n## Local development\n\nPoint the CLI at a local Supabase + local `88eggs-backend` instead of\nproduction. Env vars are prefixed `EGGS_`, not `88EGGS_` — shell env var\nnames can't start with a digit:\n\n```bash\nEGGS_SUPABASE_URL=http://127.0.0.1:54321 \\\nEGGS_SUPABASE_PUBLISHABLE_KEY=<local anon/publishable key> \\\nEGGS_API_URL=http://localhost:3000 \\\n88eggs login\n```\n\nLocal Supabase has Google sign-in **disabled by default**\n(`supabase/config.toml`'s `[auth.external.google]` block) — enable it\nwith real (or test) OAuth credentials first, same as any other local\nGoogle sign-in testing against `88eggs-backend`.\n\n## Testing\n\n```bash\npnpm test        # unit tests (credentials storage, token refresh logic)\npnpm typecheck\npnpm lint\n```\n\nThe OAuth round-trip itself isn't unit-tested (there's no meaningful way\nto fake a real Google consent) — verified manually via `88eggs login`\nagainst production, confirming the credentials file is written\ncorrectly and `88eggs projects list` successfully calls the real API\nafterward.\n","readmeFilename":"README.md"}