Overview

Firestone-generated CLIs provide intuitive commands for all CRUD operations. This guide shows you how to use each command type with practical examples.

Command Mapping

OperationHTTP MethodResource PathCLI Command
ListGET/taskstasks list
CreatePOST/taskstasks create
GetGET/tasks/{id}tasks get ID
UpdatePUT/PATCH/tasks/{id}tasks update ID
DeleteDELETE/tasks/{id}tasks delete ID

List Operation

List all resources in a collection.

Basic Usage

python cli.py tasks list

With Pagination

# Get first 10 items
python cli.py tasks list --limit 10

# Get next 10 items (offset 10)
python cli.py tasks list --limit 10 --offset 10

# Get items 20-30
python cli.py tasks list --limit 10 --offset 20

With Filtering

If your resource defines query parameters:

# tasks.yaml
schema:
  query_params:
    - name: status
      schema:
        type: string
        enum: [active, completed]
    - name: assignee
      schema:
        type: string

Use them in the CLI:

# Filter by status
python cli.py tasks list --status active

# Filter by assignee
python cli.py tasks list --assignee alice

# Combine filters
python cli.py tasks list --status active --assignee alice --limit 20

Output

JSON array:

[
  {
    "task_id": "abc123",
    "title": "Review PR",
    "completed": false
  },
  {
    "task_id": "def456",
    "title": "Write docs",
    "completed": true
  }
]

Processing Output

Count items:

python cli.py tasks list | jq '. | length'

Extract specific field:

python cli.py tasks list | jq '.[].title'

Filter output:

python cli.py tasks list | jq '.[] | select(.completed == true)'

Create Operation

Create a new resource in the collection.

Basic Usage

python cli.py tasks create --title "New task" --completed false

Required vs Optional Fields

Based on your schema:

schema:
  items:
    properties:
      title:
        type: string
      description:
        type: string
      completed:
        type: boolean
    required:
      - title  # Required

Generated CLI:

# Required field
--title TEXT  [required]

# Optional fields
--description TEXT
--completed/--no-completed

Usage:

# Minimal (only required fields)
python cli.py tasks create --title "Urgent task"

# With optional fields
python cli.py tasks create \
  --title "Complete project" \
  --description "Finish by Friday" \
  --completed false

Boolean Fields

# Set to true
python cli.py tasks create --title "Task" --completed

# Set to false
python cli.py tasks create --title "Task" --no-completed

# Omit (uses default or null)
python cli.py tasks create --title "Task"

Array Fields

properties:
  tags:
    type: array
    items:
      type: string
python cli.py tasks create \
  --title "Tagged task" \
  --tags "urgent,backend,api"

Object Fields

properties:
  metadata:
    type: object

JSON string:

python cli.py tasks create \
  --title "Task" \
  --metadata '{"priority": "high", "team": "backend"}'

YAML file:

# metadata.yaml
priority: high
team: backend
labels:
  - urgent
  - api
python cli.py tasks create \
  --title "Task" \
  --metadata metadata.yaml

JSON file:

python cli.py tasks create \
  --title "Task" \
  --metadata metadata.json

Enum Fields

properties:
  priority:
    type: string
    enum: [low, medium, high]
# Valid
python cli.py tasks create --title "Task" --priority high

# Invalid - shows error
python cli.py tasks create --title "Task" --priority critical
# Error: Invalid value for '--priority': invalid choice: critical. (choose from low, medium, high)

Output

Created resource as JSON:

{
  "task_id": "xyz789",
  "title": "New task",
  "completed": false,
  "created_at": "2025-01-15T10:30:00Z"
}

Capture ID

# Extract task_id
TASK_ID=$(python cli.py tasks create --title "Task" | jq -r '.task_id')
echo "Created task: $TASK_ID"

Get Operation

Retrieve a specific resource by ID.

Basic Usage

python cli.py tasks get abc123

With Query Parameters

If instance operations support query params:

schema:
  query_params:
    - name: include_metadata
      schema:
        type: boolean
python cli.py tasks get abc123 --include-metadata

Output

Single resource as JSON:

{
  "task_id": "abc123",
  "title": "Review PR",
  "description": "Review the authentication PR",
  "completed": false,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T14:20:00Z"
}

Processing

Check if exists:

if python cli.py tasks get abc123 &>/dev/null; then
  echo "Task exists"
else
  echo "Task not found"
fi

Extract field:

python cli.py tasks get abc123 | jq -r '.title'

Update Operation

Update an existing resource.

Basic Usage

python cli.py tasks update abc123 --completed true

Partial Updates

Update operations typically allow partial updates:

# Update just the title
python cli.py tasks update abc123 --title "Updated title"

# Update just completed status
python cli.py tasks update abc123 --completed true

# Update multiple fields
python cli.py tasks update abc123 \
  --title "New title" \
  --description "New description" \
  --completed true

Unsetting Fields

Boolean fields:

# Set to false
python cli.py tasks update abc123 --no-completed

Other fields:

# Most APIs don't support unsetting via CLI
# You may need to set to null/empty via JSON:
python cli.py tasks update abc123 --description '""'

Array Updates

# Replace entire array
python cli.py tasks update abc123 --tags "new,tags,list"

Object Updates

# Replace entire object
python cli.py tasks update abc123 --metadata '{"priority": "low"}'

Output

Updated resource:

{
  "task_id": "abc123",
  "title": "Updated title",
  "completed": true,
  "updated_at": "2025-01-15T16:45:00Z"
}

Delete Operation

Delete a resource.

Basic Usage

python cli.py tasks delete abc123

Output

Varies by API:

No content:

None

Deleted resource:

{
  "task_id": "abc123",
  "deleted": true
}

Confirmation message:

{
  "message": "Task abc123 deleted successfully"
}

Check Success

if python cli.py tasks delete abc123 &>/dev/null; then
  echo "Deleted successfully"
else
  echo "Delete failed"
  exit 1
fi

Complete Workflows

Create, Update, Delete

#!/bin/bash

# Create
TASK=$(python cli.py tasks create --title "Deploy to production")
TASK_ID=$(echo $TASK | jq -r '.task_id')
echo "Created task: $TASK_ID"

# Get
python cli.py tasks get $TASK_ID | jq .

# Update
python cli.py tasks update $TASK_ID --completed true

# Verify update
python cli.py tasks get $TASK_ID | jq '.completed'

# Delete
python cli.py tasks delete $TASK_ID
echo "Task deleted"

Bulk Operations

Create multiple:

for title in "Task 1" "Task 2" "Task 3"; do
  python cli.py tasks create --title "$title"
done

Update all:

python cli.py tasks list | jq -r '.[].task_id' | while read id; do
  python cli.py tasks update $id --completed true
done

Delete completed:

python cli.py tasks list --status completed | jq -r '.[].task_id' | while read id; do
  python cli.py tasks delete $id
done

Migration Script

#!/bin/bash
# Migrate tasks from old API to new API

# Export from old API
OLD_API_URL=https://old-api.example.com
python cli.py --api-url $OLD_API_URL tasks list > tasks.json

# Import to new API
NEW_API_URL=https://new-api.example.com
cat tasks.json | jq -c '.[]' | while read task; do
  TITLE=$(echo $task | jq -r '.title')
  DESC=$(echo $task | jq -r '.description')
  python cli.py --api-url $NEW_API_URL tasks create \
    --title "$TITLE" \
    --description "$DESC"
done

Global Options

All commands support these global options:

API URL

python cli.py --api-url https://api.example.com tasks list

Or via environment variable:

export API_URL=https://api.example.com
python cli.py tasks list

Authentication

API Key:

python cli.py --api-key abc123... tasks create --title "Task"

Or:

export API_KEY=abc123...
python cli.py tasks create --title "Task"

Mutual TLS:

python cli.py \
  --client-cert /path/to/cert.pem \
  --client-key /path/to/key.pem \
  tasks list

Or:

export CLIENT_CERT=/path/to/cert.pem
export CLIENT_KEY=/path/to/key.pem
python cli.py tasks list

Debug Mode

python cli.py --debug tasks create --title "Task"

Shows:

  • API requests/responses
  • Parameter validation
  • Error details

Error Handling

API Errors

python cli.py tasks get nonexistent
# Output: {"error": "Not found"}
# Exit code: 1 (failure)

Validation Errors

python cli.py tasks create --priority invalid
# Error: Invalid value for '--priority': invalid choice: invalid. (choose from low, medium, high)
# Exit code: 2 (usage error)

Network Errors

python cli.py --api-url https://down-api.example.com tasks list
# Output: Connection refused
# Exit code: 1 (failure)

Script Error Handling

#!/bin/bash
set -e  # Exit on any error

# This will exit if creation fails
TASK_ID=$(python cli.py tasks create --title "Task" | jq -r '.task_id')

# Only runs if creation succeeded
python cli.py tasks update $TASK_ID --completed true

Tips and Best Practices

Use jq for JSON Processing

# Install jq
sudo apt-get install jq  # Debian/Ubuntu
brew install jq          # macOS

# Pretty print
python cli.py tasks list | jq .

# Extract field
python cli.py tasks get abc123 | jq -r '.title'

# Filter
python cli.py tasks list | jq '.[] | select(.completed == true)'

Environment Variables

Create .env file:

# .env
API_URL=https://api.example.com
API_KEY=your-api-key-here

Load before running:

source .env
python cli.py tasks list

Or use direnv:

# Install direnv
brew install direnv

# Create .envrc
echo 'export API_URL=https://api.example.com' > .envrc
direnv allow

# Now API_URL is always set in this directory
python cli.py tasks list

Aliases

# Add to ~/.bashrc or ~/.zshrc
alias tasks='python /path/to/cli.py --api-url https://api.example.com tasks'

# Usage
tasks list
tasks create --title "Quick task"
tasks get abc123

Output Formatting

Table format:

python cli.py tasks list | jq -r '["ID","TITLE","DONE"], (.[] | [.task_id, .title, .completed]) | @tsv' | column -t

CSV format:

python cli.py tasks list | jq -r '["task_id","title","completed"], (.[] | [.task_id, .title, .completed]) | @csv'

Next Steps