diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000000..dbf698ebbb --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", + "name": "pgrundev", + "description": "PostgreSQL developer tools for AI coding agents", + "owner": { + "name": "PGRunDev", + "url": "https://pgx.dev" + }, + "plugins": [ + { + "name": "pgx", + "source": "./plugins/pgx", + "description": "Give every AI coding agent its own isolated, disposable Postgres database.", + "category": "database", + "tags": ["postgres", "postgresql", "database", "ai-agents", "database-branching"], + "homepage": "https://github.com/pgrundev/pgx" + } + ] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b2273f5b3..1eab7d18e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,6 +124,21 @@ jobs: npx -y skills@latest add "$GITHUB_WORKSPACE/skills/pgx" -a claude-code codex cursor -y test -f .claude/skills/pgx/SKILL.md && test -f .agents/skills/pgx/SKILL.md test ! -e .claude/skills/pgx/tests + plugin: + name: Claude Code plugin (marketplace, manifest, install cycle) + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: { node-version: 22 } + - name: Install the Claude Code CLI (pinned; validate/install need no login) + run: npm install -g @anthropic-ai/claude-code@2.1.310 && claude --version + - name: Plugin package tests (drift, manifests, hygiene, isolated install cycle) + run: plugins/tests/pgx/run.sh + - name: Secret scan of the plugin package and marketplace (gitleaks) + run: | + curl -fsSL https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz | tar -xz gitleaks + for d in plugins .claude-plugin skills; do ./gitleaks dir "$d" --no-banner --redact; done docker: name: Docker image (${{ matrix.os }}) strategy: diff --git a/README.md b/README.md index 8cad73bb7f..cc6b0b2585 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,14 @@ License: AGPL-3.0

