Imported from echecsjs/pgn (
AGENTS.md). Install upstream withnpx skills add echecsjs/pgn. Copyright stays with the author.
AGENTS.md — Coding Agent Reference
This file documents conventions, commands, and guidelines for agents working in
the @echecs/pgn repository.
See also: REFERENCES.md |
COMPARISON.md | SPEC.md
Backlog: tracked in GitHub Issues.
Project Overview
@echecs/pgn is a PGN (Portable Game Notation) chess parser and serializer. It
uses a Peggy PEG parser compiled from
src/grammar.pegjs. The public API exports three functions:
parse(input: string, options?: ParseOptions): PGN[]— parse PGN into structured objectsstringify(input: PGN | PGN[], options?: StringifyOptions): string— serialize back to valid PGNstream()— deprecated, useparse()instead
Key source files:
| File | Role |
|---|---|
src/index.ts |
Public API barrel — re-exports functions and types |
src/types.ts |
All TypeScript type definitions |
src/parse.ts |
parse() entry point + error conversion |
src/stringify.ts |
stringify() — comment serialization + move list |
src/stream.ts |
stream() — deprecated streaming parser |
src/grammar.pegjs |
Peggy grammar source — edit this, not the .cjs |
src/grammar.cjs |
Generated — compiled from grammar.pegjs, gitignored |
src/comments.ts |
Comment command parsing ([%cal], [%clk], [%eval]) |
src/constants.ts |
Shared constants (RESULT_TO_STR, STR_TAGS) |
src/warnings.ts |
Warning helpers (missing STR tags, result mismatch) |
src/san.ts |
SAN notation reconstruction for stringify() |
src/tags.ts |
Tag serialization for stringify() |
src/__tests__/index.spec.ts |
Snapshot test suite (13 fixtures) |
src/__tests__/san.spec.ts |
SAN notation, NAGs, comments, RAVs |
src/__tests__/stream.spec.ts |
Streaming API tests |
src/__tests__/stringify.spec.ts |
Stringify + round-trip tests |
src/__tests__/index.bench.ts |
Self-benchmarks |
src/__tests__/comparison.bench.ts |
Cross-parser comparison benchmarks |
src/__tests__/grammar/ |
PGN fixture files used by tests |
Commands
Use pnpm exclusively (no npm/yarn).
Build
pnpm build # compile grammar + bundle dist/ via tsdown
pnpm grammar:compile # peggy --format commonjs -o src/grammar.cjs src/grammar.pegjs
Test
pnpm test # grammar:compile + vitest run (all tests)
pnpm test always recompiles the grammar first — no need to do it manually.
Run a single test by fixture label:
pnpm test -- --reporter=verbose -t "basic"
Available labels: basic, benko, checkmate, comment, comments,
games32, lichess, long, multiple, promotion, single, twic,
variants.
Update snapshots (only after intentional output changes):
pnpm test -- --update-snapshots
Snapshots live in src/__tests__/__snapshots__/<label>.snap and are committed
to git. Do not update them for pure performance changes.
Lint & Format
pnpm lint # ESLint + tsc --noEmit
pnpm lint:ci # same, zero warnings allowed
pnpm format # prettier --write
pnpm format:ci # prettier --list-different (check only)
Benchmarks
pnpm bench # vitest bench --run (all benchmarks, takes ~60s)
Grammar Workflow
Whenever src/grammar.pegjs is modified:
- Run
pnpm test— it recompiles and runs all 13 snapshots. - Never edit
src/grammar.cjsdirectly — it is generated and gitignored. - Grammar rule names use
SCREAMING_SNAKE_CASE(Peggy convention).
Validation
Input validation is mostly provided by TypeScript's strict type system at
compile time. There is no runtime validation library — the type signatures
enforce correct usage. Do not add runtime type-checking guards (e.g. typeof
checks, assertion functions) unless there is an explicit trust boundary. The
Peggy grammar handles syntactic validation of PGN input at parse time.
Release Protocol
Step-by-step process for releasing a new version. CI auto-publishes to npm when
version in package.json changes on main.
-
Verify the package is clean:
pnpm lint && pnpm test && pnpm buildDo not proceed if any step fails.
-
Decide the semver level:
patch— bug fixes, internal refactors with no API changeminor— new features, new exports, non-breaking additionsmajor— breaking changes to the public API
-
Update
CHANGELOG.mdfollowing Keep a Changelog format:## [x.y.z] - YYYY-MM-DD ### Added - … ### Changed - … ### Fixed - … ### Removed - …Include only sections that apply. Use past tense.
-
Update
README.mdif the release introduces new public API, changes usage examples, or deprecates/removes existing features. -
Bump the version:
npm version <major|minor|patch> --no-git-tag-version -
Open a release PR:
git checkout -b release/x.y.z git add package.json CHANGELOG.md README.md git commit -m "release: @echecs/pgn@x.y.z" git push -u origin release/x.y.z gh pr create --title "release: @echecs/pgn@x.y.z" --body "<description>"Wait for CI (format, lint, test) to pass on the PR before merging.
-
Merge the PR: Once CI is green, merge (squash) into
main. The release workflow detects the version bump, publishes to npm, and creates a GitHub Release with a git tag.
Do not manually publish with npm publish. Do not create git tags manually —
the release workflow handles tagging.