Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ npx pgxdb@latest
<!-- skills.sh badge: add [![skills.sh](https://skills.sh/b/pgrundev/pgx)](https://skills.sh/pgrundev/pgx) once https://skills.sh/pgrundev/pgx lists the skill -->

<p align="center">
<sub>Open source · Free · v0.1.1 · For disposable databases, not production data</sub>
<sub>Open source · Free · v0.1.2 · For disposable databases, not production data</sub>
</p>

PGX is a database runtime for short-lived Postgres databases: agent
Expand Down Expand Up @@ -279,8 +279,8 @@ applies to memory and to storage alike.

## Status

PGX is at **v0.1.1**, an early release with known limitations listed in the
[release notes](https://github.com/pgrundev/pgx/releases/tag/v0.1.1). It
PGX is at **v0.1.2**, an early release with known limitations listed in the
[release notes](https://github.com/pgrundev/pgx/releases/tag/v0.1.2). It
already powers PGX branches in PGRun. The current focus is PostgreSQL compatibility,
Rails/application compatibility, concurrency semantics, lifecycle
correctness, predictable resource containment and real agent workloads.
Expand Down Expand Up @@ -444,7 +444,7 @@ your permissions allow it.
| Cursor | hooks installed; `pgx agent exec --` when `PGX_ISOLATION` is unset | env propagation pending live verification |
| Codex | `pgx agent exec -- codex` (Codex hooks cannot set environment) | wrapper verified |

Requires PGX 0.1.1 or newer ([release v0.1.1](https://github.com/pgrundev/pgx/releases/tag/v0.1.1)); the Skill checks the installed version before it does anything.
Requires PGX 0.1.2 or newer ([release v0.1.2](https://github.com/pgrundev/pgx/releases/tag/v0.1.2); 0.1.1 isolates sessions but lets subagents share the parent's branch); the Skill checks the installed version before it does anything.
Details, the lifecycle, security rules and the validation notes:
[`docs/pgx/local-dev/agents.md`](docs/pgx/local-dev/agents.md). The Skill
itself: [`skills/pgx/SKILL.md`](skills/pgx/SKILL.md).
Expand Down
2 changes: 1 addition & 1 deletion crates/bin/pgx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pgx"
version = "0.1.1"
version = "0.1.2"
edition.workspace = true
publish.workspace = true
description = "PGX command-line interface: a local, disposable, PostgreSQL-compatible runtime"
Expand Down
2 changes: 1 addition & 1 deletion dist/npm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pgxdb",
"version": "0.1.1",
"version": "0.1.2",
"description": "PGX: a local, disposable, PostgreSQL-compatible runtime. `npx pgxdb` installs the native binary and starts a database.",
"license": "AGPL-3.0",
"repository": {
Expand Down
81 changes: 81 additions & 0 deletions dist/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,87 @@
A self-contained, relocatable, PostgreSQL 18 compatible runtime for local
development, CI and disposable databases. No system PostgreSQL required.

## PGX v0.1.2 — Every AI Subagent Gets Its Own Postgres

0.1.1 gave every Claude Code **session** its own branch. Subagents launched
from that session inherited the session's identity and therefore its
database: three parallel subagents, one database. 0.1.2 gives every Claude
Code **subagent** its own branch, with nothing to configure and nothing for
the model to do:

- **One branch per subagent.** Identity is `(project, host, session, agent)`;
a subagent's branch is `agent-<host>-<session8>-<agent8>`, a copy-on-write
clone of the same template. The session's branch keeps its name and records.
- **Hooks.** `pgx agent setup` / `pgx agent install claude` now writes six
Claude Code hooks (an existing four-hook installation is completed in place,
nothing duplicated): `SubagentStart` creates the subagent's branch and tells
the model its name, `PreToolUse` (Bash) runs each subagent command through
`pgx agent exec --agent <id> --cwd <project> -- <shell> -c '<command>'` so
it sees that branch's `DATABASE_URL`/`PG*`, and `SubagentStop` retires the
branch after terminating whatever it left connected. If a branch cannot be
ensured the command is refused with the reason; it never runs against the
parent's database.
- **Killed agents cannot commit later.** Every agent branch carries
`client_connection_check_interval` (5 s), `idle_in_transaction_session_timeout`
(15 min) and `statement_timeout` (1 h), set with `ALTER DATABASE … SET` and
adjustable or disableable in `.pgx.toml`; the template is never altered.
`pgx agent down` terminates the branch's backends before retiring or
dropping and reports `backends_terminated` / `backends_remaining`.
- **CLI.** `pgx agent exec`: explicit-id branches are labelled `exec`, `--keep`
leaves the branch active for its idle TTL (the next `exec` with the same
`--id` attaches to it), `--json` adds `agent_id`, `source`, `created`,
`fresh`, `method`, `elapsed_ms`, `status`; `PGSERVICE`/`PGSERVICEFILE` are
cleared in the child and the password only ever travels in the environment.
`pgx agent down --id` finds a branch under any host label, `--branch <name>`
refuses to act on any other branch, `--agent <id>` on every lifecycle
command. `pgx agent ls` shows an AGENT column and `deadline_kind`;
`pgx agent doctor` reports subagent branches and the new hook audit log
(`~/.pgx/agent/hooks.log`, ids and outcomes only).
- **Skill.** The PGX Agent Skill (Skills CLI and the Claude Code plugin,
both 0.1.2) requires PGX 0.1.2: with a 0.1.1 binary it refuses database
work and says why (session isolation only, subagents would share the
parent's branch), instead of promising isolation it cannot deliver.

### Verified with real Claude Code subagents (2026-10-26)

- 3 and then **20 concurrent subagents**, no ids, no manual provisioning:
**20/20** branches created by `SubagentStart`, **20/20** workloads in their
own branch, **zero cross-agent contamination**, 20/20 retired by
`SubagentStop`; **37 s** end to end for the 20-agent run; **92 MB** peak
PGX runtime RSS; the template and the developer database unchanged
(schema md5 identical before and after); temporary storage reclaimed after
the grace period.
- Provisioning measured **p50 1,231 ms / p95 1,371 ms / max 1,401 ms** when
all twenty branches started in the same instant. That is end-to-end hook
time under 20-way concurrency, not raw clone latency: a single branch
provisions in about 250 ms, and `pgx branch` on an idle runtime clones in
under 30 ms.
- A subagent killed mid-transaction (`BEGIN … pg_sleep … COMMIT` interrupted
by TaskStop) left a backend that aborted within the tested five-second
guard with nothing committed; on 0.1.1 the same scenario committed eight
minutes after the kill.
- Evidence and method: `docs/pgx/local-dev/validation/2026-10-26-subagent-isolation-live.md`.

### Known limitations

1. Claude Code evaluates permission rules, and in auto mode its classifier,
on the **rewritten** Bash command. Some subagent commands may therefore
ask for approval, or be refused by the auto-mode classifier, where the
unwrapped command would not have. The hook never approves anything.
2. Do **not** add a broad allow rule such as `Bash(pgx agent exec:*)` on an
agent's say-so: it would approve any command wrapped that way. Whether to
allow the wrapper, and for which path, is the user's decision.
3. A subagent stopped by force (`TaskStop`) does not always produce
`SubagentStop`; its branch stays on the idle TTL and the server-side
guards protect the data until the supervisor removes it.
4. The server-side cancellation is a bounded guard, not an unconditional
guarantee: a backend already past the point of no return of a COMMIT
still completes it, and the guards fire within their intervals, not
instantly. The documented guarantee begins when `pgx agent down` returns.
5. Cursor and Codex subagent auto-isolation is not live-verified in this
release; the hooks and `pgx agent exec --agent` are available there, and
session-level isolation is unchanged.

## What is new in 0.1.1: one Skill, every agent gets its own Postgres

```sh
Expand Down
16 changes: 9 additions & 7 deletions docs/pgx/local-dev/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ the Skill is activated and the host's permissions allow it.

## Versions

`pgx agent` and the Skill need **PGX 0.1.1 or newer**
([release](https://github.com/pgrundev/pgx/releases/tag/v0.1.1): linux-amd64,
linux-arm64, darwin-arm64 with SHA-256 checksums). The Skill's
`scripts/check-pgx.sh` verifies the installed binary from `pgx --json version`
and refuses older ones (the published 0.1.0 has no `pgx agent`). npm
`pgxdb@0.1.1` follows the GitHub release through the repository's staged
publishing process.
`pgx agent` and the Skill need **PGX 0.1.2 or newer**
([release](https://github.com/pgrundev/pgx/releases/tag/v0.1.2): linux-amd64,
linux-arm64, darwin-arm64 with SHA-256 checksums). 0.1.2 is the first
release in which Claude Code subagents get their own branches: 0.1.1
isolated sessions but let subagents share the parent's branch, and the
published 0.1.0 has no `pgx agent`. The Skill's `scripts/check-pgx.sh`
verifies the installed binary from `pgx --json version` and refuses older
ones with a hint naming what they lack. npm `pgxdb@0.1.2` follows the GitHub
release through the repository's staged publishing process.

## What you get

Expand Down
8 changes: 4 additions & 4 deletions docs/pgx/local-dev/claude-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ Then, in a project with a database:
`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
project, check for PGX 0.1.2 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 list # pgx@pgrundev Version: 0.1.2 Status: enabled
claude plugin details pgx # Component inventory: Skills (1) pgx, Hooks (0), MCP servers (0)
```

Expand All @@ -52,7 +52,7 @@ claude plugin details pgx # Component inventory: Skills (1) pgx, Hooks (0),
- `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
- `.claude-plugin/plugin.json`: name `pgx`, version `0.1.2` (the Skill's
version), display name, links.
- `README.md`.

Expand Down Expand Up @@ -152,7 +152,7 @@ and this repository:
| 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 |
| Functionality | One Agent Skill: detects the project's database setup, installs the PGX runtime on request (PGX 0.1.2+), 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 |
Expand Down
2 changes: 1 addition & 1 deletion plugins/pgx/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pgx",
"displayName": "PGX — Postgres for Agents",
"version": "0.1.1",
"version": "0.1.2",
"description": "Isolated, disposable PostgreSQL-compatible databases for AI coding agents.",
"author": {
"name": "PGRunDev",
Expand Down
2 changes: 1 addition & 1 deletion plugins/pgx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ own branch.
- 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
- No database engine. The `pgx` binary (PGX 0.1.2 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.

Expand Down
11 changes: 7 additions & 4 deletions plugins/pgx/skills/pgx/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ description: >
license: AGPL-3.0
metadata:
author: pgrundev
version: "0.1.1"
version: "0.1.2"
homepage: https://pgx.dev
repository: https://github.com/pgrundev/pgx
---
Expand Down Expand Up @@ -95,16 +95,19 @@ PGX database), `none` (no database yet), `remote` (another host),

### 2. Make sure PGX is available

PGX **0.1.1 or newer** is required. Run the check script next to this file:
PGX **0.1.2 or newer** is required. 0.1.1 isolates sessions but not Claude
Code subagents (they shared the parent's branch); 0.1.0 has no `pgx agent`
at all. 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
exit 3 means `pgx` is missing, 2 too old (0.1.1: session isolation only,
subagents would share the parent's branch; 0.1.0: 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
Expand Down
7 changes: 5 additions & 2 deletions plugins/pgx/skills/pgx/references/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ command -v pgx && pgx --json version # {"pgx_version":"0.1.x", …}
pgx --json status # exit 3 when initialised but stopped; hooks start it on demand
```

The skill needs **PGX 0.1.1 or newer**, the first release with the
`pgx agent` command group (https://github.com/pgrundev/pgx/releases/tag/v0.1.1).
The skill needs **PGX 0.1.2 or newer**
(https://github.com/pgrundev/pgx/releases/tag/v0.1.2): the first release
in which Claude Code subagents get their own branches (0.1.1 isolated
sessions only and let subagents share the parent's branch; 0.1.0 has no
`pgx agent` command group).
`scripts/check-pgx.sh` decides: exit 0 compatible, 3 missing, 2 too old, 4
malformed, always with one JSON line. It compares `pgx --json version` →
`pgx_version` as semver (`PGX_MIN_VERSION` overrides the floor). Do not use
Expand Down
16 changes: 12 additions & 4 deletions plugins/pgx/skills/pgx/scripts/check-pgx.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/usr/bin/env bash
# check-pgx.sh: is a compatible PGX on PATH? Prints one JSON object and exits
# 0 compatible (version >= MIN) {"ok":true,"version":"0.1.1","path":"…"}
# 0 compatible (version >= MIN) {"ok":true,"version":"0.1.2","path":"…"}
# 3 pgx not found {"ok":false,"reason":"missing",…}
# 2 too old {"ok":false,"reason":"too_old","version":"0.1.0",…}
# 2 too old {"ok":false,"reason":"too_old","version":"0.1.1",…}
# 4 unreadable version output {"ok":false,"reason":"malformed",…}
# `pgx agent --help` exits 0 on every PGX version (global help), so only the
# structured `pgx --json version` output counts.
set -u
MIN=${PGX_MIN_VERSION:-0.1.1}
MIN=${PGX_MIN_VERSION:-0.1.2}
esc() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }
path=$(command -v pgx 2>/dev/null || true)
if [ -z "$path" ]; then
Expand All @@ -28,4 +28,12 @@ vcmp() { # returns 0 if $1 >= $2
if vcmp "$ver" "$MIN"; then
printf '{"ok":true,"version":"%s","path":"%s","min":"%s"}\n' "$ver" "$(esc "$path")" "$MIN"; exit 0
fi
printf '{"ok":false,"reason":"too_old","version":"%s","path":"%s","min":"%s","hint":"PGX %s has no pgx agent; upgrade with the method it was installed with (npm i -g pgxdb@latest, or the installer again)"}\n' "$ver" "$(esc "$path")" "$MIN" "$ver"; exit 2
# Too old. Say what the installed version lacks: 0.1.1 isolated sessions but
# let Claude Code subagents share the parent's branch; anything older has no
# `pgx agent` at all. Either way: upgrade, do not run database work.
if vcmp "$ver" "0.1.1"; then
why="PGX $ver isolates sessions only: Claude Code subagents would share the parent's branch"
else
why="PGX $ver has no pgx agent"
fi
printf '{"ok":false,"reason":"too_old","version":"%s","path":"%s","min":"%s","hint":"%s; upgrade to %s or newer with the method it was installed with (npm i -g pgxdb@latest, or the installer again)"}\n' "$ver" "$(esc "$path")" "$MIN" "$why" "$MIN"; exit 2
11 changes: 7 additions & 4 deletions skills/pgx/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ description: >
license: AGPL-3.0
metadata:
author: pgrundev
version: "0.1.1"
version: "0.1.2"
homepage: https://pgx.dev
repository: https://github.com/pgrundev/pgx
---
Expand Down Expand Up @@ -95,16 +95,19 @@ PGX database), `none` (no database yet), `remote` (another host),

### 2. Make sure PGX is available

PGX **0.1.1 or newer** is required. Run the check script next to this file:
PGX **0.1.2 or newer** is required. 0.1.1 isolates sessions but not Claude
Code subagents (they shared the parent's branch); 0.1.0 has no `pgx agent`
at all. 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
exit 3 means `pgx` is missing, 2 too old (0.1.1: session isolation only,
subagents would share the parent's branch; 0.1.0: 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
Expand Down
7 changes: 5 additions & 2 deletions skills/pgx/references/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ command -v pgx && pgx --json version # {"pgx_version":"0.1.x", …}
pgx --json status # exit 3 when initialised but stopped; hooks start it on demand
```

The skill needs **PGX 0.1.1 or newer**, the first release with the
`pgx agent` command group (https://github.com/pgrundev/pgx/releases/tag/v0.1.1).
The skill needs **PGX 0.1.2 or newer**
(https://github.com/pgrundev/pgx/releases/tag/v0.1.2): the first release
in which Claude Code subagents get their own branches (0.1.1 isolated
sessions only and let subagents share the parent's branch; 0.1.0 has no
`pgx agent` command group).
`scripts/check-pgx.sh` decides: exit 0 compatible, 3 missing, 2 too old, 4
malformed, always with one JSON line. It compares `pgx --json version` →
`pgx_version` as semver (`PGX_MIN_VERSION` overrides the floor). Do not use
Expand Down
Loading
Loading