This document is the primary reference for contributors. Read it before implementing any module.
APilot is a multi-module monorepo that parses API source code and exports documentation in multiple formats. The architecture has three layers:
┌─────────────────────────────────────────────────────────────┐
│ IDE Integration Layer │
│ jetbrains-plugin (Kotlin/Gradle) │ vscode-plugin (TS) │
└──────────────────────┬──────────────────────────────────────┘
│ subprocess (vscode only)
┌──────────────────────▼──────────────────────────────────────┐
│ Go Engine Layer │
│ apilot-cli → api-master → api-collector / api-formatter│
└──────────────────────┬──────────────────────────────────────┘
│ implements
┌──────────────────────▼──────────────────────────────────────┐
│ Collector / Formatter Modules │
│ api-collector-{java,go,node,python} │
│ api-formatter-{markdown,curl,postman} │
└─────────────────────────────────────────────────────────────┘
| Module | Language | Role |
|---|---|---|
api-model |
Go | Canonical data types: ApiEndpoint, ApiParameter, ApiHeader, ApiBody |
api-collector |
Go | Collector interface + CollectContext |
api-formatter |
Go | Formatter interface + FormatOptions |
api-master |
Go | Core engine: CLI, registry, plugin loader, orchestration |
apilot-cli |
Go | Bundled CLI: statically links all collectors + formatters |
api-collector-java |
Go | Java/Kotlin collector (Spring MVC, JAX-RS, Feign) |
api-collector-go |
Go | Go collector (Gin, Echo, Fiber) |
api-collector-node |
Go | Node.js collector (Express, Fastify, NestJS) |
api-collector-python |
Go | Python collector (FastAPI, Django REST, Flask) |
api-formatter-markdown |
Go | Markdown formatter (simple + detailed templates) |
api-formatter-curl |
Go | cURL command formatter |
api-formatter-postman |
Go | Postman Collection v2.1 formatter |
vscode-plugin |
TypeScript | VSCode extension: invokes apilot-cli as subprocess |
jetbrains-plugin |
Kotlin | IntelliJ plugin: PSI-based, no Go dependency |
apilot-cli
├── api-master (engine + plugin runtime)
├── api-collector-java
├── api-collector-go
├── api-collector-node
├── api-collector-python
├── api-formatter-markdown
├── api-formatter-curl
└── api-formatter-postman
api-master
├── api-collector (interface only)
└── api-formatter (interface only)
api-collector
└── api-model
api-formatter
└── api-model
api-collector-{java,go,node,python}
└── api-collector
api-formatter-{markdown,curl,postman}
├── api-model (for ApiEndpoint type)
└── api-formatter
vscode-plugin
└── apilot-cli (bundled binary, no Go import)
jetbrains-plugin
└── (no dependency on any Go module)
Rule: No module may import a module above it in the graph. api-model is the only shared data contract; api-collector and api-formatter are the only shared interface contracts. Formatters depend on api-model directly — never on api-collector.
[Source Code]
│
▼
[Collector.Collect(CollectContext)]
│
│ []ApiEndpoint
▼
[api-master engine]
│
│ []ApiEndpoint + FormatOptions
▼
[Formatter.Format(...)]
│
│ []byte
▼
[stdout | file | VSCode output channel]
For subprocess plugins, CollectContext is written as JSON to the subprocess stdin, and []ApiEndpoint JSON is read from stdout. See plugin-protocol.md for the full protocol spec.
- Create a new module directory:
api-collector-<lang>/ - Add
go.modwith module pathgithub.com/tangcent/apilot/api-collector-<lang> - Declare dependency on
github.com/tangcent/apilot/api-collector - Create
collector.gowith a struct implementingcollector.Collector:Name() string— unique lowercase identifier (e.g."rust")SupportedLanguages() []string— language identifiers (e.g.["rust"])Collect(ctx collector.CollectContext) ([]collector.ApiEndpoint, error)
- Add sub-packages per framework under
<framework>/parser.go - Export a
New() collector.Collectorconstructor - Register in
apilot-cli/main.go:engine.RegisterCollector(rustcollector.New())
- Return
nil, nil(not an error) when no endpoints are found. - Skip unparseable files with a log warning; do not fail the whole collection.
- Populate
ApiEndpoint.Protocol— use"http"for REST endpoints. - Use
ApiEndpoint.Folderto group related endpoints (maps to Postman folders / Markdown sections).
- Create a new module directory:
api-formatter-<name>/ - Add
go.modwith module pathgithub.com/tangcent/apilot/api-formatter-<name> - Declare dependencies on
api-modelandapi-formatter - Create
formatter.gowith a struct implementingformatter.Formatter:Name() string— unique lowercase identifier (e.g."openapi")SupportedFormats() []string— format variant namesFormat(endpoints []model.ApiEndpoint, opts formatter.FormatOptions) ([]byte, error)
- Export a
New() formatter.Formatterconstructor - Register in
apilot-cli/main.go:engine.RegisterFormatter(openapifmt.New())
- An empty
endpointsslice MUST return valid empty output, never an error. - Use
opts.Formatto select output variant; default to the first supported format. - Use
opts.Configfor formatter-specific options.
Any binary that speaks the stdin/stdout JSON protocol can be registered as a plugin without recompiling apilot-cli. See plugin-protocol.md.
Register in ~/.config/apilot/plugins.json:
{
"plugins": [
{
"name": "rust",
"type": "collector",
"command": "api-collector-rust",
"args": []
}
]
}Third-party developers can build collectors or formatters for private frameworks or API management tools without contributing to this monorepo. There are two integration paths:
Import the published SDK modules directly:
// go.mod
require (
github.com/tangcent/apilot/api-model v<version>
github.com/tangcent/apilot/api-collector v<version> // collectors only
github.com/tangcent/apilot/api-formatter v<version> // formatters only
)Implement the interface, build a binary, and distribute it. Users add it to their local apilot-cli by forking or by using Path B below.
Published SDK modules:
| Module | Purpose |
|---|---|
github.com/tangcent/apilot/api-model |
Data types only — import this for ApiEndpoint etc. |
github.com/tangcent/apilot/api-collector |
Collector interface + CollectContext |
github.com/tangcent/apilot/api-formatter |
Formatter interface + FormatOptions |
Build a standalone binary in any language that speaks the stdin/stdout JSON protocol. No Go dependency required. See plugin-protocol.md for the full spec.
# Register your plugin
cat ~/.config/apilot/plugins.json
{
"plugins": [
{ "name": "my-framework", "type": "collector", "command": "/usr/local/bin/api-collector-myframework" },
{ "name": "my-tool", "type": "formatter", "command": "/usr/local/bin/api-formatter-mytool" }
]
}The subprocess protocol is stable and versioned — private or proprietary implementations are fully supported this way.
| Path A (Go SDK) | Path B (Subprocess) | |
|---|---|---|
| Language | Go only | Any |
| Performance | Best (in-process) | Good (one subprocess per run) |
| Distribution | Go module / binary | Any binary |
| Private framework | ✓ | ✓ |
| No recompile needed | ✗ (fork apilot-cli) | ✓ |
# Build apilot for all platforms
GOOS=linux GOARCH=amd64 go build -o bin/apilot-linux-amd64 ./apilot-cli
GOOS=linux GOARCH=arm64 go build -o bin/apilot-linux-arm64 ./apilot-cli
GOOS=darwin GOARCH=amd64 go build -o bin/apilot-darwin-amd64 ./apilot-cli
GOOS=darwin GOARCH=arm64 go build -o bin/apilot-darwin-arm64 ./apilot-cli
GOOS=windows GOARCH=amd64 go build -o bin/apilot-windows-amd64.exe ./apilot-clicd vscode-plugin
npm ci
npm run compile
# Copy platform binaries into vscode-plugin/bin/ before packaging
npx vsce packagecd jetbrains-plugin
./gradlew buildPlugin
# Artifact: build/distributions/apilot-<version>.zip| Workflow | Trigger | What it does |
|---|---|---|
.github/workflows/ci.yml |
push / PR | go test ./... + go vet ./... for all Go modules |
.github/workflows/co.yml |
push / PR | Coverage report upload to Codecov |
- Java parsing strategy — pure Go parser vs.
tree-sitter-javaCGO bindings vs. subprocessjavac. Needs a spike. - Node.js collector —
tree-sitter-typescriptrequires CGO. Evaluate pure-Go JS/TS AST (e.g.goja) for route extraction. - Shared library plugins (
dynlib.go) — requires CGO (dlopen). Deferred to v2; v1 ships subprocess-only plugin support. - Binary size — static linking all collectors may produce a large
apilot-cli. Evaluateupxcompression for release artifacts.