phyllotaxis 0.3.1

Progressive disclosure CLI for OpenAPI documents — explore one layer at a time
Documentation

CI crates.io License

An LLM-friendly CLI for exploring OpenAPI documents one layer at a time. Instead of stuffing an entire spec into a prompt, give the model exactly the slice it needs — one resource group, one endpoint, one schema.

Works great for humans too. Outputs plain text or JSON. Also available as phyll (shorter alias, same binary).

Install

Homebrew (macOS, Linux)

brew install openscribbler/tap/phyllotaxis

cargo install

cargo install phyllotaxis

Download a binary

Grab the latest release for your platform from GitHub Releases.

Linux / macOS:

# Pick your platform:
#   x86_64-unknown-linux-gnu    (Linux x86_64)
#   aarch64-unknown-linux-gnu   (Linux ARM64)
#   x86_64-apple-darwin         (macOS Intel)
#   aarch64-apple-darwin        (macOS Apple Silicon)
PLATFORM="x86_64-unknown-linux-gnu"

curl -L "https://github.com/OpenScribbler/phyllotaxis/releases/latest/download/phyllotaxis-${PLATFORM}.tar.gz" \
  | tar xz -C ~/.local/bin

Windows:

Download the phyllotaxis-x86_64-pc-windows-msvc.zip from the releases page, extract it, and add the folder to your PATH.

Build from source

Requires Rust (install via rustup).

git clone https://github.com/OpenScribbler/phyllotaxis.git
cd phyllotaxis
cargo build --release
# Binaries are in target/release/phyllotaxis and target/release/phyll

Verify

phyll --help

Why?

OpenAPI documents get big fast. Dumping one into a prompt creates problems beyond token cost:

  • Precision — models hallucinate when they have to pick relevant fields out of thousands. Focused context means fewer mistakes.
  • Agent-friendly — an LLM agent can call phyll iteratively: overview → resource → endpoint → schema. Each step is a tool call with a focused response.
  • Deterministic — same query, same output. No prompt engineering to extract the right slice.
  • Small models work — Haiku, local models, and cost-constrained setups can't fit a full spec. Phyll makes them viable.

Works great for humans too — same progressive disclosure, just without the token math.

Commands

Command What it shows
phyll API overview: title, description, base URLs, auth, top resources
phyll --resources All resource groups with endpoint counts
phyll --resources <name> Endpoints in a resource group
phyll --endpoint <METHOD> <path> Full endpoint detail: params, request body, responses
phyll --schemas All schemas
phyll --schemas <name> Schema detail: fields, types, composition
phyll --schemas <name> --used-by Which endpoints use this schema
phyll --schemas <name> --example Generate an example JSON object
phyll --auth Auth schemes and how they're used
phyll search <term> Search across everything
phyll --callbacks Webhook callbacks
phyll --callbacks <name> Callback detail
phyll init Auto-detect OpenAPI documents and write config
phyll completions <shell> Shell completions (bash, zsh, fish, powershell, elvish)

Global Flags

--doc <name|path>           Override which document to use
--json                       Output JSON instead of text
--expand                     Inline nested schemas recursively (max depth 5)
--related-limit <n>          Cap how many related schemas to show

Endpoint Detail Flags

--context     Show related schemas expanded after the endpoint
--example     Show an auto-generated example request/response body

How the Layers Work

Phyllotaxis auto-detects OpenAPI documents in your project, or you can run phyll init to configure one. For one-off exploration, pass the file directly with --doc. See Document Discovery for the full resolution order.

The first example uses --doc to show one-off usage. The rest assume a document is already configured.

Level 0: Overview

$ phyll --doc petstore.yaml
API: Petstore API
Base URL: https://petstore.example.com
Auth: bearerAuth

Top Resources:
  pets                     (4 endpoints)
  deprecated-pets          (2 endpoints)

Commands:
  phyll --resources   List all resource groups (3 available)
  phyll --schemas     List all data models (4 available)
  phyll --auth        Authentication details
  phyll search        Search across all endpoints and schemas

