oastools
Copilot instructions7 starsChanged 9 months agoMITView on GitHub
This file provides guidance to GitHub Copilot when working with code in this repository. GitHub Copilot uses these instructions to: Read through all sections before making changes. Pay special attention to: oastools is a Go-based command-line tool for working with OpenAPI Specification (OAS) files. The primary goals are: This tool supports the following OpenAPI Specification versions: All OAS versions utilize the JSON Schema Specification Draft 2020-12: https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html OAS 2.0 (Swagger) → OAS 3.0: OAS 3.0 → OAS 3.1: Some fields…
In this repository9 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- plugin/CLAUDE.mdCLAUDE.md
- corpus-testSkill
- gen-testSkill
- prepare-releaseSkill
- prereviewSkill
- publish-releaseSkill
- quality-gateSkill
The file
Show its rules and text
We split this copilot-instructions.md into the rules it gives an agent
34 rules. About 1 is common, 19 are distinctive, and 14 are very specific to this project.
≈1
Common · estimate
Many files like this have a rule of this kind.
≈19
Distinctive · estimate
This author's own choices. Worth a look.
14
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 11
Follow the same standards that human developers follow
- Distinctive: line 12
Avoid common pitfalls specific to this codebase
- Distinctive: line 14
Read through all sections before making changes.
- Distinctive: line 19
Testing Requirements: - All exported functionality must have comprehensive tests
- Very specific: line 20
Benchmark Test Requirements: - Use Go 1.24+ for b.Loop() pattern
- Very specific: line 41
All OAS versions utilize the JSON Schema Specification Draft 2020-12: https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html
- Very specific: line 86
Assuming schema.Type is always a string: - Read it through internal/schemautil rather than asserting inline
- Very specific: line 87
Creating value slices instead of pointer slices: - Check parser types and use &Type{...} syntax
- Distinctive: line 88
Forgetting to track conversion issues: - Add issues for every lossy conversion or unsupported feature
- Distinctive: line 90
Not handling operation-level consumes/produces: - Check operation-level first, then fall back to document-level
- Distinctive: line 117
After making changes to Go source files:
- Distinctive: line 157
testdata/: - Test fixtures including sample OAS files
- Distinctive: line 169
Default to YAML if unknown
- Distinctive: line 188
Test coverage must include:
- Distinctive: line 192
Exported Constants: - Verify expected values
- Very specific: line 227
Call b.ReportAllocs(). b.Loop() does not report allocations on its own.
- Very specific: line 231
Use for i := 0; i < b.N; i++ (old pattern)
- Very specific: line 232
Call b.ResetTimer() for trivial setup
- Very specific: line 251
Add minimal permissions block to GitHub Actions workflows:
- Very specific: line 263
Run make check - all code formatted, lints/tests pass
- Very specific: line 264
Run make test-coverage - review coverage report
- Distinctive: line 265
Verify all new exported functionality has tests
- Very specific: line 266
Update benchmarks with make bench-save if changes affect performance
- Very specific: line 267
Check for security vulnerabilities: govulncheck
- Distinctive: line 286
Code Changes: All required functionality is implemented
- Very specific: line 293
Security: No new security vulnerabilities introduced (verify with govulncheck if dependencies change)
- Distinctive: line 312
Add dependencies without checking for security vulnerabilities first
- Distinctive: line 314
Remove or weaken existing test coverage
- Distinctive: line 316
Commit secrets, credentials, or sensitive data
- Very specific: line 317
Create temporary files in the repository root (use /tmp instead)
- Distinctive: line 326
All core packages are public:
- Distinctive: line 343
Use convenience functions for: simple scripts, prototyping, default configuration Use struct-based API for: multiple files, reusable …
- Distinctive: line 344
Use struct-based API for: multiple files, reusable instances, advanced configuration, performance
- Common: line 363
All input documents must be pre-validated (Errors slice must be empty)
≈ “Common” is an estimate: at least 1 in 5 of the 3,779 Copilot instructions files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
GitHub Copilot Instructions for oastools
This file provides guidance to GitHub Copilot when working with code in this repository.
How to Use This File
GitHub Copilot uses these instructions to:
- Understand the project structure, conventions, and best practices
- Make informed decisions when generating or modifying code
- Follow the same standards that human developers follow
- Avoid common pitfalls specific to this codebase
Read through all sections before making changes. Pay special attention to:
- Development Environment Setup - Install golangci-lint v2 before running
make check - Acceptance Criteria - Know when a task is truly complete
- Boundaries and Exclusions - Files and directories you should never modify
- Testing Requirements - All exported functionality must have comprehensive tests
- Benchmark Test Requirements - Use Go 1.24+
for b.Loop()pattern
Project Overview
oastools is a Go-based command-line tool for working with OpenAPI Specification (OAS) files. The primary goals are:
- Validating OpenAPI specification files
- Parsing and analyzing OAS documents
- Joining multiple OpenAPI specification documents
- Converting between OAS versions
- Comparing OAS documents and detecting breaking changes
Specification References
This tool supports the following OpenAPI Specification versions:
- OAS 2.0 (Swagger): https://spec.openapis.org/oas/v2.0.html
- OAS 3.0.x: https://spec.openapis.org/oas/v3.0.0.html through v3.0.4
- OAS 3.1.x: https://spec.openapis.org/oas/v3.1.0.html through v3.1.2
- OAS 3.2.0: https://spec.openapis.org/oas/v3.2.0.html
All OAS versions utilize the JSON Schema Specification Draft 2020-12: https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html
Key OpenAPI Specification Concepts
OAS Version Evolution
OAS 2.0 (Swagger) → OAS 3.0:
- Servers:
host,basePath, andschemes→ unifiedserversarray with URL templates - Components:
definitions,parameters,responses,securityDefinitions→components.* - Request Bodies:
consumes+ body parameter →requestBody.contentwith media types - Response Bodies:
produces+ schema →responses.*.contentwith media types - Security:
securityDefinitions→components.securitySchemeswith flows restructuring - New Features: Links, callbacks, and more flexible parameter serialization
OAS 3.0 → OAS 3.1:
- JSON Schema Alignment: OAS 3.1 fully aligns with JSON Schema Draft 2020-12
- Type Arrays:
typecan be a string or array (e.g.,type: ["string", "null"]) - Nullable Handling: Deprecated
nullable: truein favor oftype: ["string", "null"] - Webhooks: New top-level
webhooksobject for event-driven APIs - License: Added
identifierfield to license object
Type System
Some fields are interface{} because the specification allows more than one shape there. schema.Type is the common one. Read it through internal/schemautil, which owns the assertion and documents the shapes it can hold, rather than asserting inline.
Nested structures are pointer slices ([]*parser.Server), so construct them with &parser.Server{...}.
Version-Specific Features
OAS 2.0 Only:
allowEmptyValue,collectionFormat, singlehost/basePath/schemes
OAS 3.0+ Only:
requestBody,callbacks,links, cookie parameters,serversarray, TRACE method
OAS 3.1+ Only:
webhooks, JSON Schema 2020-12 alignment,typeas array,license.identifier
Common Pitfalls and Solutions
- Assuming schema.Type is always a string - Read it through
internal/schemautilrather than asserting inline - Creating value slices instead of pointer slices - Check parser types and use
&Type{...}syntax - Forgetting to track conversion issues - Add issues for every lossy conversion or unsupported feature
- Mutating source documents - Deep copy before modification using generated
DeepCopy()methods on parser types (e.g.,doc.DeepCopy()). Never use JSON marshal/unmarshal for deep copying — it silently losesinterface{}type distinctions (e.g.,stringvs[]stringin OAS 3.1schema.Type) and drops fields taggedjson:"-". When the caller owns the document and won't reuse it, useWithMutableInput(true)to skip the copy entirely. - Not handling operation-level consumes/produces - Check operation-level first, then fall back to document-level
- Ignoring version-specific features during conversion - Explicitly check and warn about features that don't convert
Development Commands
Development Environment Setup
CRITICAL: Install the pinned golangci-lint before running make check
The repository pins one golangci-lint version, GOLANGCI_VERSION in the Makefile,
and both CI workflows read it from there. Install that version before making any
code changes:
make lint-install
# Add GOPATH/bin to PATH if not already present
export PATH=$PATH:$(go env GOPATH)/binmake lint refuses to run against any other version — findings would not match
CI, which is what the pin exists to prevent. Do not install a version by hand:
the Makefile is the single source of truth, so a hardcoded version here would
drift out of date the moment the pin moves.
Recommended Workflow
After making changes to Go source files:
make check # Runs all quality checks (tidy, fmt, lint, test) and shows git statusCommon Commands
# Building
make build # Build binary to bin/oastools
make install # Install to $GOPATH/bin
# Testing
make test # Run all tests with race detection and coverage
make test-coverage # Generate and view HTML coverage report
# Code Quality
make fmt # Format all Go code
make vet # Run go vet
make lint # Run golangci-lint (requires golangci-lint v2 installation)
# Maintenance
make deps # Download and tidy dependencies
make clean # Remove build artifactsArchitecture
Directory Structure
- cmd/oastools/ - CLI entry point with command routing
- parser/ - Parse YAML/JSON OAS files, resolve references, detect versions
- validator/ - Validate OAS against spec schema (structural, format, semantic)
- converter/ - Convert between OAS versions (2.0 ↔ 3.x) with issue tracking
- joiner/ - Join multiple OAS files with flexible collision resolution
- differ/ - Compare OAS files, detect breaking changes by severity
- generator/ - Generate Go code (clients, servers, types) from OAS files
- builder/ - Build OAS documents programmatically with reflection-based schema generation
- internal/ - Shared utilities (httputil, severity, issues, testutil)
- testdata/ - Test fixtures including sample OAS files
Each public package includes doc.go (package docs) and example_test.go (godoc examples).
Design Patterns
IMPORTANT: The parser, converter, and joiner automatically preserve the input file format (JSON or YAML).
Format detection:
- From file extension (
.json,.yaml,.yml) - From content (JSON starts with
{or[) - Default to YAML if unknown
- First file determines output format for joiner
IMPORTANT: Use package-level constants instead of string literals.
- HTTP Methods:
httputil.MethodGet,httputil.MethodPost, etc. - Severity Levels:
severity.SeverityError,severity.SeverityWarning, etc.
HTTP status codes have no string constants. The standard library's are int
(http.StatusOK), which is what an int-taking API wants, including builder.WithResponse.
An OAS document keys responses by string, so write the literal there ("200"), which is how
httputil.StandardHTTPStatusCodes stores its own keys. Use httputil.IsStatusCode,
httputil.IsSuccessStatusCode, or httputil.IsStandardStatusCode to check a code a document
supplies.
Testing Requirements
CRITICAL: All exported functionality MUST have comprehensive test coverage.
Test coverage must include:
- Exported Functions - Package-level convenience functions and struct methods
- Exported Types - Struct initialization, fields, type conversions
- Exported Constants - Verify expected values
Coverage types:
- Positive Cases: Valid inputs work correctly
- Negative Cases: Error handling with invalid inputs, missing files, malformed data
- Edge Cases: Boundary conditions, empty inputs, nil values
- Integration: Components working together (parse then validate, parse then join)
Benchmark Test Requirements
CRITICAL: Use the Go 1.24+ for b.Loop() pattern for all benchmarks.
Correct pattern:
func BenchmarkOperation(b *testing.B) {
// Setup (parsing, creating instances, etc.)
source, _ := parser.ParseWithOptions(
parser.WithFilePath("file.yaml"),
parser.WithValidateStructure(true),
)
b.ReportAllocs()
for b.Loop() { // ✅ Modern Go 1.24+ pattern
_, err := Operation(source)
if err != nil {
b.Fatal(err)
}
}
}DO:
- Call
b.ReportAllocs().b.Loop()does not report allocations on its own.
DO NOT:
- Use
for i := 0; i < b.N; i++(old pattern) - Call
b.ResetTimer()for trivial setup
Security
Common Security Alert Fixes
Size computation for allocation may overflow (CWE-190):
// Safe pattern - use uint64 for arithmetic, check fits in int
capacity := 0
sum := uint64(len(a)) + uint64(len(b))
if sum <= uint64(math.MaxInt) {
capacity = int(sum)
}
result := make([]string, 0, capacity)Workflow permissions (CWE-275):
Add minimal permissions block to GitHub Actions workflows:
permissions:
contents: read # Minimal permissions following principle of least privilegeCode Quality Standards
Before Submitting:
- Install golangci-lint v2 - Required for
make checkandmake lint(see Development Environment Setup) - Run
make check- all code formatted, lints/tests pass - Run
make test-coverage- review coverage report - Verify all new exported functionality has tests
- Update benchmarks with
make bench-saveif changes affect performance - Check for security vulnerabilities:
govulncheck
Never submit code with:
- Untested exported functions, methods, or types
- Tests that only cover the "happy path" without error cases
- Performance regressions without documented justification
- Linting errors (all golangci-lint checks must pass)
Commit Message Format:
- First line: Conventional commit message within 72 characters
- Body: Simply formatted (max 100 columns), basic reasoning and changes
- PR: Same title as commit, detailed markdown with reasoning, changes, and context
Acceptance Criteria
A task is considered complete when ALL of the following are met:
- Code Changes: All required functionality is implemented
- Tests: New/modified exported functions have comprehensive tests (positive, negative, edge cases)
- Build:
make buildsucceeds without errors or warnings - Tests Pass:
make testpasses with no failures - Code Quality: Code is formatted (
make fmt) and follows existing patterns - Documentation: Public APIs have godoc comments; non-trivial changes update relevant docs
- No Regressions: Existing tests still pass; no breaking changes to public APIs (unless intentional)
- Security: No new security vulnerabilities introduced (verify with
govulncheckif dependencies change)
For documentation-only changes, only items 3, 6, and 7 apply.
Boundaries and Exclusions
DO NOT modify these files/directories:
.github/workflows/- CI/CD workflows (except when specifically requested)testdata/- Test fixtures (except when adding new test cases)vendor/- External dependencies (managed by Go modules)bin/,dist/- Build artifacts (generated by build tools).git/- Version control internalsgo.mod,go.sum- Only modify when explicitly adding/removing dependencies.goreleaser.yaml- Release configuration (managed separately)benchmarks/- Benchmark data (except when updating benchmarks per BENCHMARK_UPDATE_PROCESS.md)
DO NOT:
- Add dependencies without checking for security vulnerabilities first
- Modify benchmark test patterns (must use Go 1.24+
for b.Loop()pattern) - Remove or weaken existing test coverage
- Change public API signatures without documenting breaking changes
- Commit secrets, credentials, or sensitive data
- Create temporary files in the repository root (use
/tmpinstead)
Go Module
- Module path:
github.com/erraggy/oastools - Minimum Go version: 1.25
Public API Structure
All core packages are public:
github.com/erraggy/oastools/parser- Parse OpenAPI specificationsgithub.com/erraggy/oastools/validator- Validate OpenAPI specificationsgithub.com/erraggy/oastools/converter- Convert between OpenAPI specification versionsgithub.com/erraggy/oastools/joiner- Join multiple OpenAPI specificationsgithub.com/erraggy/oastools/differ- Compare and diff OpenAPI specificationsgithub.com/erraggy/oastools/generator- Generate Go code from OpenAPI specificationsgithub.com/erraggy/oastools/builder- Build OpenAPI specifications programmatically
API Design Philosophy
Two complementary API styles:
- Package-level convenience functions - For simple, one-off operations
- Struct-based API - For reusable instances with configuration
Use convenience functions for: simple scripts, prototyping, default configuration Use struct-based API for: multiple files, reusable instances, advanced configuration, performance
Key API Features
Parser Package:
- Functional options:
parser.ParseWithOptions(parser.WithFilePath(...), parser.WithResolveRefs(...), ...) - Struct-based:
parser.New(),Parser.Parse(),Parser.ParseReader(),Parser.ParseBytes() ParseResult.SourcePathtracks source ("ParseReader.yaml"for readers,"ParseBytes.yaml"for bytes)
Validator Package:
- Functional options:
validator.ValidateWithOptions(validator.WithFilePath(...), validator.WithIncludeWarnings(...), ...) - Struct-based:
validator.New(),Validator.Validate(),Validator.ValidateParsed()
Joiner Package:
- Functional options:
joiner.JoinWithOptions(joiner.WithFilePaths(...), joiner.WithPathStrategy(...), ...) - Struct-based:
joiner.New(),Joiner.Join(),Joiner.JoinParsed(),Joiner.WriteResult() - All input documents must be pre-validated (Errors slice must be empty)
Converter Package:
- Functional options:
converter.ConvertWithOptions(converter.WithFilePath(...), converter.WithTargetVersion(...), ...) - Struct-based:
converter.New(),Converter.Convert(),Converter.ConvertParsed() - Configuration:
StrictMode,IncludeInfo - Returns ConversionResult with severity-tracked issues (Info, Warning, Critical)
Differ Package:
- Functional options:
differ.DiffWithOptions(differ.WithSourceFilePath(...), differ.WithTargetFilePath(...), differ.WithMode(...), ...) - Struct-based:
differ.New(),Differ.Diff(),Differ.DiffParsed() - Returns DiffResult with changes categorized by severity (Critical, Error, Warning, Info)
Usage Examples
Quick operations:
// Parse
result, _ := parser.ParseWithOptions(
parser.WithFilePath("openapi.yaml"),
parser.WithValidateStructure(true),
)
// Validate
result, _ := validator.ValidateWithOptions(
validator.WithFilePath("openapi.yaml"),
validator.WithIncludeWarnings(true),
)
// Join
result, _ := joiner.JoinWithOptions(
joiner.WithFilePaths("base.yaml", "ext.yaml"),
joiner.WithConfig(joiner.DefaultConfig()),
)
// Convert
result, _ := converter.ConvertWithOptions(
converter.WithFilePath("swagger.yaml"),
converter.WithTargetVersion("3.0.3"),
)
// Diff
result, _ := differ.DiffWithOptions(
differ.WithSourceFilePath("v1.yaml"),
differ.WithTargetFilePath("v2.yaml"),
)Reusable instances:
// Parser for multiple files
p := parser.New()
p.ResolveRefs = false
result1, _ := p.Parse("api1.yaml")
result2, _ := p.Parse("api2.yaml")
// Validator with config
v := validator.New()
v.IncludeWarnings = true
result1, _ := v.Validate("api1.yaml")
// Joiner with strategy
j := joiner.New(config)
result1, _ := j.Join([]string{"api1-base.yaml", "api1-ext.yaml"})
// Converter with settings
c := converter.New()
c.StrictMode = false
result1, _ := c.Convert("swagger-v1.yaml", "3.0.3")
// Differ for multiple comparisons
d := differ.New()
result1, _ := d.Diff("api-v1.yaml", "api-v2.yaml")
result2, _ := d.Diff("api-v2.yaml", "api-v3.yaml")Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

