CLI Reference¶
The quill CLI provides tools for code generation, RPC calls, benchmarking, and debugging.
Installation¶
Commands Overview¶
| Command | Description |
|---|---|
quill gen |
Generate client/server code from .proto files |
quill call |
Make RPC calls (curl-for-proto) |
quill bench |
Run benchmarks against services |
quill compat |
Check protobuf compatibility |
quill explain |
Decode protobuf payloads |
quill gen¶
Generate client and server stubs from protobuf definitions.
Usage¶
Options¶
| Option | Description |
|---|---|
--lang <LANG> |
Target language(s): go, ts, rust (comma-separated) |
--out <DIR> |
Output directory (default: ./gen) |
--proto <PATH> |
Proto file or directory (default: ./proto) |
--include <PATH> |
Additional include paths |
Examples¶
# Generate Go and TypeScript
quill gen --lang go,ts --out ./gen
# Generate from specific proto
quill gen --lang rust --proto ./api/v1/service.proto
# With include paths
quill gen --lang go --include ./vendor/proto
quill call¶
Make RPC calls to Quill services. Think "curl for protobuf".
Usage¶
Arguments¶
| Argument | Description |
|---|---|
<URL> |
Full URL: http://host/package.Service/Method |
Options¶
| Option | Description |
|---|---|
--in <DATA> |
Request body as JSON or @file.json |
--header <K:V> |
Add request header (can be repeated) |
--stream |
Enable streaming mode |
--prism <PROFILE> |
Transport profile: classic, turbo, hyper |
--accept <TYPE> |
Accept content type |
--timeout <SECS> |
Request timeout in seconds |
--compress |
Enable request compression |
Examples¶
# Simple unary call
quill call http://localhost:8080/users.v1.UserService/GetUser \
--in '{"user_id": "123"}'
# With headers
quill call http://localhost:8080/api.v1.Service/Method \
--in '{"key": "value"}' \
--header "Authorization: Bearer token123"
# Server streaming
quill call http://localhost:8080/logs.v1.LogService/TailLogs \
--in '{"filter": "level=ERROR"}' \
--stream
# Using a specific transport profile
quill call http://localhost:8080/service/method \
--in '{"data": "test"}' \
--prism turbo
# Read input from file
quill call http://localhost:8080/service/method \
--in @request.json
# With timeout
quill call http://localhost:8080/service/method \
--in '{}' \
--timeout 60
Output Format¶
Responses are printed as JSON:
For streaming responses, each message is printed on a separate line:
{"timestamp": "2024-01-01T00:00:00Z", "level": "ERROR", "message": "First"}
{"timestamp": "2024-01-01T00:00:01Z", "level": "ERROR", "message": "Second"}
quill bench¶
Run benchmarks against Quill services.
Usage¶
Options¶
| Option | Description |
|---|---|
--config <FILE> |
Benchmark configuration (default: benchmarks.yaml) |
--output <FILE> |
Output file for results |
--format <FMT> |
Output format: json, csv, markdown |
--duration <SECS> |
Test duration per scenario |
--connections <N> |
Concurrent connections |
Configuration File¶
# benchmarks.yaml
scenarios:
- name: "unary-small"
method: "users.v1.UserService/GetUser"
request: '{"user_id": "123"}'
duration: 30s
connections: 10
rate: 1000 # requests per second
- name: "streaming"
method: "logs.v1.LogService/TailLogs"
request: '{"limit": 100}'
streaming: true
duration: 60s
connections: 5
targets:
- name: "local"
url: "http://localhost:8080"
- name: "staging"
url: "https://staging.example.com"
Examples¶
# Run with default config
quill bench
# Custom config
quill bench --config ./performance/benchmarks.yaml
# Quick benchmark
quill bench --duration 10 --connections 5
# Output results
quill bench --output results.json --format json
Output¶
Benchmark Results
================
Target: http://localhost:8080
Duration: 30s
Connections: 10
Scenario: unary-small
Requests: 30,245
Throughput: 1,008 req/s
Latency:
p50: 2.3ms
p90: 4.1ms
p99: 8.7ms
Errors: 0 (0.00%)
quill compat¶
Check protobuf compatibility between versions using buf.
Prerequisites¶
Install the buf CLI for full functionality:
# macOS
brew install bufbuild/buf/buf
# Linux
curl -sSL https://github.com/bufbuild/buf/releases/latest/download/buf-Linux-x86_64 -o /usr/local/bin/buf
chmod +x /usr/local/bin/buf
Usage¶
Arguments¶
| Argument | Description |
|---|---|
INPUT |
Proto files or directories to check (default: .) |
Options¶
| Option | Description |
|---|---|
-a, --against <REF> |
Compare against: git ref, local path, or buf registry |
--strict |
Exit with code 2 on breaking changes |
--config <FILE> |
Path to buf.yaml configuration |
-f, --format <FMT> |
Output format: text, json |
--error-limit <N> |
Limit number of errors (0 = unlimited) |
Examples¶
# Compare against git tag
quill compat --against v1.0.0
# Compare against main branch
quill compat --against .git#branch=main
# Compare against local directory
quill compat --against ../old-version
# Check specific directory with JSON output
quill compat --against v1.0.0 ./proto --format json
# Fail CI on breaking changes
quill compat --against HEAD~1 --strict
# Use custom buf configuration
quill compat --against main --config buf.yaml
Breaking Change Categories¶
The compatibility check detects:
- Field removals - Removing a field breaks deserialization
- Field renumbering - Changing field numbers breaks wire format
- Field type changes - Changing types (e.g., int32 to string)
- Required field additions - Adding required fields to existing messages
- Enum value removals - Removing enum values breaks existing data
- Service/method removals - Removing RPCs breaks clients
- Method signature changes - Changing input/output types
Output¶
Checking compatibility...
Input: ./proto
Against: v1.0.0
Breaking changes detected:
proto/api.proto:10:3: Field "email" was removed from message "User".
proto/api.proto:25:3: RPC "DeleteUser" was removed from service "UserService".
Found 2 breaking change(s)
JSON output (with --format json):
[
{
"file": "proto/api.proto",
"line": 10,
"column": 3,
"message": "Field \"email\" was removed from message \"User\".",
"rule": "FIELD_SAME_NAME"
}
]
quill explain¶
Decode and explain protobuf payloads for debugging using dynamic message reflection.
Prerequisites¶
Generate a descriptor set from your proto files:
Usage¶
Options¶
| Option | Description |
|---|---|
-d, --descriptor-set <FILE> |
Descriptor set file (.pb or .binpb) |
-p, --payload <DATA> |
Payload as hex, base64, or file path |
-m, --message-type <NAME> |
Message type (e.g., users.v1.User) |
-f, --input-format <FMT> |
Input format: hex, base64, file, auto (default) |
-o, --output-format <FMT> |
Output format: json, json-pretty, text, debug |
--list-types |
List all message types in descriptor set |
--show-field-numbers |
Show field numbers in text output |
Examples¶
# Decode hex payload
quill explain \
--descriptor-set api.pb \
--message-type users.v1.User \
--payload 0a05416c696365
# Decode base64 (auto-detected)
quill explain -d api.pb -m users.v1.User -p CgVBbGljZQ==
# Read from binary file
quill explain \
--descriptor-set api.pb \
--message-type users.v1.User \
--payload response.bin \
--input-format file
# List available types
quill explain --descriptor-set api.pb --list-types
# Text output with field numbers
quill explain -d api.pb -m users.v1.User -p 0a05416c696365 \
--output-format text --show-field-numbers
Generating Descriptor Sets¶
# Single file
protoc --descriptor_set_out=api.pb --include_imports api.proto
# Multiple files
protoc --descriptor_set_out=all.pb --include_imports \
-I./proto \
./proto/**/*.proto
# With buf
buf build -o api.pb
Output Formats¶
JSON (default):
JSON Pretty:
Text (with --show-field-numbers):
List Types Output¶
Available message types:
users.v1
- User
- CreateUserRequest
- CreateUserResponse
Services:
users.v1.UserService
- GetUser (GetUserRequest -> User)
- CreateUser (CreateUserRequest -> CreateUserResponse)
Exit Codes¶
| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Invalid input (bad arguments, malformed request) |
| 3 | Network/protocol error (connection failed, timeout) |
| 4 | Server error (non-2xx response) |
Example Error Handling¶
quill call http://localhost:8080/service/method --in '{}'
status=$?
case $status in
0) echo "Success" ;;
2) echo "Invalid input" ;;
3) echo "Network error" ;;
4) echo "Server error" ;;
esac
Environment Variables¶
| Variable | Description |
|---|---|
QUILL_URL |
Default base URL |
QUILL_TOKEN |
Default bearer token |
QUILL_TIMEOUT |
Default timeout (seconds) |
QUILL_PRISM |
Default transport profile |
QUILL_PROTO_PATH |
Default proto include paths |
Example¶
export QUILL_URL=http://localhost:8080
export QUILL_TOKEN=my-api-token
export QUILL_TIMEOUT=30
# Now just use method path
quill call /users.v1.UserService/GetUser --in '{"user_id": "123"}'
Shell Completion¶
Generate shell completions:
# Bash
quill completions bash > /etc/bash_completion.d/quill
# Zsh
quill completions zsh > ~/.zfunc/_quill
# Fish
quill completions fish > ~/.config/fish/completions/quill.fish
Next Steps¶
- Quick Start - Get started with Quill
- Configuration - Configuration reference
- Server Guide - Server development