The most impactful contribution you can make is adding a new provider recipe. Each recipe is a self-contained JSON file that guides users through setting up API credentials for a service.
Provider recipes live in providers/<id>.json. Here's the minimal structure:
{
"schema_version": "1",
"id": "my-service",
"display_name": "My Service API",
"description": "Set up API access for My Service.",
"category": ["category"],
"website": "https://my-service.dev",
"auth_types": ["api_key"],
"estimated_time": "5 minutes",
"prerequisites": [
"A My Service account"
],
"outputs": [
{
"key": "MY_SERVICE_API_KEY",
"description": "API key for My Service",
"sensitive": true
}
],
"steps": [
...
]
}| Field | Required | Description |
|---|---|---|
schema_version |
Yes | Always "1" |
id |
Yes | Lowercase, hyphenated identifier (matches filename) |
display_name |
Yes | Human-readable name shown to users |
description |
Yes | One-line description of what the recipe sets up |
category |
Yes | Array of category tags (e.g. ["ai", "llm"]) |
website |
Yes | URL to the service's developer portal |
auth_types |
Yes | Array: "api_key", "oauth2", "bearer_token" |
estimated_time |
Yes | Human-readable time estimate |
prerequisites |
Yes | Array of things the user needs before starting |
outputs |
Yes | Array of credential objects the recipe collects |
steps |
Yes | Array of step objects (see below) |
{
"key": "ENV_VAR_NAME",
"description": "What this credential is",
"sensitive": true
}Set sensitive: true for secrets (API keys, tokens). These are masked in terminal output.
Every step must have a unique id (string) and a type. Most steps also have a message field that supports {{VARIABLE}} template syntax.
Display an informational message.
{ "id": "intro", "type": "info", "message": "We'll set up your API key." }Open a URL in the user's browser.
{
"id": "open_console",
"type": "open_url",
"url": "https://console.example.com",
"message": "Opening the developer console."
}Prompt the user for text input with optional validation.
{
"id": "collect_key",
"type": "prompt_input",
"message": "Paste your API key:",
"output_key": "MY_SERVICE_API_KEY",
"validation": "^sk-[a-zA-Z0-9]{32,}$",
"validation_error": "That doesn't look like a valid API key."
}| Field | Required | Description |
|---|---|---|
output_key |
Yes | Variable name to store the input |
validation |
No | Regex pattern the input must match |
validation_error |
No | Custom error shown on validation failure |
Ask for yes/no confirmation. If the user says no, the session pauses for later resumption.
{
"id": "confirm_billing",
"type": "prompt_confirm",
"message": "Have you set up billing on your account?"
}Present a multiple-choice menu. Choices can set variables or jump to different steps.
{
"id": "pick_mode",
"type": "prompt_choice",
"message": "Which keys do you need?",
"choices": [
{ "label": "Test keys", "sets": { "mode": "test" } },
{ "label": "Live keys", "sets": { "mode": "live" }, "next": "live_warning" }
]
}| Choice field | Required | Description |
|---|---|---|
label |
Yes | Text shown for this option |
sets |
No | Variables to set when selected |
next |
No | Step ID to jump to after selection |
Validate credentials via HTTP request.
{
"id": "validate_key",
"type": "validate",
"method": "http_get",
"depends_on": ["collect_key"],
"message": "Checking your API key...",
"on_success": "API key verified!",
"on_failure": "Couldn't verify the key. Check it and try again.",
"config": {
"url": "https://api.example.com/v1/me",
"header_name": "Authorization",
"header_value": "Bearer {{MY_SERVICE_API_KEY}}"
}
}Write collected credentials to a file.
{ "id": "write_output", "type": "output", "message": "Saving your credentials." }Pause the recipe so the user can complete an external action and resume later.
{
"id": "wait_for_approval",
"type": "wait",
"message": "Your application is being reviewed.",
"resume_hint": "Run 'getapi resume' once approved."
}URLs and messages support {{VARIABLE}} templates that are substituted at runtime from previously collected values.
Execute a shell command.
{
"id": "install_cli",
"type": "run_command",
"command": "npm install -g @example/cli",
"message": "Installing the CLI tool."
}Copy a value to the system clipboard.
{
"id": "copy_token",
"type": "copy_to_clipboard",
"value": "{{MY_TOKEN}}",
"message": "Token copied to clipboard."
}# Run your recipe from a file
cargo run -- --recipe providers/my-service.json
# Validate JSON syntax
python3 -m json.tool providers/my-service.json > /dev/null
# Run the full test suite
cargo test- One provider per PR -- keeps reviews focused
- Test the full flow yourself before submitting
- Use existing recipes as reference (see
providers/github.jsonfor a simple example,providers/twitter.jsonfor a complex one) - Keep step messages concise -- users read these in a terminal
- Add validation for
prompt_inputsteps whenever the credential has a known format - Include a
validatestep if the service has a lightweight endpoint to test credentials against