| name | bump-pipelex |
| description | Moves this repo's `pipelex` dependency pin to the latest release on PyPI (or a version you name), re-locks, migrates `.pipelex/` config if the schema moved, runs the checks, and writes the CHANGELOG entry — stopping before the commit. Use whenever the user says "bump pipelex", "update pipelex", "upgrade pipelex", "pin pipelex to 0.48.0", "get us on the latest pipelex", "what's the latest pipelex", "is our pipelex out of date", "move off the git pin", or asks to build against a newly published pipelex release. Also use when a failure looks like a pipelex version mismatch — a `TypeError` about a missing keyword-only argument from the runtime, an `extra="forbid"` rejection, or a `StorageConfigError` at boot. This is about the **pipelex dependency**, not about releasing pipelex-api itself; releasing this package is the `release` skill.
|
Bump the pipelex dependency
This server is a thin FastAPI wrapper over the pipelex library, pinned to one
exact version. Bumping that pin is routine but not mechanical: pipelex is pre-1.0
and ships breaking changes without a deprecation window, and some of its models
are on this server's wire, so a bump can legitimately move the committed OpenAPI
artifact and the on-disk config format at the same time.
The job is to land the new pin in a state a human can read and commit: pin moved,
lock regenerated, config migrated, checks green, changelog written. Stop before
committing — the user stages and commits.
What "bumping pipelex" touches
| File | Why it moves |
|---|
pyproject.toml | The pin itself, in [project].dependencies — pipelex[<extras>]==X.Y.Z |
pyproject.toml | A [tool.uv.sources] block, if one is pinning pipelex to a git rev — that has to go |
uv.lock | Regenerated by make li |
docs/openapi/pipelex-api.openapi.yaml | Only if pipelex models that reach the wire changed shape |
.pipelex/*.toml | Only if the config schema narrowed — pipelex migrate handles it |
CHANGELOG.md | An entry under ## [Unreleased] saying what moved and what it costs a caller |
Do not touch [project].version. That is this package's own version and it
moves only at release time, via the release skill. Conflating the two is the
single most common way this task goes wrong.
Workflow
1. Orient
Read the current pin — the line in pyproject.toml matching ^ "pipelex\[.
Read it from the file, never from the virtualenv: .venv routinely lags the pin
(someone edited pyproject.toml without re-running make li), so the installed
version answers a different question than the one being asked.
Check git status. Uncommitted work in the tree is normal here — the user often
has concurrent work in the same worktree. Note what was already dirty before
you start, so the diff you report at the end separates your changes from theirs
and so you never stage something that isn't yours.
Also check whether [tool.uv.sources] names pipelex. If it does, this repo is
currently building against an unreleased git commit, and moving to PyPI means
removing that block — see step 3.
2. Resolve the target version
If the user named a version, use it. Otherwise ask PyPI:
curl -s https://pypi.org/pypi/pipelex/json \
| python3 -c "import json,sys; print(json.load(sys.stdin)['info']['version'])"
info.version is the latest non-prerelease, which is what "latest" should mean
here — a server that other people deploy has no business riding an rc by
accident. If the user explicitly wants a prerelease, list the candidates from
releases in that same JSON and let them pick.
If the resolved version equals the current pin, say so and stop. There is nothing
to do, and manufacturing a no-op lock churn is worse than reporting "already
current". Mention what the installed venv has if it disagrees, since that is a
real thing to fix with make li even when the pin is right.
3. Move the pin
Edit the version in place and keep the extras exactly as they are:
"pipelex[mistralai,anthropic,google,google-genai,bedrock,fal]==0.48.0",
The extras list is load-bearing and easy to lose when retyping the line. Each one
pulls an inference provider's SDK; extras never travel through a transitive
dependency, so dropping one produces an image that imports fine and then fails at
the first request that reaches that provider. Change the digits and nothing else —
substituting only the version substring cannot drop an extra, whereas rewriting
the line can.
So make it a substring edit: on that line, replace ==0.47.0" with ==0.48.0"
and leave every other character alone. The pinned version string appears once in
the file, so the match is unambiguous. Use your editor rather than a shell
one-liner — sed -i takes a separate empty argument on macOS and an attached
suffix on GNU/Linux, so no single invocation is portable, and the release skill
edits this same file the same way.
Confirm the result with grep '"pipelex\[' pyproject.toml before moving on.
If [tool.uv.sources] pins pipelex to a git rev, delete the whole block
(along with the comment explaining it). This matters more than it looks: in uv, a
source wins over a version specifier. Leaving it means the ==0.48.0 you just
wrote is decorative — uv keeps resolving the git commit, make li succeeds, the
checks pass, and you report a bump that did not happen. Those blocks are written
as temporary and are meant to be stripped the moment the work lands on PyPI;
they usually carry a comment saying exactly that.
4. Re-lock and install
make li
That is uv lock + uv sync, so it both rewrites uv.lock and puts the new
pipelex in .venv, which everything downstream depends on.
If it reports the requirements are unsatisfiable, the usual cause is that the
version is not on PyPI yet — publication and the announcement do not always land
together. Check with the PyPI query from step 2, and if it genuinely isn't
published, stop and tell the user rather than inventing a git pin: adding one is a
deliberate decision with a cost (see step 3), not a workaround to apply silently.
5. Migrate the on-disk config
.venv/bin/pipelex migrate --dry-run
Pipelex validates .pipelex/*.toml against the current schema at boot, and
config narrowings are enforced loudly rather than silently rewritten. Because the
test fixtures boot pipelex, stale config does not fail one test — it errors every
test in the suite, which reads like a code catastrophe and is nothing of the
kind. Running the dry run before the tests means you interpret that correctly if
it happens.
If the dry run reports changes, apply them with .venv/bin/pipelex migrate --yes
and read the resulting diff. The command writes a .bak.<timestamp> copy beside
each file it touches; those backups are local scratch, so don't offer them for
commit.
Note the scope: migrate covers this machine's pipelex config, so it reads
~/.pipelex as well as the repo's .pipelex/. That is usually what you want —
the user's own config would break at boot too — but it means the command can
change files outside the repo. If the dry run lists anything under the home
directory, say so when you report, since those changes are invisible in
git status and the user cannot review them in the diff.
Migration handles fields the schema can prove are stale. It cannot handle a
narrowing of the values a free-form string accepts — the uri_format
placeholder set is the recurring example. If boot raises a config error the
migration didn't fix, the error names the offending key and lists what is now
supported; fix it by hand and note it in the changelog, because anyone running
this server against their own .pipelex/ has to make the same edit.
6. Run the checks
make agent-check
make agent-test
make openapi-check
make openapi-check is a separate call on purpose: agent-check does not include
it (only the full make check does), and it is precisely the gate a pipelex bump
is most likely to trip. Pipelex models are on this server's wire — the run
result, the graph spec, the validation error vocabulary — so an upstream schema
change reaches docs/openapi/pipelex-api.openapi.yaml even though no code here
changed.
If it reports drift, regenerate and inspect:
make openapi-export
git diff docs/openapi/pipelex-api.openapi.yaml
Read that diff rather than accepting it — it is the clearest available statement
of what the bump changed for API consumers, and anything surprising in it (a field
disappearing, a type loosening to string) belongs in the changelog and possibly
in a conversation with the user before this lands.
Failures in agent-check or agent-test after a pipelex bump are usually the
breaking change announcing itself, not incidental breakage. Read the upstream
notes from step 7 before patching around them: the fix is normally to adopt the
new API, and a bump whose test failures were papered over is worse than no bump.
7. Digest the upstream changes
Get the release notes for every version after the old pin, up to and including
the new one. The helper does the boundary arithmetic:
.venv/bin/python .claude/skills/bump-pipelex/scripts/upstream_notes.py 0.47.0 0.48.0
It reads ../pipelex/CHANGELOG.md from the workspace checkout. Two things it
protects you from, both of which have produced wrong changelog entries before:
- It skips
## [Unreleased]. That section describes work that is not in the
version you just pinned. Attributing it to the release is a plain factual error
in a changelog people read to decide whether to upgrade.
- It tells you when the checkout is too old. The sibling repo is a working
checkout that may predate the version you are pinning. If the target heading
isn't there, the script says so and you should fall back to the published
notes:
gh release view v0.48.0 --repo Pipelex/pipelex
If the sibling checkout is absent entirely, go straight to gh.
8. Write the changelog entry
Add to CHANGELOG.md under ## [Unreleased], creating that heading right after
# Changelog if it isn't there. Work in progress accumulates under [Unreleased]
until a release cuts it into a version heading — do not add a ## [vX.Y.Z]
heading yourself, and do not bump the package version.
The entry goes under ### Changed and leads with the pin. What makes it useful is
the second half: what an operator or a caller has to do. Write it for someone
deciding whether this upgrade will break them.
## [Unreleased]
### Changed
- **Pinned `pipelex` 0.48.0.** Up from `==0.47.0`, exactly. <One or two sentences
on why this version — the capability it brings or the fix it carries.>
<If anything here breaks a caller or an operator, say so plainly and say what
they must change. If the OpenAPI artifact moved, name the fields that moved.
If `.pipelex/` config needed migrating, say that and name >
Match the surrounding entries' register: complete sentences, the reasoning stated,
no bare bullet lists of commit subjects. If the bump is genuinely uneventful —
a patch release with no wire, config, or behaviour change reaching this server —
then say that in one sentence and stop. Padding a quiet bump with upstream detail
that doesn't affect this repo makes the loud ones harder to spot.
Where a change is breaking, write "breaking" rather than "pre-1.0 breaking", per
the workspace convention.
9. Report and stop
Show the user:
- The version move, old → new.
- Every file you changed, and whether
uv.lock, the OpenAPI artifact, or
.pipelex/ config moved.
- The check results, honestly — if
agent-test failed, say so with the output
rather than reporting a bump as done.
- Anything from the upstream notes that needs a human decision.
- Whether the bump is breaking, because that is a cross-repo signal. The
hosted plane pins
pipelex at several sites and consumes pipelex-api by git
tag, so a breaking bump here means someone has to move pipelex-server too.
That is not yours to change from this repo — mention it, and if the user wants
it tracked, the workspace convention is a note in ../wip/inbox/.
Then stop. Do not commit, branch, or push unless the user asks.
If they do ask you to commit, stage the files explicitly by path — never
git add -A. Concurrent uncommitted work in this worktree is common, and a
blanket add sweeps someone's in-flight work into a bump commit. Stage
pyproject.toml, uv.lock, CHANGELOG.md, and the OpenAPI artifact and
.pipelex/ files only if they actually moved. A working branch here is
chore/<Topic>, and PRs target dev.
Traps worth remembering
- A
[tool.uv.sources] git pin silently outranks the version specifier. The
bump looks successful and changes nothing. Always check for it, always remove it
when returning to PyPI.
- Extras are not transitive. Losing one from the pin line produces a server
that fails only on the request that needs that provider.
make agent-check does not run openapi-check. Call it yourself; it's the
gate this task trips most.
- Every test erroring at once usually means stale
.pipelex/ config, not
broken code. Run pipelex migrate --dry-run before you start debugging.
## [Unreleased] upstream is not in the version you pinned. Never quote it
as part of the release.
[project].version is this package's version, not pipelex's. Bumping it
here is out of scope; that's the release skill.