Files
claude-agent-acp/AGENTS.md
Andrey Bragin 0dd58685b1 ci: set up preview publishing (#1084)
Today nothing reaches npm between two release-please releases, so trying
a merged
but unreleased change means building from source. This adds a
continuously
published preview channel.

Every CI-green push to `main` that is not a release merge publishes
`<package.json version, patch bumped>-preview.N` under the `preview`
dist-tag,
tags the commit `v<version>`, and dispatches the same agent registry
update a
stable release does. With `main` at 0.73.0 that gives
`0.73.1-preview.1`,
`0.73.1-preview.2`, and so on; `N` restarts at 1 whenever a release
moves the
base. `latest` is untouched.

## Approach

- **Added to `publish.yml` rather than a new workflow.** npm binds a
trusted
publisher to one repo + workflow filename, and a package gets only one.
A
  separate file would fail OIDC and cost the stable path its publisher.
- **Gated on the `CI` workflow succeeding** (`workflow_run`), so a red
commit is
never published. release-please's release merge is excluded by the head
commit's author and subject — its `releases_created` output is not
reachable
  from a different workflow run.
- **`N` is the max of the npm registry and local git tags.** npm
reserves
versions forever, even after `unpublish`, so a reused `N` is a hard
failure;
but the registry is CDN-served and lags, which the tags cover. A
registry read
  failure aborts rather than guessing.
- **Base is patch+1, not release-please's prediction**, which moves
mid-flight
  and would reset `N` under already-published previews.
- **The version is applied to the CI working tree only**, never
committed —
`package.json` and the release-please manifest stay release-please's to
own.
- **`--tag preview` is mandatory:** `npm publish` defaults to `latest`
even for a
  semver prerelease.
- **Three jobs.** `publish-npm-preview` mirrors `publish-npm` and only
publishes
(no repo write access); `publish-tag-preview` only tags, so a failed tag
is
retryable with _Re-run failed jobs_ without re-publishing an immutable
version;
`trigger-registry-update` is shared with the stable path. Both
downstream jobs
gate on a `published` output the publish step sets, not on job status —
the tag
push happens after the publish, so a red job can still mean npm has the
  version.

## Next step

The publish is `npm publish --dry-run` for now. The `workflow_run`
trigger and
the `release` environment's protected-branch policy mean this job cannot
run off
the default branch at all, so merging this is the only way to exercise
the
trigger, the gate and the version calculation — and with `published`
unset, the
rehearsal neither tags nor touches the registry.

Once one run looks right, a follow-up drops `--dry-run` and adds
`echo "published=true" >> "$GITHUB_OUTPUT"` to that step. Nothing else
changes.
2026-09-08 14:16:37 +02:00

1.7 KiB

Agent guide

An ACP-compatible coding agent powered by the Claude Agent SDK. Source in src/, TypeScript, ESM, Node >= 22.

Commands

npm run build         # tsc
npm run test:run      # vitest, single pass
npm run check         # eslint + prettier --check
npm run lint:fix      # eslint --fix
npm run format        # prettier --write

CI runs format:check, lint, build and test:run. Run npm run check before opening a PR.

Pull requests

Squash merges use the PR title as the commit subject, and release-please parses it to compute the next version. Titles must be conventional commits using one of: feat, fix, perf, revert, docs, style, chore, refactor, test, build, ci. conventional-prs.yml rejects anything else.

The title also decides the release: feat: bumps the minor, fix:/perf: the patch, and chore:/ci:/test: and friends do not release at all.

Releasing

Stable releases are fully automated by release-please. There is no manual release workflow, and the version is never chosen by hand — it follows from the commit history.

npm run release:preflight     # verifies it is safe to release, prints the PR and version
gh pr merge <pr-number> --squash

The preflight is the guard-list as code; if it exits non-zero, follow what it prints rather than merging.

Every other push to main publishes a preview to npm — 0.73.1-preview.4 and so on — under the preview dist-tag, tags the commit it came from, and updates the agent registry the same way a release does. Only latest is reserved for real releases. So anything merged to main is published within minutes; there is no staging branch. Full runbook, including how to recover a stalled release: docs/RELEASES.md.