Skip to content

Make user API keys first-class in me apikey#107

Merged
jgpruitt merged 3 commits into
mainfrom
jgpruitt/me-apikey
Jun 25, 2026
Merged

Make user API keys first-class in me apikey#107
jgpruitt merged 3 commits into
mainfrom
jgpruitt/me-apikey

Conversation

@jgpruitt

Copy link
Copy Markdown
Collaborator

Problem

me apikey create was designed for agents only. We later allowed users to mint personal access tokens (PATs) via --self, but the command structure was broken for that case:

  • Positionals were [agent] [name] with a guard if (opts.self && agent) → "Pass an agent or --self, not both.", so under --self the first positional parsed as agent and was rejected — you could never name a --self key. It always fell back to cli-<YYYY-MM-DD>.
  • Two PATs minted the same day collided on the DB constraint unique (member_id, name)23505A record with that name already exists.
  • me apikey list required <agent>, so there was no way to list your own PATs.

Reported by Matty: me apikey create --self twice (once per space) → second fails. (Keys are global per-principal, not per-space; the separate --space-per-MCP-server config gap is its own ticket.)

Change

Invert the model so user keys are the default and agents opt in:

me apikey create [name] [--agent <agent>] [--expires <ts>]   # no --agent → a PAT for you
me apikey list   [--agent <agent>]                            # no --agent → your own keys
me apikey get    <id>
me apikey delete <id> [-y]
  • Drop --self — self is now the default.
  • name is the only positional (unambiguous), so PATs can be named.
  • Default name gains a random suffix (cli-<date>-<rand>) so repeated unnamed creates never collide.
  • list defaults to your own keys.

No server/protocol/DB/engine changes — the wire is already memberId-based and treats user vs agent identically.

Breaking change (intentional, strict + silent)

  • me apikey create my-agent now mints a PAT named my-agent; agent provisioning moves to me apikey create --agent my-agent.
  • me apikey list <agent>me apikey list --agent <agent> (bare positional now errors).
  • No "did you mean --agent?" hint.

Agent-centric copy (me apikey create <agent>--agent <agent>) swept across CLI/server messages, the claude-plugin, and docs (incl. a rewrite of docs/cli/me-apikey.md).

Verification

  • ./bun run check — 648 pass, 0 fail.
  • api-key + authenticate-space integration tests (local Postgres) — 16 pass, incl. the legacy-key recreate-message assertion and PAT creation.
  • me apikey {create,list} -h confirmed showing the self-first shape.
  • New e2e test (7b): two unnamed PATs don't collide, a named PAT works, me apikey list shows your own keys, and a PAT authenticates as kind u. (The e2e suite self-skips without OPENAI_API_KEY locally; runs in CI.)

Closes TNT-145

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reshapes the me apikey CLI so personal access tokens (user keys) are the default, and agent keys are opt-in via --agent, aligning the CLI UX with the existing memberId-based server API and preventing same-day name collisions for unnamed PATs.

Changes:

  • Reworks me apikey create/list syntax to be self-default (--self removed) and agent-targeted via --agent <agent>.
  • Adds randomized default key names (cli-<date>-<rand>) and extends integration/e2e coverage for PAT behavior (create/list/authenticate).
  • Sweeps updated instructions across server/CLI messages, plugin metadata, and docs to reflect the new CLI shape.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
scripts/integration-test.ts Updates integration test invocations to the new --agent flag shape.
packages/server/middleware/authenticate-space.ts Updates legacy API key error guidance to point to me apikey create --agent <agent>.
packages/cli/commands/mcp.ts Updates MCP CLI legacy-key guidance to the new --agent syntax.
packages/cli/commands/apikey.ts Implements self-default create/list behavior and randomized default key names.
packages/cli/commands/agent.ts Updates agent workflow hints to reference me apikey create --agent ….
packages/claude-plugin/README.md Updates setup instructions to mint agent keys via --agent.
packages/claude-plugin/.claude-plugin/plugin.json Updates plugin config text to reference me apikey create --agent <agent>.
e2e/cli.e2e.test.ts Adds e2e test ensuring PAT default behavior and no same-day unnamed collisions.
docs/mcp-integration.md Updates MCP prerequisites to document PAT vs agent-key creation.
docs/cli/me-opencode.md Updates --api-key guidance to include PAT and --agent agent keys.
docs/cli/me-login.md Updates login docs to describe PATs as headless alternative while sessions remain primary.
docs/cli/me-gemini.md Updates --api-key guidance to include PAT and --agent agent keys.
docs/cli/me-codex.md Updates --api-key guidance to include PAT and --agent agent keys.
docs/cli/me-claude.md Updates headless install credential guidance for PATs and agent keys.
docs/cli/me-apikey.md Rewrites me apikey reference docs for self-default + --agent shape and naming behavior.
AUTH_DESIGN.md Updates auth design text to reflect PAT creation without --self.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/cli/commands/apikey.ts
Comment thread docs/cli/me-apikey.md Outdated
Comment on lines 75 to 77
clack.log.info(
"Add it to a space with 'me agent add', then mint a key with 'me apikey create'.",
`Add it to a space with 'me agent add', then mint a key with 'me apikey create --agent ${name}'.`,
);
Comment on lines 152 to +155
clack.log.success(`Added agent ${agent} to the space.`);
clack.log.info("Mint a key with 'me apikey create'.");
clack.log.info(
`Mint a key with 'me apikey create --agent ${agent}'.`,
);
Invert the command so a personal access token (PAT) is the default and
agents opt in via `--agent`:

  me apikey create [name] [--agent <agent>] [--expires <ts>]
  me apikey list   [--agent <agent>]

- Drop `--self`; self is now the default. The old guard made `--self
  [name]` impossible, so PATs could never be named and two same-day
  unnamed PATs collided on `unique (member_id, name)`.
- `name` is now the only positional (unambiguous).
- Default name gains a random suffix (`cli-<date>-<rand>`) so repeated
  unnamed creates never collide.
- `list` defaults to your own keys (was a required `<agent>` positional).

Breaking, intentional, strict + silent: `me apikey create my-agent`
mints a PAT named `my-agent`; agent provisioning moves to `--agent`.

No server/protocol/DB/engine changes — the wire is already memberId-based.
Sweeps agent-centric copy (`me apikey create <agent>` → `--agent`) across
CLI/server messages, the claude-plugin, and docs.

Refs TNT-145
@jgpruitt jgpruitt force-pushed the jgpruitt/me-apikey branch from 5c17815 to 04a38bb Compare June 25, 2026 19:03
jgpruitt and others added 2 commits June 25, 2026 14:06
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: John Pruitt <jgpruitt@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: John Pruitt <jgpruitt@gmail.com>
@jgpruitt jgpruitt merged commit 3e7a0cc into main Jun 25, 2026
5 checks passed
@jgpruitt jgpruitt deleted the jgpruitt/me-apikey branch June 25, 2026 19:09
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