Warning
Already on v3.0.x? A plain /plugin update is all you need — skip this box.
Coming from v2.x, do not run claude plugin update on its own. v3
introduced two compatibility plugins (ecto, lv) that v2 never declared,
and claude plugin update does not install dependencies a new version newly
declares. The plugin then fails to load entirely — you lose all 36 /phx:*
commands, not just /ecto:* and /lv:*. Install the two first, in this
order:
claude plugin marketplace update oliver-kriska
claude plugin install ecto@oliver-kriska
claude plugin install lv@oliver-kriska
claude plugin update elixir-phoenix@oliver-kriskaAlready updated in the wrong order and seeing ✘ failed to load? Nothing is
lost — claude plugin install ecto@oliver-kriska then
claude plugin install lv@oliver-kriska recovers it (one dependency per
invocation).
A fifth runtime target (DeepSeek Harness), the first user-facing hook
documentation, and a native Amp phx-watch-pr lifecycle.
Added
-
DeepSeek Harness (dsh) target (#139) — a fifth generated runtime target
attargets/dsh/, projecting all 51 canonical skills with their complete
resource subtrees. dsh'sdsh-skill-filesystemprovider scans
.agents/skillsand friends for single-level<name>/SKILL.mdbundles, and
its pre-step boundary injects the full body for a whitespace-bounded
/phx-*token, so the plugin's command surface survives intact. dsh also
readsCLAUDE.mdnatively, so/phx:initoutput needs no porting. Adds
scripts/port_lib/dsh.py,scripts/build_dsh_skills.py, twelve tests in
scripts/tests/test_dsh.py,make dsh-skills{,-sync,-validate}wired into
generated-skills-syncandci, an optionalmake dsh-runtime-smokethat
verifies discovery over dsh's loopback/apiRPC bridge (session.createthen
skill.list, no API key needed), a golden snapshot entry,docs/dsh.md, and
adshcolumn indocs/runtime-support.md. Two dsh-specific build gates:
descriptions are capped at the 500-charcatalogDescriptionMaxLength(dsh
truncates silently past it) and nestedSKILL.mdfiles are rejected (dsh
discovery is deliberately one level deep). Skills-only by design — dsh has no
markdown agent registry, and its Claude Code hook bridge covers 7 of 30 events
while droppingif:gating, so neither the 26 agents nor the 30 hooks ship.
Tested against dsh0.1.1-rc.2, a developer preview. -
Hook documentation — the 23 hooks across 10 lifecycle events had no
user-facing docs; the reasoning lived only in script header comments and a
terse contributor checklist. AddsHOOKS.mdat the repo root (what fires
when, a lifecycle diagram, the full hook table, escape hatches),
plugins/elixir-phoenix/hooks/README.md(per-event output-channel table and
the shared conventions:mix.exsgating, the fail-open contract,if
conditions, blame-aware scanning), and six per-group deep dives under
plugins/elixir-phoenix/hooks/docs/— safety gates, code quality, failure
recovery, context injection, session lifecycle, workflow state. Each records
the incident or measurement the hook came from (issue #55 cross-project
bleed, issue #61--force-with-lease, issue #38 progress.md cross-writes,
the ~0% CLAUDE.md routing finding).CLAUDE.mdnow requires these docs to be
updated in the same commit as any hook change. -
Amp-native
phx-watch-prlifecycle — the deterministic Amp target now
includes a focused Plugin API runtime that acquires an Orb keep-alive lease,
persists watch state across reloads, filters deployment-like checks out of
readiness, detects unresolved review threads and required CI failures, and
serializes--fixevents back into the same worker thread. Defaults are a
60-second poll, 15-minute activity-based quiet period, and 2-hour hard
active-watch cap; head pushes, required-check transitions, reviews, and
comments restart quiet so delayed reviews cannot be hidden by an early green
snapshot without waking inference for routine progress. Deployment-only
transitions remain status-visible but silent. Every terminal path releases
the lease, and the plugin never blindly reruns shared CI, merges, or deploys.
An optional durable Amp webhook can reactivate a completed watch after the
Orb pauses only when the event identifies the exact watched PR or head SHA;
repository webhook configuration remains an explicit external administrator
action. -
README links phxagents.dev above the fold — a docs badge, a one-line
Docs block pointing at/install/,/compatibility/,/iron-laws/and
/catalog/, and a per-runtime install-guide link in each of the four
"Using Amp/Codex/Pi/OpenCode?" callouts. The README had zero
phxagents.devmentions across 1,056 lines while being the project's
higher-traffic discovery surface: over 08/02-08/15, Google sent 56 unique
visitors to the repo versus 14 from the docs site, so everyone arriving from
search read the whole README and never learned the docs site exists. The
repo's About → Website field was already set. -
Deterministic Amp workflow plugin — the generated Amp target now includes
40 workflow palette commands, five read-only domain specialists, bounded
parallel review and investigation, a persistent classified edit lock, and a
boundedphx-fullverification gate. The standalone distribution promotes a
validatedstablebranch for direct GitHub installation.
Changed
-
route-intent.shtimeout raised 10s → 30s — theUserPromptSubmit
intent-routing hook had the tightest budget of any hook in the plugin despite
sitting on the latency path of every prompt. It normally finishes in well
under 100ms (it truncates the prompt to 4000 chars before scanning), but a
timeout drops the routing hint silently, so the extra headroom costs nothing
on the common path and avoids losing suggestions on a slow first run. The
hook already exits 0 on every path — aUserPromptSubmithook must never
exit 2, which would erase the user's prompt. -
Release bodies now carry a docs-site footer — the
releasecontributor
skill gained an Iron Law and aprintfstep that appends
<https://phxagents.dev>to the extracted CHANGELOG release notes. A release
body is read at the moment someone decides whether to install, and releases
are this project's one promotion lever with a measured effect: v3.0.1 drove
unique cloners from 51 to 120 in a single day (2.4x), decaying to baseline
over about four days. -
Amp installation profiles and scope names now match current Amp — docs
distinguish hosted-native from paired-full behavior, use nativeskill: invokefor deterministic hosted skill loading, and separate machine-local
--globalinstalls from personal/workspace hosted repositories. The public
standalone repository, generated target, gatedstablebranch, paired local
install, and GitHub/curl fallback remain supported. -
deep-bug-investigatorsynthesizes on opus, its four tracks run on sonnet
(thanks @BugsBunny338, #133) — the agent coordinates four parallel
investigation tracks and then reconciles their often-conflicting evidence.
Cross-track synthesis is where the stronger model earns its cost, and
hard-to-reproduce bugs are where a weak synthesis is most expensive. The
frontmatter bump alone would have been the wrong fix: the tracks spawn as
baregeneral-purposesubagents, which default tomodel: inheritand so
resolve to the spawning parent's model — opus on the orchestrator would
have silently promoted the whole fan-out to five opus contexts. The tracks
are now pinned tomodel: "sonnet"explicitly, keeping fan-out cost where it
was: sonnet gathers evidence, opus synthesizes.effort: mediumis
unchanged; the eval allowlists opus for orchestrators, so no symmetry fix is
owed. -
workflow-orchestratorpins its COMPOUNDING spawn to sonnet — same
inheritance leak as above, found while reviewing #133. The orchestrator runs
on opus and spawned an unpinnedgeneral-purposesubagent to write solution
docs, so that mechanical phase was silently billed at opus. Namedphx:*
subagents were never affected — their own frontmatter wins — so
parallel-reviewerandplanning-orchestratorneeded no change. -
The
releasecontributor skill hoists upgrade warnings to the top of the
release body — a new Iron Law and template: when a release needs anything
beyond/plugin update, the body opens with a> [!WARNING]block carrying
the exact commands, and states the blast radius in what the user loses rather
than in mechanism. v3.0.0 documented its staged upgrade correctly but placed
it at roughly line 145 of a long changelog dump, phrased as "a temporary
missing-dependency state" — and users upgraded into a broken install anyway
(#135). A correct instruction nobody reaches is indistinguishable from a
missing one. -
CLAUDE.md model-tier rules describe the actual split — the guidance said
"opus for primary workflow orchestrators, sonnet for secondary orchestrators
(investigation, tracing)", which stopped matching the plugin once
planning-orchestratormoved to sonnet anddeep-bug-investigatormoved to
opus. The rule is now stated in terms of what earns opus (synthesis across
parallel workers) and names the four agents on each side, plus the
general-purposepinning requirement that follows from it.
Fixed
-
Canonical skills told every runtime to run Claude Code's
/mcp(#141) —
tidewave-integration/SKILL.md(Iron Law 3) andexamples/SKILL.mdboth used
/mcpto check MCP availability, and shipped byte-identical to all five
generated targets, where that command does not exist. Iron Law 3 now reads
"Call Tidewave only when matchingmcp__tidewave__*tools are present" — a
check that works on every runtime — and theexamplesfence drops the probe
for a# Requires connected mcp__tidewave__* toolsnote, switching from abash
fence to atextone since its contents are tool invocations rather than
shell. The one remaining mention stays, already qualified with "in Claude
Code". Found while reviewing #140; fixing it in one target would have broken
the test asserting the two Agent Skills projections differ only by the
runtime name. -
The
phx-watch-prharness test was one second from red — it ran with a
60-second subprocess timeout and takes ~59 seconds of wall time for ~3 seconds
of CPU: the harness drives a fake clock with real 80ms flushes, andadvance()
performs up to 21 of them across 23 calls. Observed locally at 58.9s, 60.4s,
and 73.9s on consecutive runs, so it passes or fails on runner load alone —
and it is a required check, meaning it would have started blocking unrelated
PRs. Raised to 240s; the harness itself is unchanged, since shortening the
flush would trade a timeout flake for a race. -
The
phx-watch-prinstall command could never have worked — README and
docs/amp.mdtold users to runamp plugins addagainst a
raw.githubusercontent.comURL. Amp0.0.1787045288rejects that with
For now, only https://ampcode.com/@amp/plugins/*.ts ... URLs are allowedand
writes nothing. The samedocs/amp.mdalready said, 390 lines further down,
that "Amp currently restrictsamp plugins add... to Amp-hosted plugins" —
the file contradicted itself, and the install instruction was the wrong half.
Both call sites now use the atomiccurl+mvpattern already documented
forelixir-phoenix.ts, pointing at the standalone repository'sstable
branch. The update section covers both plugins instead of only the workflow
one. -
Upgrading from v2.x no longer lands users in a dead install (reported by
@barquesurlocean, #135) — v3.0.0 renamed the plugin manifest tophx(which
is what makes/phx:*correct; pre-v3 versions namespaced their commands as
/elixir-phoenix:*while/phx:initwrote/phx:*intoCLAUDE.md) and in
the same commit introduced theectoandlvcompatibility plugins as
manifestdependencies. Adding a dependency turns out to be a breaking
change for already-installed users:claude plugin updatedoes not
install dependencies a new version newly declares, and a missing dependency
is a hard load failure, so the obvious/plugin updateleaves the plugin at
✘ failed to loadwith all 36/phx:*commands gone — taken down by the 3
compatibility commands. Verified on Claude Code 2.1.234, so this is not the
2.1.76–2.1.109 version band recorded during #130; it affects every v2 user on
every Claude Code version. Nothing self-heals either, because auto-update is
off by default for non-Anthropic marketplaces. The README's staged upgrade
block was already correct but described the failure as "a missing-dependency
state"; it now leads with a warning, states the blast radius in commands
lost, declares the 2.1.110 version floor, adds a recovery path for anyone who
already updated in the wrong order, and explains the/phx:vs
/elixir-phoenix:prefix history. Note during recovery that
claude plugin install elixir-phoenix@oliver-kriskaresolves only one
missing dependency per invocation. -
make validatecovers every plugin manifest — the target validated
plugins/elixir-phoenixand the marketplace only, soplugins/ecto,
plugins/lv, andplugins/catchupcould ship a schema violation that CI
never saw. This is exactly howdisplayNamereached users: it was present in
all four Claude-facing manifests while the gate looked at one of them. All
five manifests are validated now. -
Amp wrapper skill resolution follows supported local precedence — the
generated plugin now checks machine-local skill roots before workspace roots
and searches.agents/skillsand.claude/skillsthrough the parent
directories exposed fromworkspaceRoot. Docs explicitly call out sources
the Plugin API cannot resolve, including hosted repositories, built-ins,
plugin caches, customamp.skills.path, and nested invocation roots that are
not exposed to plugins. -
displayNameremoved from all Claude Code manifests (reported by
@ndrean, #130) — the field was introduced alongside the v3 plugin split and
reported as an install blocker one day later. It is undocumented: it appears
nowhere in the plugin manifest schema, whose metadata fields areversion,
description,author,homepage,repository,license, andkeywords.
It is also inert —claude plugin listrenders the pluginname, never
displayName— and Anthropic's own marketplace uses it in 3 of 285 entries,
always inmarketplace.jsonand never in aplugin.json, which is exactly
where this repo had it.catchuphad already been shipping without it. A
clean install from GitHub could not be reproduced as broken on 2.1.227, so
the original failure was likely specific to the Claude Code range current in
late July; the field is gone regardless, since nothing depended on it. The
Codex manifests (targets/codex/.codex-plugin/plugin.json,
.agents/plugins/marketplace.json) keep theirs — different runtime,
different schema, where it is nested underinterface.
Docs, install guides, and the runtime compatibility matrix: https://phxagents.dev