Skip to content

feat(marketplace): publish skills/profiles/MCPs from your PC via API token#74

Merged
NagyVikt merged 2 commits into
mainfrom
claude/dashboard-api-marketplace-fnqk21
Jun 24, 2026
Merged

feat(marketplace): publish skills/profiles/MCPs from your PC via API token#74
NagyVikt merged 2 commits into
mainfrom
claude/dashboard-api-marketplace-fnqk21

Conversation

@NagyVikt

Copy link
Copy Markdown
Contributor

What & why

Users could already mint an API token on cuecards.cc (BetterAuth apiKey + the studio API view), but the only thing they could do with it was GET /api/v1/me. The marketplace Publish button was a localStorage-only stub ("will open a registry PR later").

This PR closes the loop: a user gets a token and pushes their skills, cue profiles, and MCPs to the marketplace from their own machine — via the CLI or the studio.

Hosted API (web/)

  • web/lib/db.ts — shared, serverless-safe pg pool singleton (BetterAuth keeps its own).
  • web/lib/market.tsgetMarket() / publishMarket(), Postgres-backed, authenticated through auth.api.getSession so a session cookie OR Authorization: Bearer <api-key> both work (same path as /api/v1/me). Security-minded by design:
    • the install command is derived server-side (cue add <handle>/<name>, cue marketplace install-mcp <name>, …) and never read from the request → a submission can't smuggle curl … | bash into someone's dashboard;
    • every field is length-clamped, names/tags slugged, sourceUrl must be https://;
    • id embeds a per-user suffix and (user_id, type, name) is unique → re-publishing updates your item and can't overwrite another user's;
    • schema is created lazily (no extra migration step).
  • web/api/v1/community.ts — Vercel function: GET (public list), GET ?mine=1 (your items, any status), POST (publish). Kept on a distinct path from the local dashboard's /api/v1/market browse catalog so both coexist.
  • dev-server + check-auth-flow.ts now exercise publish + list end-to-end (the existing auth gate, extended).
  • vite proxy routes /api/v1/community to the auth server in dev.

CLI (src/)

cue marketplace login --token <t>     # verifies, then saves to ~/.config/cue/credentials.json (0600)
cue marketplace whoami                # who am I authenticated as
cue marketplace publish <type> <name> # push a profile / skill / mcp  (--desc --tags --source-url --api)
  • src/lib/cue-credentials.ts — token store + resolution order --token > CUE_API_TOKEN > file; CUE_API_URL/--api point at a different deployment. Unit-tested.

Studio (web/src/)

  • Market view Publish modal now pushes to the hosted API when signed in (falls back to a local draft + sign-in hint otherwise), and the browse list merges the community catalog with "yours" flagging.

Testing

  • bun test src/lib/cue-credentials.test.ts → 5 pass (resolution order, 0600 perms, URL precedence).
  • Root tsc clean for all touched files (one pre-existing unrelated error in pair-suggestions.ts).
  • Web src tsc clean for touched files (one pre-existing unrelated error in studio/components/index.tsx).
  • CLI smoke: publish/whoami error paths verified; marketplace --help updated.
  • The full publish→list flow is covered by web/scripts/check-auth-flow.ts (needs DATABASE_URL + BETTER_AUTH_SECRET to run live).

Notes / follow-ups

  • Items default to status = 'approved' (matches the existing free-signup, no-email-verification posture); the status column is the hook for moderation later without a schema change.
  • Docs: new ## API section in README.md + expanded web/AUTH.md.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 2 commits June 22, 2026 09:57
…token

Adds the missing "push to marketplace" path so a user can mint an API
token on cuecards.cc and publish from their own machine.

Hosted API (web/):
- web/lib/db.ts: shared pg pool (singleton, serverless-safe).
- web/lib/market.ts: getMarket()/publishMarket(), Postgres-backed,
  authenticated via auth.api.getSession (session cookie OR Bearer
  api-key). Install commands are derived server-side (never trusted from
  the client), every field is clamped/slugged, ids carry a per-user
  suffix and (user_id, type, name) is unique so re-publishing updates
  your own item and can't overwrite another user's. Schema is created
  lazily.
- web/api/v1/community.ts: Vercel function (GET list / GET ?mine / POST).
- dev-server + check-auth-flow now cover publish + list (the e2e gate).
- vite proxy routes /api/v1/community to the auth server in dev.

CLI (src/):
- cue marketplace login | whoami | publish <type> <name>.
- src/lib/cue-credentials.ts: token store (~/.config/cue/credentials.json,
  0600), resolution order flag > CUE_API_TOKEN > file; CUE_API_URL /
  --api override the endpoint. Unit-tested.

Studio (web/src/):
- Market view: Publish modal now pushes to the hosted API when signed in
  (falls back to a local draft otherwise), and the browse list merges the
  community catalog with "yours" flagging.

Docs: README "## API" section + updated web/AUTH.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153P8DbBQg1yPQYhBv8JiWg
The pinned gitlink (4274beae) was force-pushed away on opencue/skills, so
actions/checkout failed fetching the submodule on every job — repo-wide,
before tests/lint ran. Bump to a452e5d (current soul-main head) so CI can
fetch submodules and actually run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153P8DbBQg1yPQYhBv8JiWg
@NagyVikt NagyVikt marked this pull request as ready for review June 24, 2026 09:02
@NagyVikt NagyVikt merged commit 4b95bbf into main Jun 24, 2026
1 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants