# Update Phel

> Bump phel-lang/phel-lang dependency to the latest release in this website repo. Triggers on "update phel", "bump phel", "upgrade phel-lang", "new phel release". Handles composer constraint bump, lock refresh, and verifies the post-update hook regenerated config.toml.

- Skill: `phel-lang/update-phel` (Agent Skill)
- Install (CLI): `npx skillmds@latest add phel-lang/update-phel`
- Raw SKILL.md: https://api.skillmd.com/api/skills/phel-lang/update-phel/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: phel-lang (https://skillmd.com/u/phel-lang)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/phel-lang/update-phel

---


# Update phel-lang to latest

This repo pins `phel-lang/phel-lang` in `composer.json` and mirrors the active version in `config.toml` (used by the Zola site to render the version badge / install snippets). A `post-update-cmd` runs `build/update-phel-version.php` which rewrites `config.toml` from the installed package version - do not edit `config.toml` by hand.

## Procedure

1. **Find current + latest version.**
   ```bash
   composer show phel-lang/phel-lang | grep -E "^versions"
   composer show phel-lang/phel-lang --all | grep -E "^versions" | head -1
   ```
   First command shows installed (marked `*`). Second lists all tags - latest stable is first non-`dev-*` entry.

2. **Bump constraint in `composer.json`.** Edit the `phel-lang/phel-lang` line under `require`. Use caret on the minor (`^0.40`), matching existing style. Phel is pre-1.0 so minor bumps may break - read the changelog if anything fails later.

3. **Update lock + run post-update hook.**
   ```bash
   composer update phel-lang/phel-lang --with-dependencies
   ```
   This pulls the new package, refreshes `composer.lock`, then auto-runs `php build/update-phel-version.php` which rewrites `config.toml` `phel_version = "vX.Y.Z"`. If `config.toml` did NOT change, the hook failed - investigate before committing.

4. **Verify.**
   ```bash
   git diff config.toml          # should show phel_version bump
   composer test                 # phpunit (45+ tests), must pass
   composer test:snippets        # runs every ```phel doc block against the new runtime
   ```
   `composer test:snippets` is the important one for a version bump: a new
   Phel release can rename core fns, move namespaces, or change printed
   output, which silently breaks documentation examples. The snippet baseline
   (`build/doc-snippets-baseline.json`) is empty, so ANY newly-broken snippet
   is reported as a regression and fails. See "When snippets break" below.

5. **Scan prose for stale version strings.** The snippet harness only runs ` ```phel ` blocks, so versions written in prose, JSON examples, and upgrade headings drift silently (they are never executed). After bumping to vX.Y.Z, grep for and update any that still name an older version:
   ```bash
   grep -rnE '"phel-lang/phel-lang": *"\^0\.[0-9]+"|^## Upgrading|var-dumper' content/
   ```
   Update at least:
   - `content/documentation/installation.md` - the `## Upgrading to ...` heading, the `composer require phel-lang/phel-lang:^X.Y` command, and a short breaking-changes list for the new minor (pull from the release notes).
   - `content/documentation/guides/coming-from-clojure.md` - the example `composer.json` pin.
   - `content/documentation/tooling/php-tools.md` - the `symfony/var-dumper` constraint should match this repo's own `composer.json`.

   These prose fixes belong in the same commit or a follow-up `docs:` commit.

6. **Commit.** Use this exact subject (matches prior `chore: bump phel-lang to 0.39.0` convention):
   ```
   chore: bump phel-lang to X.Y.Z
   ```
   For a clean bump, stage exactly `composer.json`, `composer.lock`,
   `config.toml`. If the new release added namespaces or broke snippets you
   will also have legitimate changes to `build/tests/.../ApiJsonFileTest.php`,
   `content/**`, and/or `build/doc-snippets-baseline.json` (see below) - those
   belong in the SAME commit or a follow-up `docs:`/`test:` commit, not
   discarded. Conventional commits, no Claude trailers (per global instructions).

## Files touched (expected)

Clean bump (no API/snippet changes):
- `composer.json` - constraint bump only (1 line)
- `composer.lock` - phel-lang + transitive deps (often symfony/*)
- `config.toml` - `phel_version` rewritten by post-update hook

A release that adds/renames core namespaces or changes runtime behaviour also
legitimately touches:
- `build/tests/php/ApiGenerator/Integration/ApiJsonFileTest.php` - the
  `$expectedNamespaces` list + its count (0.41 added `edn`, `reflect`, `transit`)
- `content/documentation/reference/api/*.md` - regenerated by `composer build`
- `content/**` and `build/doc-snippets-baseline.json` - if doc snippets broke

## When tests fail after bump

Phel < 1.0: minor releases can rename core fns or change emit output. Check:
- `https://github.com/phel-lang/phel-lang/releases/tag/vX.Y.Z` for breaking changes
- Failing tests in `build/tests/` - usually `VersionUpdater` or API page generation
- Regenerate API artifacts: `composer build` (runs `api-page.php`, `api-search.php`, `api-json.php`, `generate-releases.php`)

If breakage is in Phel itself, do not patch the website to compensate - open an issue upstream and pin to the prior version.

## When snippets break

`composer test:snippets` runs each ```phel doc block in `content/` in an
isolated `phel run` subprocess against the new runtime. The baseline
(`build/doc-snippets-baseline.json`) is empty, so the suite is green only when
every block either passes or carries an explicit skip. A new release commonly
breaks blocks via renamed core fns, moved/renamed namespaces, or changed
printed output (`; =>` comments). Triage each reported `file:line  [error]`:

- **Behaviour/name actually changed in Phel** -> update the snippet to the new
  API and fix any `; =>` output comment to the real runtime output (Phel
  vectors print as `@[...]`, strings keep quotes). This is the common case and
  the whole point of the check.
- **Genuinely non-runnable block** (syntax template with placeholder ids, REPL
  transcript, intentional-error demo, web/server-context) -> add an
  `<!-- phel-test: skip -->` HTML comment on its own line directly above the
  ```phel fence. Do NOT use a ` ```phel skip ` fence info string (breaks
  syntax highlighting). Most templates are already skipped.

Iterate until `composer test:snippets` reports `Failed: 0`. Useful commands:

```bash
php build/run-doc-snippets.php content/path/to/file.md --verbose  # one file
php build/run-doc-snippets.php --update-baseline                  # only if you
# deliberately accept a new known-failure; prefer fixing/skipping over this.
```

Keep the baseline empty when possible - a non-empty baseline is debt, not a
solution.