+```text +# Claude Code: install inside a session (native plugin) +/plugin marketplace add pgrundev/pgx +/plugin install pgx@pgrundev +``` + ```bash -# Recommended: AI coding agents (Claude Code, Cursor, Codex) +# Any agent host (Claude Code, Cursor, Codex): the Agent Skills CLI npx skills add pgrundev/pgx --skill pgx # Manual PGX installation @@ -396,7 +402,16 @@ permanent or system databases, and resumes cleanup automatically after a ### Every AI agent gets its own Postgres -Install the Skill in a project, then ask your agent: +Install the Skill, then ask your agent. In Claude Code, from inside a session: + +```text +/plugin marketplace add pgrundev/pgx +/plugin install pgx@pgrundev +/pgx:pgx Set up isolated Postgres databases for this project. +``` + +For Cursor, Codex or several hosts at once, the Agent Skills CLI installs the +same Skill into the project: ```bash npx skills add pgrundev/pgx --skill pgx @@ -404,6 +419,14 @@ npx skills add pgrundev/pgx --skill pgx > Use PGX to give this project isolated databases for coding agents. Set everything up. +The plugin is the Skill packaged for Claude Code's plugin manager (`/plugin` +lists, updates and removes it; the skill is `/pgx:pgx` and Claude also picks +it up on its own when a task touches the database). The Skills CLI copies +the Skill into `.claude/skills/pgx` and `.agents/skills/pgx` for every host. +Both contain no hooks and install no database engine: the `pgx` binary is +installed when the Skill first needs it, with your approval. Details and the +differences: [`docs/pgx/local-dev/claude-plugin.md`](docs/pgx/local-dev/claude-plugin.md). + The agent detects your database setup, installs PGX if needed, imports your development database **schema-only** into a template (`pgx copy`), writes a committed `.pgx.toml`, installs lifecycle hooks (`pgx agent setup`) and @@ -563,6 +586,7 @@ any semantic difference (`classify-regress-diffs.py --fail-on-semantic`). | [`v0.1-readiness.md`](docs/pgx/v0.1-readiness.md) | what is ready, known limitations, approved use | | [`linux-results.md`](docs/pgx/linux-results.md) | the full benchmark report | | [`compatibility-gate.md`](docs/pgx/compatibility-gate.md) | how to decide whether a database can run on PGX | +| [`local-dev/claude-plugin.md`](docs/pgx/local-dev/claude-plugin.md) | the PGX plugin for Claude Code: `/plugin marketplace add pgrundev/pgx`, `/plugin install pgx@pgrundev`, how it relates to the Skills CLI install, updates, removal | | [`local-dev/agents.md`](docs/pgx/local-dev/agents.md) | the PGX Skill and `pgx agent`: automatic per-session isolation for Claude Code, Cursor and Codex, with the compatibility matrix | | [`local-dev/copy.md`](docs/pgx/local-dev/copy.md) | `pgx copy`: import an existing PostgreSQL database and branch it per agent | | [`pgrun-integration.md`](docs/pgx/pgrun-integration.md) | the host-agent API PGRun builds against | diff --git a/docs/pgx/local-dev/agents.md b/docs/pgx/local-dev/agents.md index 1bda671277..6400ada4fb 100644 --- a/docs/pgx/local-dev/agents.md +++ b/docs/pgx/local-dev/agents.md @@ -5,11 +5,24 @@ Code, Cursor or Codex session that touches your database works in its own disposable branch of a template, created in milliseconds, never shared, and cleaned up on its own. Your real PostgreSQL is read once and never written. +```text +/plugin marketplace add pgrundev/pgx # Claude Code: the Skill as a native plugin, inside a session +/plugin install pgx@pgrundev +``` + ```sh -npx skills add pgrundev/pgx --skill pgx # the Skill (recommended) +npx skills add pgrundev/pgx --skill pgx # any host (Claude Code, Cursor, Codex): the Skills CLI npx pgxdb@latest # PGX itself, if you prefer to install it by hand ``` +Three channels, one Skill: the Claude Code plugin (native install, `/plugin` +manages updates and removal, skill name `/pgx:pgx`), the Agent Skills CLI +(copies the Skill into the project for every supported host, skill name +`/pgx` in Claude Code) and the PGX CLI itself for manual use. The plugin and +the Skills CLI copy are the same files; see +[claude-plugin.md](claude-plugin.md) for the differences and for running +both. + Then open your agent in the project and ask it to set PGX up: > Use PGX to give this project isolated databases for coding agents. Set everything up. @@ -46,7 +59,7 @@ publishing process. | Host | Automatic isolation | How | Verified | |---|---|---|---| -| **Claude Code** | Yes | `SessionStart` hook writes the exports to `CLAUDE_ENV_FILE`; `UserPromptSubmit`/`PreToolUse` extend the TTL; `SessionEnd` retires the branch. | **Live, 2026-10-25**: setup from an existing PostgreSQL, feature work in a fresh session, resume within grace, two concurrent sessions. [validation note](validation/2026-10-25-agent-live-claude.md) | +| **Claude Code** | Yes | `SessionStart` hook writes the exports to `CLAUDE_ENV_FILE`; `UserPromptSubmit`/`PreToolUse` extend the TTL; `SessionEnd` retires the branch. | **Live, 2026-10-25**: setup from an existing PostgreSQL, feature work in a fresh session, resume within grace, two concurrent sessions. [validation note](validation/2026-10-25-agent-live-claude.md). **2026-10-26**: the same through the native plugin (`/plugin install pgx@pgrundev`). [plugin note](validation/2026-10-26-claude-plugin-live.md) | | **Cursor** (IDE agent, `agent` CLI) | Hooks installed; env injection pending live verification | `sessionStart` hook answers `{"env": …}`, which Cursor applies to that conversation's shell per its docs. Env is not re-applied to a reopened chat and not inherited by Cursor subagents; cloud agents are skipped. | Payload-level tests only; live run needs `agent login`. [note](validation/2026-10-25-agent-live-cursor.md). Use `pgx agent exec -- ` whenever `PGX_ISOLATION` is unset. | | **Codex** | With the wrapper | Codex hooks cannot set environment. `pgx agent exec -- codex` puts the branch in Codex's environment; inside any Codex session `pgx agent exec -- ` attaches to the session's branch. Lifecycle hooks still create the branch and tell the model. The `workspace-write` sandbox blocks loopback TCP until `sandbox_workspace_write.network_access = true`. | Wrapper verified by tests; native hooks pending a logged-in Codex. [note](validation/2026-10-25-agent-live-codex.md) | | Anything else | With the wrapper | `pgx agent exec -- ` | `tests/agent_exec.rs`, e2e scenarios C and D | diff --git a/docs/pgx/local-dev/claude-plugin.md b/docs/pgx/local-dev/claude-plugin.md new file mode 100644 index 0000000000..d06872611d --- /dev/null +++ b/docs/pgx/local-dev/claude-plugin.md @@ -0,0 +1,178 @@ +# The PGX plugin for Claude Code + +**One plugin. Every Claude Code agent gets its own Postgres.** + +The repository is a Claude Code plugin marketplace named `pgrundev` +(`.claude-plugin/marketplace.json`) with one plugin, `pgx` +(`plugins/pgx/`), which packages the PGX Agent Skill for Claude Code's +plugin manager. Nothing else changes: the Skill in `skills/pgx/` stays the +canonical implementation and the Skills CLI install keeps working. + +## Install, inside Claude Code + +```text +/plugin marketplace add pgrundev/pgx +/plugin install pgx@pgrundev +``` + +The second command opens the plugin's page in the `/plugin` panel. Choose a +scope: + +| Scope | Who gets it | Written to | +|---|---|---| +| user | you, in every project on this machine | `~/.claude/settings.json` | +| project | everyone who works in this repository | `.claude/settings.json` (committed) | +| local | you, in this repository only | `.claude/settings.local.json` | + +From a shell, without a session: `claude plugin marketplace add pgrundev/pgx` +then `claude plugin install pgx@pgrundev [--scope user|project|local]`. + +Then, in a project with a database: + +```text +/pgx:pgx Set up isolated Postgres databases for this project. +``` + +`pgx:pgx` is the skill's name under the plugin's namespace. You can also just +describe database work ("add a column and run the tests"); Claude selects +the skill when it is relevant. Both routes run the same Skill: detect the +project, check for PGX 0.1.1 or newer and offer to install it, prepare a +schema-only template, `pgx agent setup`, then work inside the session's +branch. See [agents.md](agents.md) for what that gives you. + +Check what is installed: + +```sh +claude plugin list # pgx@pgrundev Version: 0.1.1 Status: enabled +claude plugin details pgx # Component inventory: Skills (1) pgx, Hooks (0), MCP servers (0) +``` + +## What the plugin contains + +- `skills/pgx/`: the Skill, its eleven reference documents and two helper + scripts, identical to `skills/pgx/` at the repository root + (`plugins/sync.sh --check` fails CI on any difference). +- `.claude-plugin/plugin.json`: name `pgx`, version `0.1.1` (the Skill's + version), display name, links. +- `README.md`. + +About 84 KB, 16 files; roughly 190–270 tokens of context in every session +while installed (`claude plugin details pgx`). + +It contains **no hooks, MCP servers, commands or binaries**. Installing it at +user scope does nothing in projects that have not opted in: the Skill is +available, and database infrastructure appears only when you ask for it in a +project and `pgx agent setup` writes that project's `.pgx.toml` and hooks. + +## Hooks: one owner, no duplicates + +Lifecycle hooks (`SessionStart` → branch, `UserPromptSubmit`/`PreToolUse` → +keep-alive, `SessionEnd` → retire) are installed per project by `pgx agent +setup`, which is idempotent and recognises its own entries by their command +string. The plugin never registers hooks of its own, so there is exactly one +source of hooks whichever way the Skill was installed, and installing, +updating, disabling or removing the plugin never touches `.claude/settings.json` +(tested in `plugins/tests/pgx/run.sh`). Fail-closed behaviour is unchanged: +it lives in `pgx agent hook`, not in the Skill files. + +## The plugin and the Skills CLI together + +`npx skills add pgrundev/pgx --skill pgx` copies the Skill into +`.claude/skills/pgx` (and `.agents/skills/pgx`). That copy is a plain skill +named `pgx`. With the plugin installed as well, Claude Code lists both +`/pgx` and `/pgx:pgx` (verified: the session inventory shows the two names +side by side; neither hides the other). They are the same text, so whichever +Claude picks runs the same workflow, and nothing is duplicated at the +database level because branches and hooks come from `pgx agent`, not from +the skill files. The cost is two descriptions in context. + +To keep one copy, either remove the Skills CLI one (`npx skills remove pgx`, +which deletes only `.claude/skills/pgx` and `.agents/skills/pgx`) or the +plugin (`/plugin uninstall pgx@pgrundev`). Switching from the Skills CLI to +the plugin is those two steps; nothing in `.pgx.toml`, the hooks or the +databases changes. + +Cursor and Codex are not Claude Code plugins hosts: keep using the Skills +CLI for them. The PGX runtime itself is independent of both. + +## Update, disable, remove + +| Action | In a session | In a shell | +|---|---|---| +| Update | `/plugin` → Installed → pgx → Update now | `claude plugin update pgx@pgrundev` | +| Disable / enable | `/plugin` → Installed → Space | `claude plugin disable pgx@pgrundev` / `enable` | +| Remove | `/plugin uninstall pgx@pgrundev` | `claude plugin uninstall pgx@pgrundev` | +| Remove the marketplace | `/plugin marketplace remove pgrundev` | `claude plugin marketplace remove pgrundev` | + +Updates follow the plugin's `version` field: a new PGX Skill release bumps +it and `claude plugin update` (or the marketplace's auto-update, off by +default for third-party marketplaces) fetches it; users on an older copy keep +working. + +Uninstalling removes the Skill files from Claude Code's plugin cache and the +`enabledPlugins` entry, nothing else: PGX databases, templates, `.pgx.toml`, +the PGX runtime and any hooks `pgx agent setup` installed all stay. +`pgx agent uninstall` removes a project's hooks when you want that. + +## Performance and what gets downloaded + +`/plugin marketplace add pgrundev/pgx` clones the PGX repository once per +machine into `~/.claude/plugins/marketplaces/pgrundev/` (Claude Code reads +the catalog from a clone). The repository carries fuzzing corpora and +benchmark results, so that clone is a 192 MB shallow fetch and 2.2 GB on +disk and takes about a minute (53 s measured); `claude plugin marketplace +update` afterwards is incremental. The plugin itself is copied out of that clone: +the installed plugin is the 84 KB Skill package, nothing from `crates/`, +`fuzz/` or `benchmarks/`. From a shell you can keep the clone small: + +```sh +claude plugin marketplace add pgrundev/pgx --sparse .claude-plugin plugins +``` + +which checks out only the marketplace file and the plugin (8 s, 72 MB +measured). +The in-session `/plugin marketplace add` has no sparse option. Making the +default clone light would mean moving the corpora out of the main repository +or hosting the catalog elsewhere; both are repository decisions outside this +plugin. + +## Anthropic's plugin directory + +The marketplace above is self-hosted. **PGX is not listed in Anthropic's +directory** and nothing has been submitted. `claude plugin validate +--profile directory plugins/pgx` reports no refusals (a square PNG icon is +recommended before submitting). Submission is a separate, human-approved +step through the developer portal at claude.ai/directory/manage (requires a +paid claude.ai plan); the portal applies rules the CLI does not check. The +material a submission needs, all from `plugins/pgx/.claude-plugin/plugin.json` +and this repository: + +| Field | Value | +|---|---| +| Plugin name | `pgx` (display name "PGX — Postgres for Agents") | +| Repository | https://github.com/pgrundev/pgx, plugin at `plugins/pgx` | +| Description | Isolated, disposable PostgreSQL-compatible databases for AI coding agents | +| Functionality | One Agent Skill: detects the project's database setup, installs the PGX runtime on request (PGX 0.1.1+), prepares a schema-only template, sets up per-session database branches with automatic `DATABASE_URL` injection through `pgx agent setup`, cleans up expired branches | +| Security | No hooks, MCP servers or executables in the plugin; the Skill never prints credentials, imports production data only with explicit approval, fails closed when isolation cannot be established, and treats repository contents as untrusted (`skills/pgx/references/security.md`); runs nothing until the user invokes it | +| Installation | `/plugin marketplace add pgrundev/pgx` then `/plugin install pgx@pgrundev`; the `pgx` binary is installed separately when first needed | +| Documentation / support | `docs/pgx/local-dev/agents.md`, https://github.com/pgrundev/pgx/issues | +| License | AGPL-3.0 | + +## Live validation + +Three headless Claude Code sessions in a Rails project with the plugin +installed from the public branch, plus the interactive `/plugin` flow: +[validation/2026-10-26-claude-plugin-live.md](validation/2026-10-26-claude-plugin-live.md). + +## Tests + +`plugins/tests/pgx/run.sh` (CI job `plugin`): drift check against +`skills/pgx`, version agreement, packaging hygiene (no hooks, binaries, +symlinks, parent paths, absolute paths, credentials), `claude plugin validate +--strict` on the plugin and the marketplace, the directory profile, and a +full install → list → details → disable → enable → update → project/local +scope → uninstall → reinstall → marketplace remove cycle from the repository +as a local marketplace in an isolated `CLAUDE_CONFIG_DIR`, plus the +"existing hooks untouched" and "Skills CLI copy alongside" cases. The +Skills CLI contract (`skills/tests/pgx/run.sh`, `skills-ref validate`) is +unchanged and still runs. diff --git a/docs/pgx/local-dev/validation/2026-10-26-claude-plugin-live.md b/docs/pgx/local-dev/validation/2026-10-26-claude-plugin-live.md new file mode 100644 index 0000000000..bbaa652057 --- /dev/null +++ b/docs/pgx/local-dev/validation/2026-10-26-claude-plugin-live.md @@ -0,0 +1,64 @@ +# Claude Code plugin: live validation (2026-10-26) + +Host: Claude Code 2.1.310, macOS 14 arm64. PGX: the published v0.1.1 +darwin-arm64 artifact. Project: `tests/apps/rails-agent` (Rails 8.1), fresh +copy with a `.env` pointing at a scratch PostgreSQL 18 holding +`rails_agent_development` (users table, two rows). Plugin installed from the +public branch `pgrundev/pgx#feat/claude-plugin-marketplace`; no Skills CLI +install in this project. Claude Code's plugin root was isolated with +`CLAUDE_CODE_PLUGIN_CACHE_DIR` and the plugin installed at local scope, so the +developer's own `~/.claude` was not touched. + +## Installation from GitHub + +| Step | Result | +|---|---| +| `claude plugin marketplace add pgrundev/pgx#` (full clone) | 53 s; shallow clone, 2.2 GB on disk (`.git` 192 MB); `Successfully added marketplace: pgrundev` | +| same with `--sparse .claude-plugin plugins` | 8 s, 72 MB | +| `claude plugin install pgx@pgrundev --scope local` | `Successfully installed plugin: pgx@pgrundev (scope: local)`; installed copy 84 KB, 16 files, nothing from `crates/`, `fuzz/` or `benchmarks/` | +| `claude plugin details pgx` | `Skills (1) pgx`, `Agents (0)`, `Hooks (0)`, `MCP servers (0)`; always-on ~190–270 tokens | +| `claude plugin update pgx@pgrundev` | `already at the latest version (0.1.1)` | + +Interactive, in a real session (driven through a pseudo-terminal, screens +recorded): `/plugin marketplace add ` → `Successfully added +marketplace: pgrundev`; `/plugin install pgx@pgrundev` opened the plugin's +details with the three scope options; choosing *local* printed `✓ Installed +PGX — Postgres for Agents. Plugin is now active.`; `/plugin` → Installed +lists `PGX — Postgres for Agents · pgrundev · 1 skill`; typing `/pgx:` +offers `/pgx:pgx`; `/pgx:pgx …` answered with the skill name and its base +directory under the plugin cache. + +## Three headless sessions through the plugin + +| # | Prompt | Turns | Cost | Result | +|---|---|---|---|---| +| 1 | "Use the PGX plugin to set up isolated Postgres databases for this project." | 10 | $0.88 | Loaded `pgx:pgx` (Skill tool), ran the plugin's `detect-project.sh` and `check-pgx.sh` from `…/plugins/cache/pgrundev/pgx/0.1.1/skills/pgx/scripts/` (the `${CLAUDE_PLUGIN_ROOT}` path, substituted), classified the project `local`, `pgx run`, `pgx copy --schema-only` into `rails_agent_template`, `pgx agent setup --source rails_agent_template` (hooks for Claude Code, Cursor, Codex installed exactly once; `.pgx.toml` written), `pgx agent exec -- bin/rails db:migrate` in its branch `agent-claude-72d1102e`. 123 s. | +| 2 | new session: "Add a last_login_at timestamp to users and run the tests." | 8 | $0.64 | Branch `agent-claude-637bdc7d` provided by the SessionStart hook; migration written, `bin/rails test`: 3 runs, 5 assertions, 0 failures. `last_login_at` exists in the branch only: template 0, developer PostgreSQL 0. 81 s. | +| 3 | new session: print `PGX_BRANCH`, `PGX_ISOLATION`, the database name, `pgx agent ls` | 2 | $0.35 | `PGX_BRANCH=agent-claude-94863d2f`, `PGX_ISOLATION=ok`, `DATABASE_URL` names the same branch; `pgx agent ls` showed it active beside the two earlier branches, both `retired` with their grace period running. 13 s. | + +Total $1.87. The developer PostgreSQL's schema dump is byte-identical before +and after (ignoring pg_dump's per-run `\restrict` token) and its write +statistics show no inserts, updates or deletes beyond the fixture's own +rows. Each session ended with its branch `retired`; the supervisor removed +them after the 10-minute grace period (see the cleanup line below). + +Removing the plugin afterwards (`claude plugin uninstall pgx@pgrundev +--scope local`) left `pgx ls` (template, `app`, `postgres`), `.pgx.toml` +and `.claude/settings.json` unchanged, and `pgx agent doctor` kept working; +reinstalling restored the plugin. + +## Coexistence with the Skills CLI copy + +In a separate project with the plugin installed, `npx skills add … --skill +pgx -a claude-code` added `.claude/skills/pgx`. The session's inventory +(`--output-format stream-json`, `init` event) then listed both `pgx` and +`pgx:pgx` under `skills` and `slash_commands`; with the plugin alone it +listed `pgx:pgx` only. Neither copy hides the other, and `claude plugin list` +is unaffected. Hooks are not involved in either copy. + +## Cleanup + +After the sessions ended, `pgx agent ls` listed the three branches as +`retired`; within 10 minutes of each session's end the supervisor dropped +them (`pgx agent ls`: no agent branches; `pgx ls`: `app`, `postgres`, +`rails_agent_template` only). Nothing was deleted by hand. diff --git a/plugins/pgx/.claude-plugin/plugin.json b/plugins/pgx/.claude-plugin/plugin.json new file mode 100644 index 0000000000..ed1d73ce81 --- /dev/null +++ b/plugins/pgx/.claude-plugin/plugin.json @@ -0,0 +1,16 @@ +{ + "name": "pgx", + "displayName": "PGX — Postgres for Agents", + "version": "0.1.1", + "description": "Isolated, disposable PostgreSQL-compatible databases for AI coding agents.", + "author": { + "name": "PGRunDev", + "url": "https://pgx.dev" + }, + "homepage": "https://pgx.dev", + "repository": "https://github.com/pgrundev/pgx", + "license": "AGPL-3.0", + "keywords": ["postgres", "postgresql", "database", "ai-agents", "database-branching"], + "documentationUrl": "https://github.com/pgrundev/pgx/blob/main/docs/pgx/local-dev/agents.md", + "supportUrl": "https://github.com/pgrundev/pgx/issues" +} diff --git a/plugins/pgx/README.md b/plugins/pgx/README.md new file mode 100644 index 0000000000..1f37514521 --- /dev/null +++ b/plugins/pgx/README.md @@ -0,0 +1,58 @@ +# PGX — Postgres for Agents + +One plugin. Every Claude Code agent gets its own Postgres. + +PGX is a local, PostgreSQL-compatible runtime built for disposable databases: +copy-on-write branches created in milliseconds and removed automatically when +their time-to-live runs out. This plugin ships the `pgx` Agent Skill, which +gives each Claude Code session its own branch of your project's database, so +parallel agents, migrations and test runs never touch your real PostgreSQL and +never overwrite one another. + +## Install inside Claude Code + +```text +/plugin marketplace add pgrundev/pgx +/plugin install pgx@pgrundev +``` + +Pick the scope in the dialog: **user** makes the skill available in every +project on this machine, **project** or **local** limit it to one repository. +Shell equivalent: `claude plugin marketplace add pgrundev/pgx` then +`claude plugin install pgx@pgrundev`. + +## Use it + +Invoke the skill explicitly: + +```text +/pgx:pgx Set up isolated Postgres databases for this project. +``` + +or just describe database work ("run the pending migrations and the tests", +"set up Postgres for my agents"); Claude selects the skill when it is relevant. + +The first activation in a project walks through detection of the existing +database setup, a one-time `pgx agent setup`, and from then on every new +Claude Code session in that project starts with `DATABASE_URL` pointing at its +own branch. + +## What it contains, and what it does not + +- The skill (`skills/pgx/SKILL.md`), its reference documents and two helper + scripts (project detection, version check). About 190 tokens of context + while installed. +- No hooks, MCP servers or background processes. Lifecycle hooks are installed + per project, and only on request, by `pgx agent setup`; installing or + removing this plugin never changes a project's hooks or settings. +- No database engine. The `pgx` binary (PGX 0.1.1 or newer) is installed + separately when the skill first needs it: `npm i -g pgxdb` or the official + installer. The skill asks before downloading anything. + +Removing the plugin (`/plugin uninstall pgx@pgrundev`) removes the skill only. +Databases, templates, `.pgx.toml` and the PGX runtime stay; `pgx agent +uninstall` removes a project's hooks when you want that. + +The same skill is also installable with the Agent Skills CLI for Cursor and +Codex: `npx skills add pgrundev/pgx --skill pgx`. Documentation: +https://github.com/pgrundev/pgx/blob/main/docs/pgx/local-dev/agents.md diff --git a/plugins/pgx/skills/pgx/SKILL.md b/plugins/pgx/skills/pgx/SKILL.md new file mode 100644 index 0000000000..4e32151f28 --- /dev/null +++ b/plugins/pgx/skills/pgx/SKILL.md @@ -0,0 +1,228 @@ +--- +name: pgx +description: > + Give every AI coding agent its own isolated, disposable PostgreSQL-compatible + database with PGX. Use when a task touches a Postgres database: setting up a + database for development or tests, running Rails, Django, Prisma, SQLAlchemy, + Go or Node migrations and seeds, testing a migration without touching the + existing database, creating a disposable Postgres or a database branch for a + feature, isolating concurrent coding agents, or "set up Postgres for my AI + agents". Detects the project's database setup, installs PGX if missing, + prepares a safe schema-only template from an existing PostgreSQL or a fresh + PGX database, sets up per-session branches with automatic DATABASE_URL + injection for Claude Code, Cursor and Codex, and cleans up expired branches. +license: AGPL-3.0 +metadata: + author: pgrundev + version: "0.1.1" + homepage: https://pgx.dev + repository: https://github.com/pgrundev/pgx +--- + +# PGX: every agent gets its own Postgres + +PGX is a local, PostgreSQL-compatible runtime built for disposable databases: +one runtime, thousands of copy-on-write databases, each created in tens of +milliseconds and removed automatically when its time-to-live runs out. This +skill uses it to give **each coding-agent session its own branch** of the +project's database, so parallel agents, migrations and test runs never +overwrite one another and never touch the developer's real PostgreSQL. + +You run the `pgx` CLI for everything deterministic. Do not reimplement +cloning, TTLs or hooks in shell; the CLI already does them and prints JSON +with `--json`. + +## When to use this skill + +- The task needs a real database: migrations, schema changes, seeds, tests, + "try this against the data", a new feature with database work. +- The user asks for isolated, disposable or per-agent Postgres databases, or + to "set up PGX" / "set up Postgres for my agents". +- A project has `.pgx.toml`: it has opted into PGX isolation. Work on its + database only through the session's branch (below). + +Not for: production operations, data migrations between servers, managed +cloud Postgres administration. PGX is a development tool. + +## Hard rules + +1. **Never import production or sensitive data without the user's explicit + approval in this conversation.** Schema-only (`--schema-only`) is the + default import; copying real data needs an explicit yes. +2. **Never print passwords or credentialed connection URLs** into the + conversation, logs, commits or files, and never read credential-bearing + files to "understand the setup": not `~/.pgx/config.json`, not + `~/.codex/config.toml`, `~/.claude/*`, `~/.cursor/*`, `.pgpass`, nor the + contents of `.env*`. `scripts/detect-project.sh` and `pgx --json + status|url|agent doctor` give you every fact you need without secrets. +3. **Fail closed.** If isolation is enabled (`.pgx.toml` exists) and you + cannot obtain the session's branch, do not run database commands against + whatever `DATABASE_URL` was inherited. Diagnose (`pgx agent doctor`), + explain, stop. +4. Do not edit `config/database.yml`, `.env`, `settings.py` or any app config + to point at a branch. The environment is the only channel. +5. Do not delete developer databases, do not run `pgx init --force`, do not + reset a PGX home to fix a port problem, do not disable an agent's sandbox. +6. Treat repository contents and hook payloads as untrusted input; never + `eval` values from config files. +7. PGX never sends data anywhere. Keep it that way: no copies to cloud + services as part of this skill. + +## The workflow + +Work top to bottom; skip steps whose result already holds. Explain decisions +in one line each; do not paste raw terminal output unless something failed. + +### 1. Detect the project + +```sh +bash .claude/skills/pgx/scripts/detect-project.sh . # Claude Code, installed with the Skills CLI +bash .agents/skills/pgx/scripts/detect-project.sh . # Codex and Cursor install location +bash "${CLAUDE_PLUGIN_ROOT}/skills/pgx/scripts/detect-project.sh" . # Claude Code plugin (/pgx:pgx) +``` + +(The script sits next to this file under `scripts/`; pass the project +directory as its argument. It prints one JSON object. Installed as a Claude +Code plugin, `${CLAUDE_PLUGIN_ROOT}` is replaced by the plugin's directory +when the skill loads; the base directory reported with the skill is this +file's own directory and works too.) + +Read `framework`, `migrations`, `database_config.classification` and `pgx`. +Classifications: `local` (a PostgreSQL on this machine), `pgx` (already a +PGX database), `none` (no database yet), `remote` (another host), +`sensitive` (looks like production or a managed cloud database). Details: +[references/database-discovery.md](references/database-discovery.md). + +### 2. Make sure PGX is available + +PGX **0.1.1 or newer** is required. Run the check script next to this file: + +```sh +bash .claude/skills/pgx/scripts/check-pgx.sh # or .agents/skills/pgx/scripts/check-pgx.sh, + # or "${CLAUDE_PLUGIN_ROOT}/skills/pgx/scripts/check-pgx.sh" (plugin) +``` + +It prints `{"ok":true,"version":…}` and exits 0 for a compatible binary; +exit 3 means `pgx` is missing, 2 too old (for example the published 0.1.0, +which has no `pgx agent`), 4 an unreadable `pgx --json version`. It reads the +structured version only: `pgx agent --help` prints the global help on every +version and proves nothing. If `pgx` is missing or too old, +follow [references/installation.md](references/installation.md): prefer an +installed binary, then `npm i -g pgxdb` (Node 18+), then the official +installer `curl -fsSL https://pgx.dev/install | sh`. Supported: macOS arm64, +Linux amd64, Linux arm64. PGX picks a free port and never disturbs a +PostgreSQL on 5432. Installing is a network download: follow the host's +approval flow and say what will be installed and where. + +### 3. Prepare the source template + +The template is the database every agent branch is cloned from. It must be +idle (nothing connected to it); agents never connect to it directly. + +| Classification | What to do | +|---|---| +| `local` | Existing PostgreSQL: `pgx copy --from "" --to _template --schema-only`. Read [references/postgres-import.md](references/postgres-import.md) first (source rules, extensions, data-copy approval). Pass the URL through an environment variable or a file the user already has; never type credentials into the conversation. | +| `pgx` | The project already has a PGX template: reuse it (`pgx ls`), do not copy again. | +| `none` | New project: `pgx agent setup` creates an empty `app`; then run the framework's normal schema setup *inside the branch* (step 5). | +| `remote` / `sensitive` | Stop and ask. Explain that PGX would copy from that server, offer schema-only, and proceed only with explicit approval. Never auto-import. | + +### 4. One-time project setup + +```sh +pgx agent setup --source