Skip to content

Releases: tomaspozo/agentlink

v2.4.0

Choose a tag to compare

@tomaspozo tomaspozo released this 15 Jul 17:24

Added

  • Codex plugin format — the same directory now installs in Claude Code, Cursor, and Codex. New .codex-plugin/plugin.json (spec) declares the seven shared skills, the destructive-DB hook, and an interface block (display name, category, brand color, default prompts) for directory presentation. The hook is reused verbatim — no Codex variant: Codex's hook system mirrors Claude Code's (same PreToolUse event, matcher: "Bash", tool_input.command payload, exit-2 + stderr blocking) and it reads CLAUDE_PLUGIN_ROOT for compatibility, so .codex-plugin/plugin.json points straight at hooks/hooks.json.
  • codex/skills/builder/ — the builder spine for Codex. Codex plugin manifests have no agents and no rules field, so neither agents/builder.md (Claude, forced default via settings.json) nor rules/agentlink.mdc (Cursor, alwaysApply) can port. This entry-point skill carries the same spine — engage-AgentLink routing, plan-first, the architecture decision matrix, the decision protocol, core rules, and the prod guardrail — and delegates the how to the shared skills. It is the peer of those two files: change one, consider the other two.
    • It lives in a Codex-only root so it stays invisible to Claude Code (which auto-discovers ./skills/ only) and Cursor (whose manifest points at skills) — the seven domain skills stay shared and single-source, with no duplication.
    • ⚠️ .codex-plugin/plugin.json declares "skills": ["./skills/", "./codex/skills/"]. The manifest array replaces the default ./skills root rather than adding to it (plugin_skill_roots()), so ./skills/ must stay listed — drop it and the domain skills silently stop loading. (Array support: openai/codex#28790, stable since rust-v0.143.0; the published docs still describe skills as a single string.)
  • .agents/plugins/marketplace.json — the Codex repo marketplace, making the plugin installable. Codex reads a repo's marketplace from .agents/plugins/marketplace.json (not .codex-plugin/, which holds only the plugin manifest), and its plugin entries take a source object ({"source":"local","path":"./"}) rather than Claude's plain string. Install is codex plugin marketplace add tomaspozo/agentlink (accepts a local path, owner/repo[@ref], or an HTTPS/SSH Git URL) followed by codex plugin add agentlink@tomaspozo — note plugin add, not plugin install.
    • ⚠️ .agents/ was gitignored (it's where companion skills install locally), so .gitignore now re-includes that one file explicitly — level by level, since git won't descend into an excluded directory. Without the negation the marketplace never ships and the documented install fails. Keep it in sync if the file ever moves.
  • cli skill: references/resend.md documents the new OAuth key-provisioning path. First-time interactive resend setup now leads with "Connect with Resend" — a browser OAuth flow that mints a sending_access key and pushes it, no dashboard/copy-paste — with paste as the fallback. The note makes clear this only affects the interactive prompt: --api-key, --non-interactive, and saved defaults are unchanged, so agent-driven/scripted setup still passes the key explicitly. Matches the CLI's resend setup OAuth feature.
  • frontend skill: the canonical list + detail routing pattern is documented and demonstrated. references/routing.md gained a "List + detail pages" section and SKILL.md a matching rule: for independent /x (list) and /x/$id (detail) pages, use an index route (x/index.tsx + x/$id.tsx) — never a flat x.tsx + x.$id.tsx, which makes the generator treat x.tsx as a parent layout and nest the detail inside it, so /x/$id changes the URL but keeps rendering the list (the detail only mounts in an <Outlet/> the full-page list doesn't have). Points at the scaffold's new _auth/settings/members/ (list index.tsx + detail $membershipId.tsx) as the reference to copy.
  • frontend skill: references/data_fetching.md gained "Reloading on a Workspace Switch". Explains why query keys must NOT carry the active workspace id (reloading on switch is centralized in WorkspaceProvider, which resets workspace-scoped queries), with a user-scoped vs workspace-scoped table and the rule that a user-level query (profile, oauth-grants, account settings, active sessions, billing…) must be added to KEEP_ON_WORKSPACE_SWITCH so it isn't needlessly refetched on every switch. A matching note landed in SKILL.md's workspace-switching section and the Query Key Structure rules; flags the two anti-patterns (filter-less invalidateQueries(), threading activeId into keys).

Changed

  • rules/agentlink.mdc slimmed to routing + non-negotiables (114 → 58 lines, ~6.7k → ~3.1k chars). The rule is alwaysApply: true, so it rides in the system prompt of every Cursor request — length there is paid on all traffic and dilutes the rules. It now does the one job only it can do (route a generic agent into AgentLink and state the hard stops: api-only exposure, .rpc() never .from(), RLS everywhere, never reset the DB, forward-only migrations, prod needs approval) and delegates the detail to the skills Cursor already loads. Dropped from the rule and verified as covered: the function-prefix table and schema layout (database), the withSupabase options (edge-functions), scaffold-map and prerequisites (cli), and the blank-project kickoff (cli/references/workflows.md). Dropping the withSupabase block also removes a copy of a contract that churns between releases — the edge-functions skill is the single source of truth for it.
  • release.sh bumps all three manifests. .codex-plugin/plugin.json joins .claude-plugin and .cursor-plugin in the version bump and the release commit, so the Codex manifest can't silently drift out of lockstep.
  • frontend skill: canonical members references now point at members/index.tsx. SKILL.md's route tree, references/auth_ui.md's route-guard recipe, and references/routing.md's convention table updated for the CLI scaffold's members list+detail split.

v2.3.1

Choose a tag to compare

@tomaspozo tomaspozo released this 07 Jul 23:20

Changed

  • frontend skill: the invite-accept flow diagram (references/auth_ui.md) reflects the CLI 2.3.1 scaffold. A new user accepting an invitation with email confirmation on now routes through the shared /check-inbox?type=signup step (paste the 8-digit OTP or click the link) and lands back on /accept-invite to auto-join — instead of the old bare "click the link" card. The diagram also drops a stale /sign-in bounce (the page is self-contained with an inline create-account / sign-in form) and notes the ["tenants"] cache refresh before landing on /dashboard. Keeps the plugin in lockstep with the CLI's 2.3.1 scaffold (invite-accept OTP step, invite-accept sign-out-race fix, and the route-guard query-cache fix).

v2.3.0

Choose a tag to compare

@tomaspozo tomaspozo released this 07 Jul 21:22

Changed

  • database + cli skills: pgmq queues are documented as an IMPERATIVE resource, not a schema file or migration. cli/references/migration_system.md, cli/SKILL.md, cli/references/scaffold-map.md, cli/references/troubleshooting.md, database/SKILL.md (the supabase/database/ tree), and database/references/naming_conventions.md now place the pgmq queue in supabase/database/queue/ alongside config/, cron/, storage/, rbac/. The rule agents must learn: a queue (or any DO/pgmq/cron block) in schemas/ never reaches prod — prod is migrations-only and skips declarative db apply, so Supabase-managed objects must live in an imperative folder. Documented db resources --env <name> / --prod as the way to push just those to a cloud env.
  • database skill: a permission-gated write must not be directly writable by authenticated. SKILL.md and root CONVENTIONS.md gained the rule that a write guarded by auth_verify_access(...) must go through a SECURITY DEFINER helper and grant the write to service_role only — RLS is isolation-only and can't see the permission check, so a direct authenticated write grant + isolation-only RLS is a weaker gate than the RPC. Includes the "tell" (if the RPC calls auth_verify_access, route the write through a DEFINER helper).

v2.2.0

Choose a tag to compare

@tomaspozo tomaspozo released this 07 Jul 02:45

Changed

  • frontend skill: forms migrate from React Hook Form to TanStack Form. The scaffold's form stack is now @tanstack/react-form — the same family as the scaffold's TanStack Router + TanStack Query, and the stack shadcn's own docs currently favor — instead of react-hook-form + @hookform/resolvers. SKILL.md's basic pattern and references/forms.md's modal/edit-form patterns now use useForm with validators: { onSubmit: schema } and form.Field's render prop, wrapped in shadcn's Field/FieldLabel/FieldError primitives, instead of register/Controller/zodResolver.
  • frontend skill: three more curated shadcn primitives — alert, empty, field. references/scaffold-map.md's components/ui/ inventory and references/auth_ui.md/references/data_fetching.md now reference these where they replace hand-rolled markup (e.g. empty states, inline field errors), keeping with the "never hand-roll a primitive shadcn ships" rule. skills/cli/references/scaffold-map.md component list updated to match.
  • frontend skill: the scaffold's toaster is now the real vendored shadcn Toaster (ui/sonner.tsx), not a hand-rolled AppToaster. routing.md and data_fetching.md's __root.tsx examples now import Toaster from @/components/ui/sonner; scaffold-map.md's component inventory drops app-toaster/forms/form-field (both deleted from the scaffold) and adds sonner to the curated components/ui/ list.

Fixed

  • frontend skill: SKILL.md's own frontmatter still said "React Hook Form + Zod forms" — missed in the earlier TanStack Form migration pass, which updated the body sections but not the YAML description used to decide when the skill activates.

v2.1.0

Choose a tag to compare

@tomaspozo tomaspozo released this 04 Jul 01:19

Added

  • notifications skill: a new references/resend-box.md documents the local email sandbox's actual HTTP API (list/filter/fetch/clear captured emails, response shape, a verification recipe) so the plugin is self-contained. transactional-email.md's local-testing step previously said "see the resend-box companion skill" — that skill is not part of this plugin, not declared as a dependency, and not guaranteed to be installed, so on any machine without it the agent knew resend-box captures emails but had no way to actually query it. notifications/SKILL.md and cli/references/resend.md now cross-link the new reference too.
  • auth skill: document the scaffold's new no_access suspension role and api.user_ban/api.user_unban platform-wide ban. The membership RPC contract table grows from eight to eleven RPCs (membership_suspend, user_ban, user_unban), the role table gains no_access (rank 0, non-invitable, zero permissions), and the "role changes take effect on the next request" section is rewritten — it previously said the scaffold doesn't ship a live-session hard-cut and you'd have to build one; it now does (user_ban bans the account, kills auth.sessions/auth.refresh_tokens, and _auth_pre_request rejects a banned caller immediately even on a still-valid access token).

Fixed

  • cli skill: document that db migrate now also gates destructive migrations behind --allow-destructive. The CLI closed a gap where db migrate could silently write a migration containing an ungated DROP TABLE/COLUMN/SCHEMA/TRUNCATE (e.g. a table rename) with no confirmation — unlike db apply/db rebuild, which already required the flag before pushing the same statement to a live DB. SKILL.md's Tier 2 migrations section and references/migration_system.md's db migrate deep dive now say so, so the agent reviews the printed diff with the user before adding --allow-destructive instead of being surprised by the new refusal.

v2.0.0

Choose a tag to compare

@tomaspozo tomaspozo released this 02 Jul 20:27

Agent 2.0 — the plugin is rewritten to the identity-only auth model + native MCP. The JWT proves identity only (no tenant, no permissions in the token); the active workspace is asserted per request via an x-workspace-id header, resolved by a public._auth_pre_request() db-pre-request hook into a transaction-local GUC, with role/permissions read from api.session_context(). The 1.x machinery is gone (session_tenants, _hook_custom_access_token, _internal_admin_set_session_tenant/sync_session_tenants, api.tenant_select, all app_metadata.tenant_id/permissions JWT claims). Skills auth / frontend / rpc / database were updated to the new model; edge-functions gained an MCP reference; cli gained the 1.x → 2.0 upgrade runbook. New scaffold objects: public._auth_pre_request, api.session_context, api.tenant_update, api.tenant_delete, the imperative config/ folder (config/db_pre_request.sql), and the mcp edge function + _shared/mcp.ts. Version bumped to 2.0.0 (plugin + CLI in lockstep).

Added

  • Reference: upgrading a project to 2.0 (identity-only auth + native MCP). skills/cli/references/upgrade-2.0-identity-auth.md is the breaking 1.x → 2.0 migration runbook — what --force-update does and doesn't cover at the 2.0 boundary, the removed/added auth objects, deleting orphaned files, generating the new_auth_model transformation via db migrate, the frontend semantic merge, and the contract bump. Validated end-to-end on a real 1.2 project. Linked from references/upgrading.md and the cli SKILL reference index.

v1.4.1

Choose a tag to compare

@tomaspozo tomaspozo released this 26 Jun 02:34

Changed

  • The release script bumps both plugin manifests, the builder.md stamp, and the changelog in lockstep with the CLI. scripts/release.sh gained a --lockstep mode (skips the confirm prompt, tolerates an empty [Unreleased] for a CLI-only release) and now also stamps agents/builder.md. The normal entry point is the CLI repo's scripts/release.sh, which invokes this with --lockstep so both repos release at the same version.

v1.4.0

Choose a tag to compare

@tomaspozo tomaspozo released this 26 Jun 02:30

Added

  • Migrations are forward-only — a new immutability rule. A migration becomes immutable the moment it is either committed to git or deployed to any environment: editing a committed migration is forbidden (fix forward with a new db migrate), and an uncommitted migration may be edited/regenerated only after confirming with the user that it has not reached production (a prod deploy from a dirty tree can push one). Added at the decision layer in agents/builder.md and as an authoritative section in skills/cli/references/migration_system.md; the "Fix a broken migration" / "Remove a migration" troubleshooting steps and the cli skill's manual-fix list were reconciled to gate on uncommitted-and-not-deployed instead of telling the agent to edit migration files.
  • AGENTLINK_VERSION stamp in agents/builder.md. Records the current version (plugin + CLI ship in lockstep, same number) and how the agent should reason about contract drift from a project's agentlink.json (version / appliedVersion). Kept in sync by the release script.

Changed

  • Prefer the project-local CLI (pnpm exec agentlink) over npx …@latest for in-project work (pairs with the CLI's 1.4 devDependency pinning). agents/builder.md and the cli skill gained a "Running the CLI" section explaining the convention and the name split — the package is agentlink-sh, the installed binary is agentlink, and bare npx agentlink is unsafe (it resolves a different npm package when no local install exists). Swept ~230 in-project command references across the skills, README.md, rules/agentlink.mdc, and the destructive-DB hooks from npx agentlink-sh@latest <cmd> to pnpm exec agentlink <cmd>; create and recovery commands keep @latest (no local CLI exists yet). The hooks now point users at pnpm exec agentlink db rebuild — the block matcher is invocation-prefix-agnostic, so destructive-reset blocking still fires.

v1.3.1

Choose a tag to compare

@tomaspozo tomaspozo released this 24 Jun 16:43

Added

  • database skill: "deprecate, don't delete" rule for deployed cron/storage resources. The imperative deploy step only applies files that are present and never reconciles deletions (unlike rbac/), so removing a cron/ or storage/ file leaves the resource live in an already-deployed DB. New rule in skills/database/SKILL.md: rename to deprecated-<name>.sql, comment out the original definition, then for cron append an idempotent cron.unschedule(jobid) FROM cron.job WHERE jobname='<name>' (the bare unschedule throws when absent and rolls back the cron folder); for storage emit no SQL and delete the bucket from the dashboard (objects cascade), since DELETE FROM storage.buckets orphans objects that keep counting against Storage usage.

v1.3.0

Choose a tag to compare

@tomaspozo tomaspozo released this 23 Jun 03:11

Added

  • New notifications skill — the entry point for transactional / non-auth email. Teaches the builder how AgentLink sends app-driven email (welcome, "export ready", receipts, alerts) through the queue: api._admin_send_email → PGMQ → internal-queue-worker → internal-send-email → Resend, with public.internal_logs_email for idempotency/observability. SKILL.md covers the server-only send rule, the send API, the welcome sample + its confirmation-timing nuance, and cross-links auth (auth emails), cli (per-env Resend setup), edge-functions, and database. references/transactional-email.md is the deep dive: add-an-email recipe, the internal_logs_* convention, retry/dead-letter via read_ct, local resend-box testing, and troubleshooting. Registered in agents/builder.md (now 7 preloaded skills); auth and edge-functions SKILLs cross-link it so non-auth email is routed to the right place.
  • builder agent: the transactional-vs-auth email split is now spelled out at the decision layer. Two new rows in the architecture matrix (agents/builder.md) route app-driven email to api._admin_send_email(...) → internal-send-email (notifications skill) and Supabase Auth email to the _hook_send_email → internal-send-auth-email hook (auth skill, flagged a separate function). A new "Email: two paths, never crossed" subsection adds the originator litmus test (does your code decide to send it? → notifications; does an auth event trigger it? → auth hook), warns against routing auth email through api._admin_send_email or adding auth templates to the internal-send-email registry, and notes the scaffolded welcome email is deliberately a notification, not an auth hook, so it never collides with the signup confirmation.
  • notifications skill: migration guide for projects scaffolded before the unified email path. New section in skills/notifications/SKILL.md for older projects that shipped a dedicated internal-invite-member edge function: recommend consolidating onto the invite registry entry in internal-send-email (confirm with the user first — it removes a function and leaves an orphaned cloud deployment to delete), with exact steps (add the invite template, repoint _internal_admin_create_invitation/_resend_invitation to api._admin_send_email('invite', …) with no dedupe_key, delete the function + its config.toml block, db apply/db migrate/deploy, then supabase functions delete on cloud). Generalizes to any bespoke per-email function; notes auth emails stay on the auth hook.

Changed

  • Prescriptive docs migrated off the per-function invite pattern to the unified api._admin_send_email('invite') → internal-send-email path. agents/references/recipes.md (Recipe 2), skills/auth/SKILL.md (invitation RPC row + troubleshooting), skills/auth/references/rls_patterns.md, skills/edge-functions/SKILL.md (naming table + resend link), and skills/cli/references/resend.md no longer teach the standalone internal-invite-member function as the canonical invite-email path.