Repository navigation
Releases: tomaspozo/agentlink
Release list
v2.4.0
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 aninterfaceblock (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 (samePreToolUseevent,matcher: "Bash",tool_input.commandpayload, exit-2 + stderr blocking) and it readsCLAUDE_PLUGIN_ROOTfor compatibility, so.codex-plugin/plugin.jsonpoints straight athooks/hooks.json. codex/skills/builder/— the builder spine for Codex. Codex plugin manifests have noagentsand norulesfield, so neitheragents/builder.md(Claude, forced default viasettings.json) norrules/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 atskills) — the seven domain skills stay shared and single-source, with no duplication. ⚠️ .codex-plugin/plugin.jsondeclares"skills": ["./skills/", "./codex/skills/"]. The manifest array replaces the default./skillsroot 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 sincerust-v0.143.0; the published docs still describeskillsas a single string.)
- It lives in a Codex-only root so it stays invisible to Claude Code (which auto-discovers
.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 asourceobject ({"source":"local","path":"./"}) rather than Claude's plain string. Install iscodex plugin marketplace add tomaspozo/agentlink(accepts a local path,owner/repo[@ref], or an HTTPS/SSH Git URL) followed bycodex plugin add agentlink@tomaspozo— noteplugin add, notplugin install.⚠️ .agents/was gitignored (it's where companion skills install locally), so.gitignorenow 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.
cliskill:references/resend.mddocuments the new OAuth key-provisioning path. First-time interactiveresend setupnow leads with "Connect with Resend" — a browser OAuth flow that mints asending_accesskey 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'sresend setupOAuth feature.frontendskill: the canonical list + detail routing pattern is documented and demonstrated.references/routing.mdgained a "List + detail pages" section andSKILL.mda matching rule: for independent/x(list) and/x/$id(detail) pages, use an index route (x/index.tsx+x/$id.tsx) — never a flatx.tsx+x.$id.tsx, which makes the generator treatx.tsxas a parent layout and nest the detail inside it, so/x/$idchanges 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/(listindex.tsx+ detail$membershipId.tsx) as the reference to copy.frontendskill:references/data_fetching.mdgained "Reloading on a Workspace Switch". Explains why query keys must NOT carry the active workspace id (reloading on switch is centralized inWorkspaceProvider, 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 toKEEP_ON_WORKSPACE_SWITCHso it isn't needlessly refetched on every switch. A matching note landed inSKILL.md's workspace-switching section and the Query Key Structure rules; flags the two anti-patterns (filter-lessinvalidateQueries(), threadingactiveIdinto keys).
Changed
rules/agentlink.mdcslimmed to routing + non-negotiables (114 → 58 lines, ~6.7k → ~3.1k chars). The rule isalwaysApply: 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), thewithSupabaseoptions (edge-functions),scaffold-mapand prerequisites (cli), and the blank-project kickoff (cli/references/workflows.md). Dropping thewithSupabaseblock also removes a copy of a contract that churns between releases — theedge-functionsskill is the single source of truth for it.release.shbumps all three manifests..codex-plugin/plugin.jsonjoins.claude-pluginand.cursor-pluginin the version bump and the release commit, so the Codex manifest can't silently drift out of lockstep.frontendskill: canonical members references now point atmembers/index.tsx.SKILL.md's route tree,references/auth_ui.md's route-guard recipe, andreferences/routing.md's convention table updated for the CLI scaffold's members list+detail split.
v2.3.1
Changed
frontendskill: 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=signupstep (paste the 8-digit OTP or click the link) and lands back on/accept-inviteto auto-join — instead of the old bare "click the link" card. The diagram also drops a stale/sign-inbounce (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's2.3.1scaffold (invite-accept OTP step, invite-accept sign-out-race fix, and the route-guard query-cache fix).
v2.3.0
Changed
database+cliskills: 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(thesupabase/database/tree), anddatabase/references/naming_conventions.mdnow place the pgmq queue insupabase/database/queue/alongsideconfig/,cron/,storage/,rbac/. The rule agents must learn: a queue (or anyDO/pgmq/cronblock) inschemas/never reaches prod — prod is migrations-only and skips declarativedb apply, so Supabase-managed objects must live in an imperative folder. Documenteddb resources --env <name>/--prodas the way to push just those to a cloud env.databaseskill: a permission-gated write must not be directly writable byauthenticated.SKILL.mdand rootCONVENTIONS.mdgained the rule that a write guarded byauth_verify_access(...)must go through aSECURITY DEFINERhelper and grant the write toservice_roleonly — RLS is isolation-only and can't see the permission check, so a directauthenticatedwrite grant + isolation-only RLS is a weaker gate than the RPC. Includes the "tell" (if the RPC callsauth_verify_access, route the write through a DEFINER helper).
v2.2.0
Changed
frontendskill: 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 ofreact-hook-form+@hookform/resolvers.SKILL.md's basic pattern andreferences/forms.md's modal/edit-form patterns now useuseFormwithvalidators: { onSubmit: schema }andform.Field's render prop, wrapped in shadcn'sField/FieldLabel/FieldErrorprimitives, instead ofregister/Controller/zodResolver.frontendskill: three more curated shadcn primitives —alert,empty,field.references/scaffold-map.md'scomponents/ui/inventory andreferences/auth_ui.md/references/data_fetching.mdnow 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.mdcomponent list updated to match.frontendskill: the scaffold's toaster is now the real vendored shadcnToaster(ui/sonner.tsx), not a hand-rolledAppToaster.routing.mdanddata_fetching.md's__root.tsxexamples now importToasterfrom@/components/ui/sonner;scaffold-map.md's component inventory dropsapp-toaster/forms/form-field(both deleted from the scaffold) and addssonnerto the curatedcomponents/ui/list.
Fixed
frontendskill: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
Added
notificationsskill: a newreferences/resend-box.mddocuments 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 theresend-boxcompanion 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.mdandcli/references/resend.mdnow cross-link the new reference too.authskill: document the scaffold's newno_accesssuspension role andapi.user_ban/api.user_unbanplatform-wide ban. The membership RPC contract table grows from eight to eleven RPCs (membership_suspend,user_ban,user_unban), the role table gainsno_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_banbans the account, killsauth.sessions/auth.refresh_tokens, and_auth_pre_requestrejects a banned caller immediately even on a still-valid access token).
Fixed
cliskill: document thatdb migratenow also gates destructive migrations behind--allow-destructive. The CLI closed a gap wheredb migratecould silently write a migration containing an ungatedDROP TABLE/COLUMN/SCHEMA/TRUNCATE(e.g. a table rename) with no confirmation — unlikedb apply/db rebuild, which already required the flag before pushing the same statement to a live DB.SKILL.md's Tier 2 migrations section andreferences/migration_system.md'sdb migratedeep dive now say so, so the agent reviews the printed diff with the user before adding--allow-destructiveinstead of being surprised by the new refusal.
v2.0.0
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-idheader, resolved by apublic._auth_pre_request()db-pre-request hook into a transaction-local GUC, with role/permissions read fromapi.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, allapp_metadata.tenant_id/permissionsJWT 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 imperativeconfig/folder (config/db_pre_request.sql), and themcpedge 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.mdis the breaking 1.x → 2.0 migration runbook — what--force-updatedoes and doesn't cover at the 2.0 boundary, the removed/added auth objects, deleting orphaned files, generating thenew_auth_modeltransformation viadb migrate, the frontend semantic merge, and the contract bump. Validated end-to-end on a real 1.2 project. Linked fromreferences/upgrading.mdand the cli SKILL reference index.
v1.4.1
Changed
- The release script bumps both plugin manifests, the
builder.mdstamp, and the changelog in lockstep with the CLI.scripts/release.shgained a--lockstepmode (skips the confirm prompt, tolerates an empty[Unreleased]for a CLI-only release) and now also stampsagents/builder.md. The normal entry point is the CLI repo'sscripts/release.sh, which invokes this with--lockstepso both repos release at the same version.
v1.4.0
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 inagents/builder.mdand as an authoritative section inskills/cli/references/migration_system.md; the "Fix a broken migration" / "Remove a migration" troubleshooting steps and thecliskill's manual-fix list were reconciled to gate on uncommitted-and-not-deployed instead of telling the agent to edit migration files. AGENTLINK_VERSIONstamp inagents/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'sagentlink.json(version/appliedVersion). Kept in sync by the release script.
Changed
- Prefer the project-local CLI (
pnpm exec agentlink) overnpx …@latestfor in-project work (pairs with the CLI's 1.4 devDependency pinning).agents/builder.mdand thecliskill gained a "Running the CLI" section explaining the convention and the name split — the package isagentlink-sh, the installed binary isagentlink, and barenpx agentlinkis 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 fromnpx agentlink-sh@latest <cmd>topnpm exec agentlink <cmd>;createand recovery commands keep@latest(no local CLI exists yet). The hooks now point users atpnpm exec agentlink db rebuild— the block matcher is invocation-prefix-agnostic, so destructive-reset blocking still fires.
v1.3.1
Added
databaseskill: "deprecate, don't delete" rule for deployed cron/storage resources. The imperative deploy step only applies files that are present and never reconciles deletions (unlikerbac/), so removing acron/orstorage/file leaves the resource live in an already-deployed DB. New rule inskills/database/SKILL.md: rename todeprecated-<name>.sql, comment out the original definition, then for cron append an idempotentcron.unschedule(jobid) FROM cron.job WHERE jobname='<name>'(the bareunschedulethrows when absent and rolls back the cron folder); for storage emit no SQL and delete the bucket from the dashboard (objects cascade), sinceDELETE FROM storage.bucketsorphans objects that keep counting against Storage usage.
v1.3.0
Added
- New
notificationsskill — 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, withpublic.internal_logs_emailfor idempotency/observability.SKILL.mdcovers 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.mdis the deep dive: add-an-email recipe, theinternal_logs_*convention, retry/dead-letter viaread_ct, local resend-box testing, and troubleshooting. Registered inagents/builder.md(now 7 preloaded skills);authandedge-functionsSKILLs cross-link it so non-auth email is routed to the right place. builderagent: 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 toapi._admin_send_email(...)→internal-send-email(notificationsskill) and Supabase Auth email to the_hook_send_email→internal-send-auth-emailhook (authskill, 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 throughapi._admin_send_emailor adding auth templates to theinternal-send-emailregistry, and notes the scaffoldedwelcomeemail is deliberately a notification, not an auth hook, so it never collides with the signup confirmation.notificationsskill: migration guide for projects scaffolded before the unified email path. New section inskills/notifications/SKILL.mdfor older projects that shipped a dedicatedinternal-invite-memberedge function: recommend consolidating onto theinviteregistry entry ininternal-send-email(confirm with the user first — it removes a function and leaves an orphaned cloud deployment to delete), with exact steps (add theinvitetemplate, repoint_internal_admin_create_invitation/_resend_invitationtoapi._admin_send_email('invite', …)with nodedupe_key, delete the function + itsconfig.tomlblock,db apply/db migrate/deploy, thensupabase functions deleteon 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-emailpath.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), andskills/cli/references/resend.mdno longer teach the standaloneinternal-invite-memberfunction as the canonical invite-email path.