Level 1: Resource Listing

$ phyll --resources
Resources:
  pets              Pet management
  deprecated-pets   [DEPRECATED]  Old pet endpoints
  experimental      [ALPHA]       Alpha feature endpoints

Level 2: Resource Detail

$ phyll --resources pets
Resource: Pets

Endpoints:
  GET     /pets         List all pets
  POST    /pets         Create a pet
  GET     /pets/{id}    Get a pet by ID
  DELETE  /pets/{id}    Delete a pet

Level 3: Endpoint Detail

$ phyll --endpoint POST /pets
POST /pets

Authentication: bearerAuth (required)

Request Body (application/json):
  name      string       (required)              Pet name

Request Example:
  { "name": "Fido" }

Responses:
  201 Created → Pet

Errors:
  400 Invalid input
  409 Duplicate pet

Drill deeper:
  phyll --schemas Pet

Schema Detail

$ phyll --schemas Pet
Schema: Pet

Fields:
  id        string/uuid  (required, read-only)  Unique identifier
  name      string       (required)             Pet name
  status    string       (optional)             Enum: [available, pending, sold]
  nickname  string       (optional, nullable)   Optional nickname
  owner     Owner        (optional)

Related schemas:
  phyll --schemas Owner

Callbacks

$ phyll --callbacks
Callbacks:
  onPetAdded    Defined on: POST /pets
$ phyll --callbacks onPetAdded
Callback: onPetAdded
Defined on: POST /pets

Operations:
  POST {$request.body#/callbackUrl}
    Body: PetEvent
    Responses:
      200 Callback received

Example Generation

Generate example JSON from any schema:

$ phyll --schemas Pet --example
Example (Pet, required fields, auto-generated):
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "string"
}

Placeholders are based on the field type and format:

Type/Format Placeholder
string "string"
string/uuid "550e8400-e29b-41d4-a716-446655440000"
string/date-time "2024-01-15T10:30:00Z"
string/email "user@example.com"
string/uri "https://example.com"
integer 0
boolean true
enum First enum value

If the document has example values on schemas or properties, those get used instead. For discriminated unions (oneOf with a discriminator), the type field gets set to the correct mapped value.

Reverse Schema Lookup

Find out which endpoints use a given schema:

$ phyll --schemas TagDTO --used-by
Schema: TagDTO

Used by 114 endpoint(s):

  In request body:
    POST    /api/v1/access-conditions
    PUT     /api/v1/access-conditions
    ...

  In response:
    GET     /api/v1/access-conditions/{id}
    ...

This catches direct $ref references, allOf/oneOf/anyOf compositions, and schemas nested as fields inside other schemas that an endpoint uses.

Related Schemas (--context)

When you're looking at an endpoint, --context expands the schemas referenced in the request/response body:

$ phyll --endpoint POST /api/v2/access-policies --context
POST /api/v2/access-policies
...

Related Schemas:

  TagDTO (Aembit Entity Tag Details):
  key    string  (required)  Tag Key
  value  string  (required)  Tag Key Value

  PolicyCredentialMappingDTO (Access Policy Credential Mappings):
  credentialProviderId  string/uuid  (required)
  mappingType           enum         (required)  [None, AccountName, HttpHeader, HttpBody]
  ...

For oneOf/anyOf endpoints, --context shows the variant schemas too.

Schema Expansion

$ phyll --schemas Pet --expand
Schema: Pet (expanded)

Fields:
  id        string/uuid  (required, read-only)  Unique identifier
  name      string       (required)             Pet name
  status    string       (optional)             Enum: [available, pending, sold]
  nickname  string       (optional, nullable)   Optional nickname
  owner     Owner:
    id    string  (read-only)   Owner identifier
    name  string                Owner name

Search

Search across resources, endpoints, schemas, security schemes, and callbacks:

$ phyll search "authentication"

Searches resource names/descriptions, endpoint paths/summaries/descriptions, parameter names/descriptions, request body descriptions, response descriptions, schema names/descriptions/field names, and security scheme names/descriptions.

