Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
218 commits
Select commit Hold shift + click to select a range
ea9fbba
feat(client-generator): CodeWriter and language-neutral naming helpers
Marshevskyy Aug 2, 2026
75f7376
feat(client-generator): language-neutral schema helpers (flattenAllOf…
Marshevskyy Aug 2, 2026
dd3d9ad
feat(client-generator): export the language-neutral authoring toolkit…
Marshevskyy Aug 2, 2026
ab4fd93
refactor(client-generator): TS-free generation pipeline with lazily l…
Marshevskyy Aug 2, 2026
ab6b026
feat(client-generator): x-codeSamples overlay from generator sample()…
Marshevskyy Aug 2, 2026
357e49e
docs(client-generator): authoring skill v1 — AGENTS.md template, guar…
Marshevskyy Aug 2, 2026
d08648f
feat(cli): generate-client telemetry — generator usage events and too…
Marshevskyy Aug 2, 2026
7eec23a
chore: changeset for the agent-friendly authoring toolkit slice
Marshevskyy Aug 2, 2026
7e4dd6d
feat(client-generator): Python runtime core (errors, auth, send loop)…
Marshevskyy Aug 2, 2026
5f0bac9
feat(client-generator): Python model rendering via the neutral toolkit
Marshevskyy Aug 2, 2026
419deaa
feat(client-generator): Python sync/async clients over the descriptor…
Marshevskyy Aug 2, 2026
ae6f1eb
feat(client-generator): Python pagination, SSE, and multipart parity
Marshevskyy Aug 2, 2026
7e871bd
feat(client-generator): built-in python generator with Python code sa…
Marshevskyy Aug 2, 2026
00d20d9
feat(client-generator): Python e2e harness, docs, and changeset — sli…
Marshevskyy Aug 2, 2026
4496668
feat(client-generator): neutral schemaAtPointer and paginationRuleFor…
Marshevskyy Aug 2, 2026
b9045b0
feat(client-generator): Go runtime core (errors, auth, send loop) — s…
Marshevskyy Aug 2, 2026
d84f077
chore(client-generator): format-stable Go runtime embed
Marshevskyy Aug 2, 2026
b20f589
feat(client-generator): Go model rendering — structs with json tags, …
Marshevskyy Aug 2, 2026
0296ef4
feat(client-generator): built-in go generator — client assembly, code…
Marshevskyy Aug 2, 2026
481858b
feat(client-generator): Go e2e harness, docs, and changeset
Marshevskyy Aug 2, 2026
c8a439a
feat(client-generator): Go pagination, SSE, and multipart parity
Marshevskyy Aug 2, 2026
a777e4b
fix(client-generator): treat strict-mode reserved words as reserved i…
Marshevskyy Aug 2, 2026
bd9ac35
fix(client-generator): name signed-number properties Plus*/Minus* ins…
Marshevskyy Aug 2, 2026
aacf152
fix(client-generator): export Go fields for digit-leading property names
Marshevskyy Aug 2, 2026
0a1e1a1
test: add generate-client verification harness against Rebilly and Gi…
Marshevskyy Aug 2, 2026
0ac7190
ci: run the generate-client harness on generator-path changes
Marshevskyy Aug 2, 2026
9e399d5
test: update config schema snapshot for the client codeSamples option
Marshevskyy Aug 2, 2026
08752c7
feat(client-generator): zero-dep cli runtime (parser, dispatch, exit …
Marshevskyy Aug 2, 2026
47d9a41
feat(client-generator): cli generator — command data emitter and regi…
Marshevskyy Aug 2, 2026
f1b2339
test(client-generator): cli generator e2e against a live server
Marshevskyy Aug 2, 2026
a4b840a
docs(client-generator): cli generator docs, changeset, and harness bar
Marshevskyy Aug 2, 2026
8b8b5fc
feat(client-generator): PHP reserved words in the neutral naming toolkit
Marshevskyy Aug 2, 2026
a9336cd
feat(client-generator): embedded PHP runtime (curl, retries, paginati…
Marshevskyy Aug 2, 2026
9685e23
feat(client-generator): PHP SDK generator — models, client, paginatio…
Marshevskyy Aug 3, 2026
696cd4a
test(client-generator): PHP e2e smoke and harness bar
Marshevskyy Aug 3, 2026
1b8895b
docs(client-generator): PHP SDK docs and changeset
Marshevskyy Aug 3, 2026
1eb95ec
docs(client-generator): cli, python, go, and php examples
Marshevskyy Aug 3, 2026
f6ab32f
feat(client-generator): public runtime-sources entry for ejected gene…
Marshevskyy Aug 3, 2026
a856027
feat(client-generator): build-time eject assets for the language gene…
Marshevskyy Aug 3, 2026
d6dce9f
feat(client-generator): path generators may shadow built-in names
Marshevskyy Aug 3, 2026
5f088f2
feat(cli): eject-generator and scaffold-generator commands
Marshevskyy Aug 3, 2026
c5d324a
docs(client-generator): eject and scaffold docs, sidebar, changeset
Marshevskyy Aug 3, 2026
9e671dc
feat(cli): eject and ejected-generator telemetry with coarse outcome …
Marshevskyy Aug 3, 2026
29f48dc
docs(client-generator): ejected-generator and scaffolded-generator ex…
Marshevskyy Aug 3, 2026
8c296a4
docs(client-generator): commit the AGENTS.md drop in the eject/scaffo…
Marshevskyy Aug 3, 2026
3b2f4cd
docs(client-generator): bootstrap scripts and committed pristine in t…
Marshevskyy Aug 3, 2026
c61f052
feat(client-generator): text-template TS type renderer, printer-equiv…
Marshevskyy Aug 3, 2026
f4330f5
feat(client-generator): text-template data literals and descriptor bl…
Marshevskyy Aug 3, 2026
81b3800
feat(client-generator): text-template Ops type and operation aliases,…
Marshevskyy Aug 3, 2026
f93e2de
feat(client-generator): text-template type guards, printer-equivalent
Marshevskyy Aug 3, 2026
0fa5302
feat(client-generator): prepare-time runtime stripping — inline embed…
Marshevskyy Aug 3, 2026
60e4125
feat(client-generator): the flip — sdk client assembly is text templa…
Marshevskyy Aug 3, 2026
b2869a8
feat(client-generator): tanstack, swr, and wrapper support on text te…
Marshevskyy Aug 3, 2026
a74b943
feat(client-generator): transformers on text templates
Marshevskyy Aug 3, 2026
cfbfd31
feat(client-generator): zod on text templates
Marshevskyy Aug 3, 2026
9728c7f
feat(client-generator): mock and faker on text templates — the last A…
Marshevskyy Aug 3, 2026
5a332e1
feat(client-generator)!: remove the AST toolkit — one text-template a…
Marshevskyy Aug 3, 2026
fdd5b30
feat(client-generator)!: rename CodeWriter to Printer — the shared pr…
Marshevskyy Aug 3, 2026
6ed27e1
feat(client-generator): generator-per-folder with its own AGENTS.md s…
Marshevskyy Aug 3, 2026
8335506
docs(client-generator): java generator skill draft — design for revie…
Marshevskyy Aug 3, 2026
31f3a80
fix(client-generator): pin eject skill assets to their sources, corre…
Marshevskyy Aug 3, 2026
6e06798
feat(cli)!: rename scaffold-generator to architect-generator
Marshevskyy Aug 3, 2026
5c837dc
chore: consolidate branch changesets into one
Marshevskyy Aug 3, 2026
e65e52f
docs: trim AGENTS.md to non-derivable guidance, point core principles…
Marshevskyy Aug 3, 2026
e24a5a7
chore: remove stale migration-narrative comments and a duplicated ren…
Marshevskyy Aug 3, 2026
0e85d36
feat: close service-based PHP SDK adoption gaps (binary bodies, union…
Marshevskyy Aug 4, 2026
f9beb13
test: fold the generate-client harness into the e2e suite as large-de…
Marshevskyy Aug 4, 2026
1e6528e
fix: rewrite the ejected skill's intro and modify loop for the user's…
Marshevskyy Aug 4, 2026
61a9f0a
feat: dispatch Python discriminated unions via a decode registry and …
Marshevskyy Aug 4, 2026
4772a5d
chore: remove redundant comments from cli build script and generate-c…
Marshevskyy Aug 4, 2026
33e078f
refactor: rename Printer instances from writer to printer
Marshevskyy Aug 4, 2026
637218d
chore: remove the unreleased architect-generator command
Marshevskyy Aug 4, 2026
3329229
feat(client-generator): port the response-headers envelope to the tex…
Marshevskyy Aug 6, 2026
912d2cb
feat: harden the custom-generator contract (output containment, run()…
Marshevskyy Aug 4, 2026
ea9d834
feat: response-header envelope parity for php, python, and go via Wit…
Marshevskyy Aug 4, 2026
4ca28a5
ci: fix PR checks — go compile-bar timeouts on cold caches, hard tabs…
Marshevskyy Aug 4, 2026
ba4fa89
fix: gate mock-emitter code interpolations behind an identifier check…
Marshevskyy Aug 4, 2026
f5c45b7
docs: document both ejected AGENTS.md drops and the language SDKs' en…
Marshevskyy Aug 4, 2026
3167889
fix: drop the client-generator prepublishOnly rebuild that broke pack…
Marshevskyy Aug 5, 2026
33dd6ce
fix: honor the serverUrl option in the python, go, and php generators
Marshevskyy Aug 5, 2026
2adf755
test: give the cli e2e cases room for tsx startup
Marshevskyy Aug 5, 2026
631a9e4
feat: warn or fail instead of silently dropping options a language ge…
Marshevskyy Aug 5, 2026
ee6eaa4
feat: support dateType: Date in the python, go, and php generators
Marshevskyy Aug 5, 2026
e7d282f
test: pin the embedded language runtimes to their source files
Marshevskyy Aug 5, 2026
e75de09
refactor: give every generator a folder and an AGENTS.md design skill
Marshevskyy Aug 5, 2026
ee02eea
docs: specify the target behavior from PR review feedback
Marshevskyy Aug 5, 2026
5728004
fix(php): put the brace directly under each declaration, with no blan…
Marshevskyy Aug 5, 2026
33e24b6
feat(php): document element types in PHPDoc where the signature erase…
Marshevskyy Aug 5, 2026
c96f2b5
fix(python): emit an importable module name for the generated client
Marshevskyy Aug 5, 2026
63d369a
fix(python): accept the cross-language apiKey auth key, not only api_key
Marshevskyy Aug 5, 2026
a916968
fix(go): emit gofmt-clean output — column alignment, switch indentati…
Marshevskyy Aug 5, 2026
99d13cc
fix(zod): emit erasable TypeScript so the generated CLI runs under no…
Marshevskyy Aug 5, 2026
22cd204
feat(php): keep union types instead of collapsing them to mixed
Marshevskyy Aug 5, 2026
79026d0
feat: name the declared query parameters when a pagination param does…
Marshevskyy Aug 5, 2026
6ae6e41
feat: say why a name was renamed and what the publisher can change
Marshevskyy Aug 5, 2026
e5658f9
feat(cli): document global flags in help, address commands the way a …
Marshevskyy Aug 5, 2026
d415bbf
feat(cli): give the generated CLI a command-like bin name, settable v…
Marshevskyy Aug 5, 2026
c335ef6
feat: pull in a generator's prerequisites so the CLI validates by def…
Marshevskyy Aug 5, 2026
c0c60c8
feat: add goPackage so the go SDK declares the package the consumer owns
Marshevskyy Aug 5, 2026
28d8e0f
feat: let a generator declare its own options and validate them from …
Marshevskyy Aug 5, 2026
2270e1b
docs: explain the shared naming vocabulary and why a language SDK is …
Marshevskyy Aug 5, 2026
06334de
feat!: rename the pagination extension to x-redoclyPagination
Marshevskyy Aug 5, 2026
b562a31
feat: eject the generator design as an agent skill instead of an AGEN…
Marshevskyy Aug 5, 2026
6e9b404
feat: eject wires up the dependency and the config entry
Marshevskyy Aug 5, 2026
327eda4
feat!: replace the generator contract number with a semver range
Marshevskyy Aug 5, 2026
05a12ff
feat: resolve the update merge base from the ejected header instead o…
Marshevskyy Aug 5, 2026
7ee3ab3
feat: make every built-in generator ejectable, bundling the TypeScrip…
Marshevskyy Aug 6, 2026
1acf29d
refactor!: drop the AST toolkit so text printing is the only authorin…
Marshevskyy Aug 6, 2026
485586c
test: keep the e2e bars aligned with the new CLI prerequisites and re…
Marshevskyy Aug 6, 2026
12bebc5
test: give client generation its own suite and CI job
Marshevskyy Aug 6, 2026
27f008c
docs: condense the client-generation changeset to one sentence
Marshevskyy Aug 6, 2026
d345a7b
docs: use an imperative heading for the ejected-generator update section
Marshevskyy Aug 6, 2026
c41a000
fix: clean changelog
Marshevskyy Aug 6, 2026
05666b0
fix(cli): stop inlining a stale generator list in --generator help
Marshevskyy Aug 6, 2026
792f6e4
feat: add a cli-docs generator that renders the generated CLI's Markd…
Marshevskyy Aug 6, 2026
4a52931
feat(cli): document commands whose body the CLI cannot build, and ski…
Marshevskyy Aug 6, 2026
a8fed72
Potential fix for pull request finding 'CodeQL / Incomplete string es…
Marshevskyy Aug 7, 2026
1cee039
Potential fix for pull request finding 'CodeQL / Improper code saniti…
Marshevskyy Aug 7, 2026
d0d6f45
fix(go): collapse consecutive blank doc-comment lines so output stays…
Marshevskyy Aug 7, 2026
340f195
fix: escape only what JSON.stringify leaves unsafe in a code context
Marshevskyy Aug 7, 2026
723650e
Merge branch 'main' into feat/agent-friendly
Marshevskyy Aug 7, 2026
8dffbce
fix: carry the built-in contract into ejected generators
Marshevskyy Aug 7, 2026
90003ad
fix(cli): count cli-docs as a built-in generator in telemetry
Marshevskyy Aug 7, 2026
a8d986e
fix: keep the eject-asset build off compiled output
Marshevskyy Aug 7, 2026
d19e458
Merge branch 'main' into feat/agent-friendly
Marshevskyy Aug 7, 2026
4637d76
docs: correct changelog
Marshevskyy Aug 7, 2026
e039367
fix(cli): report an outcome when eject-generator fails unexpectedly
Marshevskyy Aug 7, 2026
771b9dd
docs: restore the rule test pattern and the package architecture map
Marshevskyy Aug 8, 2026
7e8bb05
feat: warn when binName or goPackage is set with no generator that re…
Marshevskyy Aug 8, 2026
3a61c3b
fix: apply readOnly declared beside a $ref in OpenAPI 3.1
Marshevskyy Aug 8, 2026
ae4a9d0
fix(cli): list only the credentials the description declares, and rej…
Marshevskyy Aug 8, 2026
e8df6a4
feat(cli): make schema the complete contract for a command
Marshevskyy Aug 8, 2026
597b938
feat(cli): composable generated CLIs — importable modules, custom com…
Marshevskyy Aug 9, 2026
183cfa5
feat(cli): compose one binary over several APIs via client.cliOutput
Marshevskyy Aug 9, 2026
a12a0f7
fix: write generated files to the path the traversal guard validated
Marshevskyy Aug 10, 2026
2483b7f
fix(cli): treat a git merge-file error exit as a failure, not a confl…
Marshevskyy Aug 10, 2026
cba1e0d
fix(cli): replace the built-in name entry when wiring an ejected gene…
Marshevskyy Aug 10, 2026
098ae0b
fix: keep the released x-redocly-pagination extension working, warnin…
Marshevskyy Aug 10, 2026
cab6952
fix(cli): merge skill edits on eject-generator --update instead of ov…
Marshevskyy Aug 10, 2026
7b20bdd
fix(cli): re-wire the toolkit devDependency range on eject-generator …
Marshevskyy Aug 10, 2026
4b2404e
fix(cli): accept --config in eject-generator
Marshevskyy Aug 10, 2026
ee592ce
fix(cli): compose the CLI from the emitted cli modules and create the…
Marshevskyy Aug 10, 2026
596acc8
fix(cli): keep composed-entry import bindings legal and unique for an…
Marshevskyy Aug 10, 2026
1797cf8
fix(cli): capture the prepared request on --dry-run for SSE commands
Marshevskyy Aug 10, 2026
2c5b8a9
fix(cli): resolve telemetry generator paths against the config dir an…
Marshevskyy Aug 10, 2026
c8bb72a
docs: align help text, anchors, and skill intros with what the featur…
Marshevskyy Aug 10, 2026
6acb94e
docs: list cli-docs among the built-in generators in the client refer…
Marshevskyy Aug 10, 2026
34b91bc
test: assert shipped-skill freshness for every ejectable generator, n…
Marshevskyy Aug 10, 2026
205072e
test: tie the generator name sets to the registry and drop a defensiv…
Marshevskyy Aug 10, 2026
d7e041a
Merge branch 'main' into feat/agent-friendly
Marshevskyy Aug 10, 2026
2a53c15
docs: restore the x-redoclyPagination note and point tsType at the ge…
Marshevskyy Aug 10, 2026
bce4e3b
fix(cli): let a composed source omit its wiring, and redact the encod…
Marshevskyy Aug 10, 2026
80f1332
fix(cli): wire the ejected generator entry relative to the config dir…
Marshevskyy Aug 10, 2026
e15b884
feat!: drop the x-redocly-pagination fallback — only x-redoclyPaginat…
Marshevskyy Aug 10, 2026
6b636fa
chore: address review naming — client-generators suite/job, telemetry…
Marshevskyy Aug 11, 2026
1b62605
feat(cli): report the composed-CLI api count and the --update version…
Marshevskyy Aug 11, 2026
076afc6
fix(cli): compare real paths when wiring the ejected generator into t…
Marshevskyy Aug 11, 2026
960889c
docs: rewrite the client-generation pages in simplified version
Marshevskyy Aug 11, 2026
c714437
Update .github/workflows/tests.yaml
Marshevskyy Aug 11, 2026
cb2d497
fix(cli): state the composition and toolkit-version comments positively
Marshevskyy Aug 11, 2026
1724969
fix: rename the sdk generator to typescript and address review feedba…
Marshevskyy Aug 13, 2026
d3c7d22
fix: address CI findings — extract the update and composed-entry flow…
Marshevskyy Aug 13, 2026
266bf67
docs: split the multi-clause sentences in the CLI composition and eje…
Marshevskyy Aug 13, 2026
33a7d95
fix: wire eject config only where generation reads it, name the sdk-t…
Marshevskyy Aug 13, 2026
7b2fcf8
fix: keep wireConfig under the complexity limit and read generator li…
Marshevskyy Aug 13, 2026
abada70
chore: strip narration comments from eject-generator
Marshevskyy Aug 13, 2026
248190f
Apply suggestions from code review
JLekawa Aug 13, 2026
eaf126e
Apply suggestions from code review
JLekawa Aug 13, 2026
d6c63e8
Apply suggestions from code review
JLekawa Aug 13, 2026
1854e62
Apply suggestions from code review
JLekawa Aug 13, 2026
9f08ce8
Apply suggestions from code review
JLekawa Aug 13, 2026
e271f78
Apply suggestions from code review
JLekawa Aug 13, 2026
eb102e2
Apply suggestion from @JLekawa
JLekawa Aug 13, 2026
03ea402
Apply suggestion from @JLekawa
JLekawa Aug 13, 2026
b44754b
Apply suggestions from code review
JLekawa Aug 13, 2026
c4a2c61
Apply suggestion from @JLekawa
JLekawa Aug 13, 2026
8f221df
docs(cli): fix linting issues in tables
JLekawa Aug 13, 2026
1f11313
docs(cli): fix lint issues
JLekawa Aug 13, 2026
15b38e8
Merge branch 'main' into feat/agent-friendly
JLekawa Aug 13, 2026
f994b2c
docs(cli): run oxfmt on docs only
JLekawa Aug 13, 2026
7ed38b7
Merge branch 'feat/agent-friendly' of https://github.com/Redocly/redo…
JLekawa Aug 13, 2026
6090b29
fix: apply a link pagination convention only where a Link header is d…
Marshevskyy Aug 14, 2026
f17da0c
test: name the cli credential fixtures after the cafe example
Marshevskyy Aug 17, 2026
381a54b
feat(client-generator): add the sdk-docs generator
Marshevskyy Aug 17, 2026
d544283
docs: drop the language-comparison table that repeated the reference
Marshevskyy Aug 17, 2026
5dc9c42
refactor(client-generator): group the language runtimes under runtime/
Marshevskyy Aug 17, 2026
ca5b332
docs(client-generator): say that each generator skill compiles into t…
Marshevskyy Aug 17, 2026
fb53dc6
docs(client-generator): state where a renderer lives
Marshevskyy Aug 17, 2026
2a46d21
docs: stop calling the built-in typescript generator a reference impl…
Marshevskyy Aug 17, 2026
085210d
fix(client-generator): align the sdk-docs notes with what each SDK does
Marshevskyy Aug 17, 2026
287f473
Merge branch 'main' into feat/agent-friendly
Marshevskyy Aug 17, 2026
eb8a8a4
chore(client-generator): refresh the sdk-docs skill asset
Marshevskyy Aug 17, 2026
2522929
docs: explain the word after the bin name, and why TypeScript has ext…
Marshevskyy Aug 17, 2026
217287b
refactor(client-generator)!: make documentation a generator hook behi…
Marshevskyy Aug 18, 2026
fd65869
docs: document --docs and the generator docs hook
Marshevskyy Aug 18, 2026
17f9465
fix(client-generator): derive each sample's module identity from the …
Marshevskyy Aug 18, 2026
2082d01
docs: lead the CLI syntax with the operationId, not the tag group
Marshevskyy Aug 18, 2026
187ebb8
docs: add a quickstart, a migration guide, and the HTTP-layer seam
Marshevskyy Aug 18, 2026
991b3ac
docs: use the plain redocly command in the client generation examples
Marshevskyy Aug 18, 2026
c819c4f
feat(client-generator): emit pydantic models for the python SDK on re…
Marshevskyy Aug 18, 2026
daefd83
docs: add generator recipes, with a runnable valibot example
Marshevskyy Aug 18, 2026
1582809
refactor(client-generator)!: drop the per-scheme credential setters
Marshevskyy Aug 18, 2026
9ed3ffd
test: assert operation-name sanitization on the operation, not on a s…
Marshevskyy Aug 18, 2026
a36cc78
fix(client-generator)!: flat iterators take the flat argument shape
Marshevskyy Aug 18, 2026
0b8a1fe
docs: show how to make binName a real command
Marshevskyy Aug 18, 2026
9710db4
docs: correct what a tag group is for in the generated CLI
Marshevskyy Aug 18, 2026
5911875
fix: make a cli operation named after a tag reachable
Marshevskyy Aug 18, 2026
b945730
fix: resolve a nested discriminated union in pydantic models, drop a …
Marshevskyy Aug 18, 2026
fee9559
feat(client-generator)!: one input object per operation, grouped by l…
Marshevskyy Aug 19, 2026
57f009d
fix(client-generator): keep a repeated parameter name usable in every…
Marshevskyy Aug 19, 2026
1ba6e7a
refactor(client-generator)!: drop binName, the generated cli names it…
Marshevskyy Aug 19, 2026
090b1c3
docs: reduce the changeset to one sentence
Marshevskyy Aug 19, 2026
1bdd8ec
fix(client-generator): make the flat fallback, the python iterators, …
Marshevskyy Aug 19, 2026
6cf104a
fix(client-generator): export invokedName, and stop reading an allOf …
Marshevskyy Aug 19, 2026
147e81b
fix(cli): read the eject assets from the package that owns them
Marshevskyy Aug 20, 2026
cae28e8
feat(cli): tell the reader how to run the generator it just ejected
Marshevskyy Aug 20, 2026
56d5e39
Merge branch 'main' into feat/agent-friendly
Marshevskyy Aug 20, 2026
44c5113
test(cli): co-locate this branch's unit tests, and write the conventi…
Marshevskyy Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .changeset/agent-friendly-generators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@redocly/client-generator': minor
'@redocly/cli': minor
---

Added agent-friendly client generation: `python`, `go`, `php`, and `cli` generators beside the TypeScript client, each self-documenting with `--docs`, configurable per generator, and available as source in your own repository through `eject-generator`.
47 changes: 47 additions & 0 deletions .claude/rules/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Repository architecture

Where things live, so a change lands in the right package.

This is a TypeScript monorepo with npm workspaces containing four packages:

## `packages/core` (@redocly/openapi-core)

The heart of the project.
Handles all OpenAPI/AsyncAPI linting, validation, bundling, and decoration logic.
This package is also used in external apps such as `language-server` and `vs-code-extension`.

Key directories:

- `src/rules/` — Built-in linting rules, organized by spec type (`oas2/`, `oas3/`, `oas3_1/`, `async2/`, `async3/`, `arazzo/`, `common/`). Each rule is its own file.
- `src/config/` — Configuration loading and resolution (reads `redocly.yaml`).
- `src/decorators/` — Built-in decorators for transforming API descriptions.
- `src/bundle/` — Bundling logic that resolves `$ref` across multiple files.
- `src/resolve.ts` — Document resolution for multi-file specs (local and remote).
- `src/types/` — TypeScript type definitions for OAS2, OAS3, AsyncAPI, Arazzo.

## `packages/cli` (@redocly/cli)

User-facing CLI layer built on top of core.
Uses yargs for argument parsing.

- `src/index.ts` — Main command dispatcher.
- `src/commands/` — One file per command.
- Commands use `commandWrapper()` for consistent output, config loading, config linting, and exit codes (0 = success, 1 = execution error, 2 = config error).

## `packages/respect-core` (@redocly/respect-core)

API contract testing framework.
Validates real API responses against OpenAPI/Arazzo specs.

- `src/run.ts` — Test execution logic.
- `src/modules/` — Core testing modules, including runtime expression evaluation.

## `packages/client-generator` (@redocly/client-generator)

Experimental package for generating clients from OpenAPI descriptions — the TypeScript client
plus the `python`, `go`, and `php` SDKs, the generated CLI, and its Markdown reference.

- `src/intermediate-representation/` — the language-neutral API model every generator reads.
- `src/emitters/` — the renderers that turn that model into source text.
- `src/generators/` — one folder per generator: a thin entry plus the design skill it must match.
- `src/authoring/` — the language-neutral toolkit generators are written with, ours and users'.
2 changes: 1 addition & 1 deletion .claude/rules/core-principles.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Release and commit mechanics are procedures, not principles — they live in

1. Respect the core patterns: Walker, Visitors, and Nodes.
New rules and decorators follow this pattern instead of using regex or manual drilling objects described by the supported specifications.
The full guide is in [`rules-system.md`](./rules-system.md).
The full guide is in [the `rules-system` skill](../skills/rules-system/SKILL.md).

1. Explain in chat, not in files.
Don't create explanation, summary, or design files unless asked.
Expand Down
44 changes: 43 additions & 1 deletion .claude/rules/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,52 @@

1. Write meaningful tests that exercise real behavior — not tests that exist only to raise coverage.
One focused, clear test is enough.
1. Rule tests are unit tests by convention: parse a YAML document, run `lintDocument`, and assert with `toMatchInlineSnapshot` — a behavior test in itself (given this input, these problems).
1. A unit test lives in a `__tests__` folder beside the file it tests, and mirrors its name:
`src/commands/eject-generator.ts` is tested by `src/commands/__tests__/eject-generator.test.ts`.
Do not rebuild the source tree inside a `__tests__` folder (`src/__tests__/commands/…`) — the
older tests that do are historical, and a reviewer should not have to guess which layout a
new test follows. One module gets one test file: split a long one by `describe`, not by adding
a second file for the same source.
1. Rule tests are unit tests by convention: parse a YAML document, run `lintDocument`, and assert
with `toMatchInlineSnapshot` — a behavior test in itself (given this input, these problems).
Generate new snapshots and update stale ones as part of the change.

The pattern — parse, lint, assert on the whole output:

```ts
import { outdent } from 'outdent';
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils.js';
import { createConfig } from '../../../config/index.js';
import { lintDocument } from '../../../lint.js';
import { BaseResolver } from '../../../resolve.js';

describe('Oas3 no-my-rule', () => {
it('should report a violation', async () => {
const document = parseYamlToDocument(
outdent`
openapi: 3.0.0
...
`,
'foobar.yaml'
);

const results = await lintDocument({
externalRefResolver: new BaseResolver(),
document,
config: await createConfig({ rules: { 'no-my-rule': 'error' } }),
});

expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`...`);
});
});
```

1. Compile before testing.

Unit tests import from `lib/` (compiled output), not `src/` — run `npm run compile` after every change.

1. Run the full suite (`npm test`) when you touch core linting logic, and make sure all tests pass in CI.
1. Client generation has its own suite: `npm run client-generators` runs the client-generator unit tests plus the `tests/e2e/generate-client` bars (which compile real Python/Go/PHP/TypeScript output).
Run it for any generation change; `npm run e2e` does not include those tests.
1. Coverage thresholds (`vitest.config.ts`) are a guide, not a number to game.
If a feature or fix is already covered by e2e tests, propose lowering the threshold rather than padding the suite with unit tests that only chase coverage.
2 changes: 1 addition & 1 deletion .claude/skills/redocly-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Configure it durably under a `client` block in `redocly.yaml` instead of flags:

```yaml
client:
generators: [sdk, zod] # add-ons: tanstack-query, swr, mock, transformers, or a plugin path
generators: [typescript, zod] # add-ons: tanstack-query, swr, mock, transformers, or a plugin path
outputMode: split
pagination: # config-only, no CLI flag
style: cursor
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
name: rules-system
description: How to write built-in lint rules and decorators for packages/core — the Walker/Visitors/Nodes pattern, visitor hooks, the ctx object, rule registration, and stateful rule examples. Use when adding or changing a rule, decorator, or preprocessor.
---

## Rules System: Walker, Visitors, and Nodes

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, why have you removed the rule?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved, not removed, it's .claude/skills/rules-system/SKILL.md now, content intact, and
AGENTS.md links it. Rules under .claude/rules/ load into every session's context;
a skill loads only when the task is about rules, so the 170-line guide stopped taxing
unrelated sessions.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see such file. Could you clarify the path?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake — the file existed locally but a local git exclude kept it out of the push, so the AGENTS.md link pointed at nothing. It's committed now in 1724969.


This is the most important pattern to understand when working in `packages/core`.
Expand Down
38 changes: 32 additions & 6 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,24 @@ jobs:
uses: davelosert/vitest-coverage-report-action@d63aa97db4c0319f304f1787689de1ca548365cf # v2.11.1

e2e:
# The e2e suite is split across shards so no single runner carries the whole set.
# Running all suites in one step was cancelled mid-run by the Actions service once the
# generate-client suites grew past ~28 (a healthy runner, no resource exhaustion);
# each shard stays well under that.
# Everything under tests/e2e EXCEPT generate-client, which has its own job below.
Comment thread
tatomyr marked this conversation as resolved.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24
cache: npm
- name: Install dependencies
run: npm ci
- name: E2E Tests
run: npm run e2e

client-generators:
# Client generation has its own job: the client-generator unit tests plus the
# generate-client e2e bars, which compile real Python, Go, PHP, and TypeScript output
# (including big real-world descriptions) — the slowest tests we have, needing
# toolchains nothing else does. Adding a language bar here cannot slow the shared e2e job.
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand All @@ -52,10 +66,22 @@ jobs:
with:
node-version: 24
cache: npm
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
- name: Install httpx and pydantic (the Python import bars need them)
run: pip install httpx pydantic
# Go, gofmt, and php come with the runner image; a bar whose toolchain is missing
# skips itself, so a thinner image degrades coverage instead of failing the job.
- name: Cache the pinned GitHub REST description
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: tests/e2e/generate-client/.cache
key: large-descriptions-${{ hashFiles('tests/e2e/generate-client/large-descriptions.test.ts') }}
Comment on lines +69 to +80

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a separate test suite for generator.
I think it will be very big and slow eventually when we start testing compiled languages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and it's already the biggest suite. Splitting generator tests (client-generator unit +
tests/e2e/generate-client, including the large-description compile bars) into their own vitest
suite and CI job so compiled-language testing can grow without slowing the main e2e job.

- name: Install dependencies
run: npm ci
- name: E2E Tests (shard ${{ matrix.shard }}/2)
run: npm run e2e -- --shard=${{ matrix.shard }}/2
- name: Client generator tests (shard ${{ matrix.shard }}/2)
run: npm run client-generators -- --shard=${{ matrix.shard }}/2

examples:
# The examples gitignore their generated clients (only zero-install-quickstart commits
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ __changesets__.json
**/.claude/agent-registry.json
**/.claude/agent-memory-local
**/.claude/first-run
**/.claude/assistant-daemon-state.json
**/.claude/assistant-daemon-state.json
__pycache__/
1 change: 1 addition & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"packages/core/src/rules/common/__tests__/fixtures/invalid-yaml.yaml",
"tests/performance/api-definitions/",
"tests/e2e/generate-client/examples/*/src/api/",
"tests/e2e/generate-client/examples/*/generators/",
"tests/e2e/generate-client/*-consumer/api*.ts",
"tests/smoke/**/*.yaml",
"snapshot*.txt",
Expand Down
84 changes: 12 additions & 72 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,12 @@ npm run unit -- -t 'test name pattern'
# Update snapshots
npm run unit -- -u

# Run e2e tests
# Run e2e tests (everything under tests/e2e except generate-client)
npm run e2e

# Run every generator test (client-generator unit + generate-client e2e)
npm run client-generators

# Run the full test suite (compile + typecheck + unit + e2e)
npm test

Expand All @@ -64,47 +67,13 @@ npm run cli -- lint openapi.yaml

## Architecture

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this block was removed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't have been — restored in 771b9dd.

The intent was to keep AGENTS.md to guidance an agent can't derive by reading the repo, and the package map looked derivable. It isn't: knowing which package a change belongs in is exactly the thing that's expensive to work out from the tree, and getting it wrong is costly.
It now lives in .claude/rules/architecture.md with all four packages and their key directories intact, and AGENTS.md points at it. Same content, one hop away, so AGENTS.md stays short without losing the map.


This is a TypeScript monorepo with npm workspaces containing four packages:

### `packages/core` (@redocly/openapi-core)

The heart of the project.
Handles all OpenAPI/AsyncAPI linting, validation, bundling, and decoration logic.
This package is also used in external apps such as `language-server` and `vs-code-extension`.

Key directories:

- `src/rules/` — Built-in linting rules, organized by spec type (`oas2/`, `oas3/`, `oas3_1/`, `async2/`, `async3/`, `arazzo/`, `common/`). Each rule is its own file.
- `src/config/` — Configuration loading and resolution (reads `redocly.yaml`).
- `src/decorators/` — Built-in decorators for transforming API descriptions.
- `src/bundle/` — Bundling logic that resolves `$ref` across multiple files.
- `src/resolve.ts` — Document resolution for multi-file specs (local and remote).
- `src/types/` — TypeScript type definitions for OAS2, OAS3, AsyncAPI, Arazzo.

### `packages/cli` (@redocly/cli)

User-facing CLI layer built on top of core.
Uses yargs for argument parsing.

- `src/index.ts` — Main command dispatcher.
- `src/commands/` — One file per command.
- Commands use `commandWrapper()` for consistent output, config loading, config linting, and exit codes (0 = success, 1 = execution error, 2 = config error).

### `packages/respect-core` (@redocly/respect-core)

API contract testing framework.
Validates real API responses against OpenAPI/Arazzo specs.

- `src/run.ts` — Test execution logic.
- `src/modules/` — Core testing modules, including runtime expression evaluation.

### `packages/client-generator` (@redocly/client-generator)

Experimental package for generating TypeScript clients from OpenAPI specs.
Where each package sits, and the key directories inside it, are in
[`.claude/rules/architecture.md`](./.claude/rules/architecture.md) — read it before a change lands
in the wrong package.

## Build System

`packages/core`, `packages/respect-core`, and `packages/client-generator` are compiled by TypeScript (`tsc -b tsconfig.build.json`).
`packages/core` and `packages/respect-core` are compiled by TypeScript (`tsc -b tsconfig.build.json`).
`packages/cli` is bundled by esbuild (`packages/cli/scripts/build.mjs`) — it produces `lib/index.js` (entry chunk, ~450 kB) and lazy chunks under `lib/chunks/` (redoc + react, loaded only when `build-docs` runs).
The root `npm run compile` runs both steps: tsc for core/respect-core, then the esbuild bundle for the CLI.

Expand All @@ -114,7 +83,7 @@ The published CLI package ships from a staged `.publish/` directory (created by

Linting in `packages/core` rests on three concepts: the **Walker** traverses the parsed API description and resolves `$ref`s, **Visitors** are objects keyed by **Node** type, and the Walker calls each visitor's `enter` / `leave` / `skip` hooks as it reaches a node.
New rules and decorators follow this pattern instead of parsing documents by hand.
The full guide, with examples, is in [`.claude/rules/rules-system.md`](./.claude/rules/rules-system.md).
The full guide, with examples, is in [the `rules-system` skill](./.claude/skills/rules-system/SKILL.md).

## Add or change a built-in rule

Expand Down Expand Up @@ -144,40 +113,11 @@ Naming and reuse:
- A `redocly.yaml` in the repository root affects unit tests in the CLI package.
Remove it before running them.
- Run the full suite (`npm test`) when you touch core linting logic.
- Run `npm run client-generators` when you touch client generation — it is the whole generator suite in one command.

The full testing and QA rules are in
The full testing and QA rules — including the rule test pattern to copy — are in
[`.claude/rules/testing.md`](./.claude/rules/testing.md).

The rule test pattern looks like this:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you remove rule test pattern ? Was it not working properly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing wrong with it — the pattern is correct and still the one to copy. Removing it was the same over-trim, and it's restored in 771b9dd.

The full parse → lintDocument → toMatchInlineSnapshot example is now in .claude/rules/testing.md, which AGENTS.md links to as "the rule test pattern to copy".


```ts
import { outdent } from 'outdent';
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils.js';
import { createConfig } from '../../../config/index.js';
import { lintDocument } from '../../../lint.js';
import { BaseResolver } from '../../../resolve.js';

describe('Oas3 no-my-rule', () => {
it('should report a violation', async () => {
const document = parseYamlToDocument(
outdent`
openapi: 3.0.0
...
`,
'foobar.yaml'
);

const results = await lintDocument({
externalRefResolver: new BaseResolver(),
document,
config: await createConfig({ rules: { 'no-my-rule': 'error' } }),
});

expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`...`);
});
});
```

## Code quality — no AI slop

Before opening a PR, strip the things an assistant tends to add that a human reviewer would not:
Expand Down Expand Up @@ -207,7 +147,7 @@ The full release and commit workflow is in [`.claude/rules/workflow.md`](./.clau

- Every feature or fix needs a changeset: run `npx changeset` and describe the change in sentence case.
If the change lives in `packages/core` or `packages/respect-core` but affects CLI behavior, include `@redocly/cli` as well.
`@redocly/cli`, `@redocly/openapi-core`, and `@redocly/respect-core` share one version and release together; `@redocly/client-generator` is versioned separately.
All three packages share one version and release together.
- Use [Conventional Commits](https://www.conventionalcommits.org/) for commit messages.
- Don't add AI co-author or "Generated by" lines to commits.
- Don't modify the pull request template.
Expand Down
22 changes: 22 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,28 @@ Note that the snapshot does not always match the command output because of the w
This is intentional so outputs stay consistent for snapshot testing.
The order of stdout and stderr in a snapshot may differ from what you see in the terminal, but the combined output is stable.

### Generator tests

Client generation has its own suite: `npm run client-generators` runs the `@redocly/client-generator` unit tests together with the `tests/e2e/generate-client` end-to-end tests, so one command covers everything about generation.

```bash
npm run client-generators # every generator test
npm run client-generators -- tests/e2e/generate-client/go.test.ts # one file
npm run client-generators -- -t 'gofmt' # by test name
```

Those e2e tests compile their output with real toolchains, so what is available decides what runs:

- **Python** (`python3`, plus `httpx` for the import bars) and **Go** (`go build`, `go vet`, `gofmt`) and **PHP** (`php -l`) — a bar for a missing toolchain skips itself rather than failing, so a partial local setup still gives a useful run. CI installs Python and `httpx`; Go and PHP come with the runner image.
- The largest bars generate from big real-world descriptions (Rebilly, the GitHub REST API), which is why they are slow and why the suite has its own CI job — a growing set of compiled-language bars must not slow the shared e2e job.

`npm run e2e` covers everything under `tests/e2e/` **except** `generate-client`.
`npm run unit` still includes the client-generator unit tests, so the coverage report stays whole.

Several of these tests run a local HTTP server and assert on its request log.
On a machine with many cores, vitest runs enough of them in parallel to occasionally reset a connection — a failure that says nothing about the code under test.
Reading a server's log goes through `serverLog()` in `tests/e2e/generate-client/helpers.ts`, which retries for that reason; if you see an isolated `ECONNRESET` or `fetch failed`, re-run the file before investigating.

### Smoke tests

Smokes are for testing the CLI in different environments.
Expand Down
Loading
Loading