Observed since 20 Oct, 21:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
88eggs-cli
CLI for 88eggs -- sign in and drive 88eggs-backend from the command line.
CLI for 88eggs. Signs in with your Google account (the same one you'd
use on the 88eggs frontend) and talks to 88eggs-backend on your
behalf. (88eggs-frontend/88eggs-backend are private repos, not
linked here.)
This exists so 88eggs-skills
has something to drive, mirroring how vercel-labs/agent-skills' deploy
skill drives the vercel CLI and supabase/agent-skills drives the
supabase CLI — a skill shells out to 88eggs, 88eggs owns its own
login, and no skill ever handles a raw token itself.
Published on npm as 88eggs-cli:
npm install -g 88eggs-cli
Or from source, for local development on the CLI itself:
pnpm install
pnpm build
npm link # makes the `88eggs` command available globally
88eggs login # sign in with Google via your browser
88eggs logout # sign out, remove stored credentials
88eggs whoami # show the currently signed-in account
88eggs projects list # list your projects (--scope mine|shared|all)
88eggs assets list --project <projectId> # list a project's assets (--name, --type, --page, --limit)
88eggs assets show <assetId> # one item, incl. a signed URL
88eggs assets move <assetId> <projectId> # move to a different project
88eggs tasks list # the task catalog
88eggs tasks show <slug> # one task's detail + parameter spec
88eggs tasks start <slug> [--project <projectId>] [--name <name>] [--param key=value ...]
# start a task run; unset parameters use the task's
# own defaults; omit --project to use your oldest one;
# omit --name to get "<task name> <random word>"
88eggs task-runs list [--project <projectId>] # list task runs (every accessible project, or one)
# (--page, --limit)
88eggs task-runs status <taskRunId> # poll a task run's status (model, cost, outputs, result asset)
88eggs pipelines list [--project <projectId>] # the pipeline catalog
88eggs pipelines show <slug> # one pipeline's detail + parameter spec
88eggs pipelines start <slug> [--project <projectId>] [--name <name>] [--param key=value ...]
# start a pipeline run; unset parameters use the
# pipeline's own defaults
88eggs pipeline-runs list [--project <projectId>]
# list pipeline runs (--page, --limit)
88eggs pipeline-runs status <pipelineRunId> # full state: status, per-step timeline, review gates
88eggs pipeline-runs review <pipelineRunId> --approve [--field key=value ...]
88eggs pipeline-runs review <pipelineRunId> --reject
# work the current review gate (approve, optionally
# overriding the gate's prefilled fields; reject re-rolls)
88eggs pipeline-runs retry <pipelineRunId> # resume a failed pipeline run from its failed step
88eggs events types # the known event types (the live catalog)
88eggs events list [--project <projectId>] # list events (every accessible project, or one)
# (--type <eventTypeKey>, --page, --limit)
88eggs apps catalog # the installable app catalog (App Store)
88eggs apps install <slug> --project <projectId> [--name <name>]
# install a catalog app into a project
88eggs apps list --project <projectId> # a project's installed apps
88eggs apps show <appId> # one installed app
88eggs apps uninstall <appId> # uninstall (archive) an app; its pages are kept
88eggs apps pages <appId> [--archived] # an installed app's pages
88eggs data-tables list [--project <projectId>] [--archived]
# data tables (all accessible projects, or one)
88eggs data-tables show <tableId> # one table's schema (columns)
88eggs data-tables create <name> [--project <projectId>] [--column key:type[:label] ...]
# create a table; column type is
# text|textarea|number|boolean|asset; Id + status
# columns are built in
88eggs data-tables update <tableId> [--name <name>] [--column key:type[:label] ...]
# [--status-option <value> ...] [--archive|--restore]
88eggs data-tables publish <tableId> [--name <name>]
# publish the schema to Templates (rows not shared)
88eggs data-tables rows list <tableId> [--column <key> --value <value>] [--page --limit]
88eggs data-tables rows show <tableId> <rowId>
88eggs data-tables rows add <tableId> [--cell key=value ...] [--status <status>]
88eggs data-tables rows update <tableId> <rowId> [--cell key=value ...] [--status <status>]
88eggs data-tables rows delete <tableId> <rowId>
88eggs data-tables delete <tableId> # delete a table (rows cascade)
88eggs notes list --project <projectId> [--roots | --parent <path>] [--archived|--all] [--q <text>]
# a project's notes (flat, or one level of the tree)
88eggs notes show <noteId> # one note (metadata + markdown content)
88eggs notes by-path --project <projectId> --path <slug>
# resolve one note by its path slug
88eggs notes create <name> --project <projectId> --path <slug> [--content <md>|--content-file <file>] [--parent <path>]
# path is a unique slug: ^[a-z0-9_-]+$; --parent nests it
88eggs notes update <noteId> [--name] [--path] [--content|--content-file] [--parent <path>|--top-level] [--archive|--restore]
# rename re-links children; --archive cascades to descendants
88eggs projects show <projectId> # detail + your permissions
88eggs projects create <name> [--description <text>] [--team <teamId>]
88eggs projects update <projectId> [--name] [--description] [--team]
88eggs projects delete <projectId> # 409 if it still has assets
88eggs pipelines clone <slug> # duplicate within its project
88eggs pipelines publish <slug> [--name] [--description]
88eggs pipelines archive <slug> | restore <slug>
88eggs schedules list [--project <projectId>]
88eggs schedules show <scheduleId>
88eggs schedules create --definition <slug> --cron "<expr>" --name <name>
# [--timezone <tz>] [--project <id>] [--param k=v ...] [--disabled]
88eggs schedules update <scheduleId> [--name] [--cron] [--timezone] [--enable|--disable] [--param k=v ...]
88eggs schedules delete <scheduleId>
88eggs templates list [--type <type>] [--q <query>]
88eggs templates show <templateId>
88eggs templates clone <templateId> [--project <projectId>] [--name <name>]
88eggs task-inputs list [--project <projectId>] # saved input presets
88eggs task-inputs show <templateId>
88eggs task-inputs save <taskRunId> --name <name> [--description <text>]
88eggs teams list | show <teamId> | create <name> | update <teamId> --name <name> | delete <teamId>
88eggs teams members <teamId> | remove-member <teamId> <userId>
88eggs teams invitations <teamId> | invite <teamId> <email> | revoke-invitation <teamId> <invitationId>
88eggs invitations accept <invitationId> | decline <invitationId>
88eggs partner-profiles list | show <id> | create --name --slug --email | tasks <id>
88eggs partners show <slug> | tasks <slug>
88eggs apps page create <appId> --title <title> [--slug <slug>]
88eggs apps page show <appId> <pageId>
88eggs apps page update <appId> <pageId> [--title] [--slug] [--archive|--restore]
88eggs apps public-page <slug> # a public page's metadata
88eggs events show <eventId> # one event's detail
88eggs models # the supported-model catalog
88eggs profile show | update [--name] [--description]
88eggs messages list | read <messageId>
Install 88eggs-skills
to let an agent (Claude Code, etc.) drive this CLI on your behalf:
npx skills add ptk-studio/88eggs-skills --skill list-projects
The skill checks 88eggs whoami first and only runs 88eggs login
after asking you — since that opens your browser for a real Google
sign-in — so 88eggs-cli still needs to be installed and on your
PATH (see Install above) before the skill can do anything.
88eggs login runs a real OAuth flow against the same Supabase project
88eggs-backend/88eggs-frontend already use — there's no separate
88eggs-specific auth server, and no new backend feature was needed for
this to work:
/auth/v1/authorize?provider=google
(the same endpoint the frontend's "Continue with Google" button
hits), with redirect_to pointed at a local callback server this CLI
starts on a fixed port (127.0.0.1:51820).~/.88eggs/credentials.json (mode 600)
— never printed, never handled by anything other than this file.Every other command reads that file, refreshing the access token via
the stored refresh token when it's near expiry, and calls
88eggs-backend with it as a normal Authorization: Bearer header —
exactly what the frontend already sends, just from a CLI instead of a
browser tab. requireUser() on the backend doesn't know or care which
one it came from.
Note on the redirect URL: this worked against production without
adding http://127.0.0.1:51820/callback to Supabase's redirect-URL
allowlist first — empirically, Supabase appears to treat loopback
(127.0.0.1/localhost) redirects as implicitly trusted for this kind
of installed-app flow (matching the general pattern in
RFC 8252 for native/CLI OAuth
clients), rather than requiring an exact allowlist entry the way a
hosted redirect URL would. Flagging this as observed behavior, not
something confirmed against Supabase's own docs — if a fresh project
ever rejects the redirect, add http://127.0.0.1:51820/callback to
Authentication → URL Configuration → Redirect URLs in the Supabase
dashboard.
Point the CLI at a local Supabase + local 88eggs-backend instead of
production. Env vars are prefixed EGGS_, not 88EGGS_ — shell env var
names can't start with a digit:
EGGS_SUPABASE_URL=http://127.0.0.1:54321 \
EGGS_SUPABASE_PUBLISHABLE_KEY=<local anon/publishable key> \
EGGS_API_URL=http://localhost:3000 \
88eggs login
Local Supabase has Google sign-in disabled by default
(supabase/config.toml's [auth.external.google] block) — enable it
with real (or test) OAuth credentials first, same as any other local
Google sign-in testing against 88eggs-backend.
pnpm test # unit tests (credentials storage, token refresh logic)
pnpm typecheck
pnpm lint
The OAuth round-trip itself isn't unit-tested (there's no meaningful way
to fake a real Google consent) — verified manually via 88eggs login
against production, confirming the credentials file is written
correctly and 88eggs projects list successfully calls the real API
afterward.
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
openEnvironment{
"local_name": "open",
"alias": false,
"peer_metadata": null
} | ^10.1.0 | runtime |
commanderEnvironment{
"local_name": "commander",
"alias": false,
"peer_metadata": null
} | ^12.1.0 | runtime |
@supabase/supabase-jsEnvironment{
"local_name": "@supabase/supabase-js",
"alias": false,
"peer_metadata": null
} | ^2.58.0 | runtime |
tsxEnvironment{
"local_name": "tsx",
"alias": false,
"peer_metadata": null
} | ^4.19.2 | development |
eslintEnvironment{
"local_name": "eslint",
"alias": false,
"peer_metadata": null
} | ^9.17.0 | development |
vitestEnvironment{
"local_name": "vitest",
"alias": false,
"peer_metadata": null
} | ^2.1.8 | development |
@eslint/jsEnvironment{
"local_name": "@eslint/js",
"alias": false,
"peer_metadata": null
} | ^10.0.1 | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5.7.2 | development |
@types/nodeEnvironment{
"local_name": "@types/node",
"alias": false,
"peer_metadata": null
} | ^22.10.2 | development |
typescript-eslintEnvironment{
"local_name": "typescript-eslint",
"alias": false,
"peer_metadata": null
} | ^8.62.1 | development |
Source distribution
{
"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
}Observed since 20 Oct, 21:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:aca2dfaeeb32262efca12dd8aacafc77724bfc773501913fcfffee337f2bd31b