If a match comes from somewhere non-obvious (like a parameter name or description text), the result tells you why it matched.

JSON Output

Every command supports --json. It's pretty-printed in a terminal and compact when piped:

$ phyll --json --schemas Pet | jq '.fields[].name'
"id"
"name"
"status"
"nickname"
"owner"

Fuzzy Matching

Mistype a name and phyllotaxis suggests close matches:

$ phyll --resources pet
Error: Resource 'pet' not found.
Did you mean:
  phyll --resources pets

Document Discovery

Phyllotaxis finds your OpenAPI document in four ways (checked in this order):

  1. --doc flag - named document from config or a file path, always wins
  2. PHYLLOTAXIS_DOCUMENT env var - set to a file path; errors if the file doesn't exist, ignored if empty
  3. .phyllotaxis.yaml config - created by phyll init, checked in the current directory and parents
  4. Auto-detect - scans for *.yaml/*.yml/*.json files with openapi: in the first 200 bytes

Run phyll init to set up a config:

$ phyll init
Detected framework: Astro
Found document candidates:
  1. ./static/openapi.yaml
Select a document (enter number) or type a path: 1
Initialized. Run `phyll` to see your API overview.

For non-interactive setup (CI, scripts), pass the path directly:

$ phyll init --doc-path ./api/openapi.yaml

Multi-Document Projects

If your project has multiple API documents, use named documents in .phyllotaxis.yaml:

documents:
  public: ./api/public.yaml
  internal: ./api/internal.yaml
default: public
variables:
  tenant: my-org
  env: staging

Then pick one by name:

$ phyll --doc internal --resources

The variables map fills in server URL template variables (e.g., {tenant} becomes my-org in base URL output).

Compatibility

  • OpenAPI 3.0.x - fully supported
  • OpenAPI 3.1 - not supported (the openapiv3 parser targets 3.0)
  • Swagger / OpenAPI 2.0 - not supported
  • YAML and JSON documents - both work
  • $ref resolution - local and external file references (multi-file documents)

Project Structure

phyllotaxis/
├── src/
│   ├── main.rs              # CLI entry point (clap)
│   ├── lib.rs               # Public crate API (re-exports)
│   ├── spec.rs              # Config loading, document resolution, parsing
│   ├── commands/
│   │   ├── overview.rs      # L0: API overview
│   │   ├── resources.rs     # L1-L3: resource groups, detail, endpoints
│   │   ├── schemas.rs       # Schema listing, detail, expansion, --used-by
│   │   ├── examples.rs      # Example generation from schemas
│   │   ├── auth.rs          # Security scheme extraction
│   │   ├── search.rs        # Cross-type search
│   │   ├── callbacks.rs     # Webhook callback extraction
│   │   └── init.rs          # Framework detection, interactive setup
│   ├── models/
│   │   ├── resource.rs      # Data structs + helpers
│   │   └── schema.rs        # SchemaModel, Composition enum
│   └── render/
│       ├── text.rs          # Plain text output
│       └── json.rs          # JSON output
└── tests/
    ├── fixtures/
    │   ├── petstore.yaml     # Test fixture
    │   ├── kitchen-sink.yaml # Edge case fixture
    │   └── multi-file/       # External $ref test fixture
    ├── fixture_sanity.rs     # Fixture parse validation
    ├── integration_tests.rs  # End-to-end CLI tests
    └── lib_tests.rs          # Library API tests

Roadmap

Feature Status
External $ref resolution (multi-file documents) Done
Document management UX (persistent --doc, nicknames) Planned
Remote URL loading (fetch specs from HTTP/HTTPS) Planned
OpenAPI 3.1 support Planned
Swagger / OpenAPI 2.0 support Planned
MCP server (LLM tool integration) Planned

See issues for what's being worked on now.

Development

cargo build      # Debug build
cargo test       # Run all tests (unit + integration)
cargo clippy     # Lint
cargo build -r   # Release build

License

Apache-2.0