dw

The Doubleword Batch Inference CLI. Upload JSONL files, run batches, stream results, and send real-time inference requests — all from the terminal.

Features

  • Batch processing — upload files, create batches, watch progress, download results
  • Streamingdw stream goes from JSONL file to piped results in one command
  • Real-time inference — one-shot streaming requests via dw realtime
  • Local file tools — validate, prepare, stats, sample, merge, split, and diff JSONL files without uploading
  • Project scaffoldingdw project init creates ready-to-run project templates
  • Multi-account — manage multiple accounts and organizations, switch between them like kubectl contexts
  • Output formats — table for interactive use, JSON for scripts, auto-detected from TTY
  • Shell completions — bash, zsh, and fish
  • Self-updatedw update downloads the latest release

Quick Example

# Authenticate
dw login

# See available models
dw models list

# Run a batch and stream results (prints "Batch: <id>" to stderr)
dw stream batch.jsonl > results.jsonl

# One-shot inference
dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 "Explain batch inference"

# Check what the batch cost (use the batch ID from dw stream output)
dw batches analytics <batch-id>

Installation

curl -fsSL https://raw.githubusercontent.com/doublewordai/dw/main/install.sh | sh

This downloads the latest release binary for your platform and installs it to ~/.local/bin/. The script detects your OS (Linux, macOS) and architecture (x86_64, arm64) automatically.

From Source

git clone https://github.com/doublewordai/dw.git
cd dw
cargo build --release
cp target/release/dw ~/.local/bin/

Requires Rust 2024 edition (1.85+).

Verify

dw --version

Shell Completions

Generate shell completions for your shell:

# Bash
dw completions bash > ~/.local/share/bash-completion/completions/dw

# Zsh
dw completions zsh > ~/.zfunc/_dw

# Fish
dw completions fish > ~/.config/fish/completions/dw.fish

Updating

dw update

This downloads the latest release from GitHub, verifies the checksum, and replaces the binary in place.

Authentication

dw login

Opens your browser to the Doubleword SSO page. After authenticating, the CLI receives API keys for both the inference and admin APIs. Credentials are stored in ~/.dw/credentials.toml with 0600 permissions.

Logging into an Organization

dw login --org my-org

When you log in with --org, the CLI creates credentials scoped to that organization. Batches, files, and usage are billed to the org.

Custom Account Name

dw login --as work

By default the account is named after your email or org. Use --as to set a custom name.

API Key Login (headless)

For SSH sessions, containers, and CI:

dw login --api-key <YOUR_INFERENCE_KEY>

API key login stores only the inference key. Commands that use the admin API will not be available, including dw whoami, dw usage, dw requests, dw keys, and dw webhooks. For full functionality, use browser login (with port forwarding for remote sessions).

Credentials Storage

Credentials are stored in ~/.dw/credentials.toml:

~/.dw/
├── config.toml        # Active account, server URLs
└── credentials.toml   # API keys (0600 permissions)

Logging Out

# Log out of the active account
dw logout

# Log out of a specific account
dw logout work

# Log out of all accounts
dw logout --all

Checking Your Identity

dw whoami

Shows the authenticated user and active organization (if any).

Quickstart

This guide walks through a complete batch workflow: prepare a file, submit it, and get results.

1. Log In

dw login

2. See Available Models

dw models list

3. Create a Batch File

A batch file is JSONL where each line is an API request:

{"custom_id": "q1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8", "messages": [{"role": "user", "content": "What is batch inference?"}], "max_tokens": 256}}
{"custom_id": "q2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8", "messages": [{"role": "user", "content": "Explain transformers in 2 sentences."}], "max_tokens": 256}}

Save this as batch.jsonl.

4. Validate and Inspect

dw files validate batch.jsonl
dw files stats batch.jsonl

5. Submit and Stream Results

The fastest path from file to results:

dw stream batch.jsonl > results.jsonl

This uploads the file, creates a batch, watches progress, and pipes results to stdout as they complete.

6. Check Cost

For a single input file, dw stream prints Batch: <id> to stderr when the batch is created. When streaming a directory of multiple JSONL files, batch IDs are printed after streaming completes. Use a printed batch ID to see the cost breakdown:

dw batches analytics <batch-id>

Alternative: Step-by-Step

If you prefer manual control over each step:

# Upload
dw files upload batch.jsonl

# Create batch from the uploaded file
dw batches create --file <file-id>

# Watch progress
dw batches watch <batch-id>

# Download results
dw batches results <batch-id> -o results.jsonl

Real-Time Inference

For one-off requests without a batch file:

dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 "What is batch inference?"

Next Steps

Batch Processing

Batch processing lets you submit thousands of API requests in a single JSONL file and process them asynchronously at reduced cost.

Creating a Batch

One-Step: dw batches run

Upload a file and create a batch in one command:

dw batches run batch.jsonl

With progress watching:

dw batches run batch.jsonl --watch

Override the model for all requests:

dw batches run batch.jsonl --model Qwen/Qwen3-VL-235B-A22B-Instruct-FP8 --watch

Process an entire directory of JSONL files:

dw batches run output/ --watch

Step-by-Step

# Upload the file
dw files upload batch.jsonl

# Create a batch from the uploaded file
dw batches create --file file-abc123

# Optionally set a 1-hour completion window (default: 24h)
dw batches create --file file-abc123 --completion-window 1h

# Add metadata
dw batches create --file file-abc123 --metadata project=evals --metadata run=1

Monitoring

Watch Progress

Watch one batch:

dw batches watch batch-abc123

Watch multiple batches with parallel progress bars:

dw batches watch batch-abc123 batch-def456 batch-ghi789

Check Status

dw batches get batch-abc123

List Batches

# Recent batches
dw batches list

# Active batches first
dw batches list --active-first

# All batches (auto-paginate)
dw batches list --all

Results

Download Results

dw batches results batch-abc123 -o results.jsonl

Without -o, results are printed to stdout.

Batch Analytics

dw batches analytics batch-abc123

Shows token usage, latency breakdown, and cost for a completed batch.

Cancellation and Retry

Cancel a Batch

dw batches cancel batch-abc123

Prompts for confirmation. Use --yes to skip:

dw batches cancel batch-abc123 --yes

Retry Failed Requests

dw batches retry batch-abc123

Creates a new batch containing only the failed requests from the original batch.

Completion Windows

The completion window determines the SLA for batch processing:

WindowDescription
24hDefault. Standard batch pricing.
1hPriority processing. Results in ~1 hour.
dw batches run batch.jsonl --completion-window 1h

Cost Estimates

Before submitting, check the estimated cost:

dw files upload batch.jsonl
dw files cost-estimate <file-id>
dw files cost-estimate <file-id> --completion-window 1h

Saving Batch IDs

When running multiple files, save batch IDs for later reference:

dw batches run output/ --output-id batch-ids.txt

This writes one batch ID per line to the specified file.

Streaming Results

dw stream is the fastest path from a JSONL file to results. It uploads the file, creates a batch, watches progress, and streams results to stdout as they complete.

Basic Usage

dw stream batch.jsonl > results.jsonl

Progress is printed to stderr, results to stdout. This means you can pipe results while still seeing progress.

Streaming a Directory

When given a directory, dw stream processes all .jsonl files in it:

dw stream output/ > results.jsonl

Each file becomes a separate batch. Progress bars for all batches are shown in parallel.

Model Override

Set the model for all requests without modifying the file:

dw stream batch.jsonl --model Qwen/Qwen3-VL-235B-A22B-Instruct-FP8 > results.jsonl

Completion Window

dw stream batch.jsonl --completion-window 1h > results.jsonl

How It Works

  1. If --model is specified, the file is transformed to a temp file with the model set
  2. The file is uploaded via POST /v1/files
  3. A batch is created from the uploaded file
  4. The CLI polls the batch status, showing a progress bar
  5. As results become available, they're fetched via the file content endpoint and written to stdout
  6. Polling continues until the batch completes

Results are streamed incrementally — you don't have to wait for the entire batch to finish before seeing output.

When to Use Stream vs Batches Run

Use CaseCommand
Quick one-off, pipe to filedw stream batch.jsonl > results.jsonl
Fire and forget, check laterdw batches run batch.jsonl
Multiple files, watch progressdw batches run output/ --watch
CI pipeline, save batch IDdw batches run batch.jsonl --output-id batch.txt

dw stream is a convenience wrapper. For more control (metadata, retries, ID tracking), use dw batches run and dw batches results separately.

Real-Time Inference

dw realtime sends a single inference request and streams the response. Useful for quick tests, prototyping prompts, and interactive use.

Basic Usage

dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 "Explain batch inference in one paragraph"

The response streams token-by-token to stdout.

System Message

dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 "Summarize this text" \
  --system "You are a concise technical writer."

Reading from Stdin

When no prompt is given, dw realtime reads from stdin:

echo "What is 2+2?" | dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8
cat document.txt | dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 --system "Summarize this"

Options

FlagDescription
--system <MSG>Set the system message
--max-tokens <N>Maximum tokens to generate
--temperature <T>Sampling temperature (0.0-2.0)
--no-streamWait for full response instead of streaming
-o, --output-file <FILE>Write response to a file
--usagePrint token usage summary after completion

Non-Streaming Mode

dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 "Hello" --no-stream

Waits for the complete response before printing. Useful when you need the full text at once (e.g., for piping to jq).

Token Usage

dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 "Hello" --usage

Prints input/output token counts to stderr after the response completes.

Output to File

dw realtime Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 "Write a poem" -o poem.txt

JSONL Format

Doubleword uses the OpenAI-compatible batch JSONL format. Each line is a JSON object representing one API request.

Chat Completions

{
  "custom_id": "request-001",
  "method": "POST",
  "url": "/v1/chat/completions",
  "body": {
    "model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "What is batch inference?"}
    ],
    "max_tokens": 512,
    "temperature": 0
  }
}

Embeddings

{
  "custom_id": "emb-001",
  "method": "POST",
  "url": "/v1/embeddings",
  "body": {
    "model": "Qwen/Qwen3-Embedding-8B",
    "input": "The quick brown fox"
  }
}

Vision (Multimodal)

{
  "custom_id": "img-001",
  "method": "POST",
  "url": "/v1/chat/completions",
  "body": {
    "model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "text", "text": "Describe this image."},
          {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,/9j/4AA..."}}
        ]
      }
    ]
  }
}

Required Fields

FieldDescription
custom_idUnique identifier for the request. Used to match results.
methodHTTP method. Always "POST".
urlAPI endpoint. /v1/chat/completions or /v1/embeddings.
bodyThe request body, matching the OpenAI API format.

Model Field

The model field in the body can be:

  • Set in the JSONL file directly
  • Omitted and set later with dw files prepare --model <name>
  • Overridden at upload/run time with --model

The recommended pattern for reusable batch files is to omit the model and set it with dw files prepare:

dw files prepare batch.jsonl --model Qwen/Qwen3-VL-30B-A3B-Instruct-FP8

Result Format

Results are also JSONL, one line per completed request:

{
  "id": "req-abc123",
  "custom_id": "request-001",
  "response_body": {
    "id": "chatcmpl-xyz",
    "object": "chat.completion",
    "model": "Qwen/Qwen3-VL-30B-A3B-Instruct-FP8",
    "choices": [
      {
        "index": 0,
        "message": {"role": "assistant", "content": "Batch inference is..."},
        "finish_reason": "stop"
      }
    ],
    "usage": {
      "prompt_tokens": 42,
      "completion_tokens": 128,
      "total_tokens": 170
    }
  }
}

Match results to requests using the custom_id field.

Local File Operations

The CLI includes local JSONL tools that run without uploading or authenticating. These are useful for preparing, inspecting, and manipulating batch files before submission.

Validate

Check a JSONL file for format errors:

dw files validate batch.jsonl

Validates that each line is valid JSON with the required fields (custom_id, method, url, body).

Stats

Show statistics for a JSONL file:

dw files stats batch.jsonl

Output includes line count, models used, and estimated token counts.

Prepare

Transform a JSONL file in place (or to a new file):

# Set the model on every line
dw files prepare batch.jsonl --model Qwen/Qwen3-VL-30B-A3B-Instruct-FP8

# Set model and temperature
dw files prepare batch.jsonl --model Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 --temperature 0

# Write to a new file instead of modifying in place
dw files prepare batch.jsonl --model Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 -o batch-30b.jsonl

# Prepare all files in a directory
dw files prepare output/ --model Qwen/Qwen3-VL-30B-A3B-Instruct-FP8

Setting Arbitrary Fields

Use --set for any field in the request body:

dw files prepare batch.jsonl --set body.stream=false --set body.top_p=0.9

Encoding Images

Convert local image paths and URLs to base64 data URIs:

dw files prepare batch.jsonl --encode-images

Adding and Removing Lines

# Append a new request line
dw files prepare batch.jsonl --add-line '{"custom_id":"extra","method":"POST","url":"/v1/chat/completions","body":{"messages":[{"role":"user","content":"test"}]}}'

# Remove lines matching a pattern
dw files prepare batch.jsonl --remove-lines "test-*"

Sample

Extract a random sample from a JSONL file:

dw files sample batch.jsonl -n 10 -o sample.jsonl

Uses reservoir sampling for bounded memory on large files.

Merge

Combine multiple JSONL files into one:

dw files merge file1.jsonl file2.jsonl file3.jsonl -o merged.jsonl

Split

Split a JSONL file into chunks:

dw files split large.jsonl --chunk-size 1000

Creates large_001.jsonl, large_002.jsonl, etc. in the same directory. Use -o for a different output directory:

dw files split large.jsonl --chunk-size 1000 -o chunks/

Diff

Compare two JSONL result files by custom_id:

dw files diff results-30b.jsonl results-235b.jsonl

Shows which custom_ids are present in one file but not the other, and a content hash comparison for matching IDs.

Project System

The project system lets you define multi-step workflows in a dw.toml manifest file and run them with dw project commands.

Creating a Project

From a Template

dw project init my-project

Interactive prompts let you choose a template:

TemplateDescription
single-batchPrepare, submit, and analyze a single batch
pipelineMulti-stage pipeline (prepare -> run stages -> analyze)
shellShell-script steps instead of Python
minimalJust a dw.toml with no scaffolding

Or specify directly:

dw project init my-project --template pipeline

From an Example

dw examples clone model-evals
cd model-evals

Manually

Create a dw.toml in your project directory.

The dw.toml Manifest

[project]
name = "my-project"
setup = "uv sync"
workflow = [
    "dw project setup",
    "dw project run prepare -- -n 100",
    "dw files stats batches/batch.jsonl",
    "dw files prepare batches/batch.jsonl --model Qwen/Qwen3-VL-30B-A3B-Instruct-FP8",
    "dw batches run batches/batch.jsonl --watch --output-id .batch-id",
    "dw batches results $(cat .batch-id) -o results.jsonl",
    "dw project run analyze -- -r results.jsonl",
    "dw batches analytics $(cat .batch-id)",
]

[steps.prepare]
description = "Download dataset and generate batch JSONL"
run = "uv run my-project prepare"

[steps.analyze]
description = "Score results against ground truth"
run = "uv run my-project score"

Fields

FieldDescription
project.nameProject name
project.setupCommand to run on dw project setup (e.g., uv sync)
project.workflowOrdered list of commands for dw project run-all and dw project info
steps.<name>.runShell command to execute for this step
steps.<name>.descriptionHuman-readable description shown in dw project info

Running Steps

Setup

Install dependencies:

dw project setup

Runs the project.setup command from dw.toml.

Individual Steps

dw project run prepare

Pass extra arguments after --:

dw project run prepare -- -n 100 --output custom.jsonl

Full Workflow

Run all workflow steps sequentially:

dw project run-all

This executes every command in the workflow array, skipping dw project setup (run it separately first).

Resume After Failure

If a step fails, fix the issue and continue from where you left off:

dw project run-all --continue

Or start from a specific step:

dw project run-all --from 3

Inspecting State

Project Info

dw project info

Shows available steps, descriptions, and the full workflow.

Run Status

dw project status

Shows the current run state: which steps have completed, which failed, and where the run left off.

Cleanup

dw project clean

Removes batches/, results/, and the run state file (.dw-run.json).

Workflow Comments

Lines in the workflow starting with # are comments. They are displayed in dw project info but skipped during dw project run-all and excluded from step numbering for --from:

workflow = [
    "dw project setup",
    "# Download the dataset from: https://example.com/data",
    "dw project run prepare",
]

Examples

Doubleword provides a set of real-world use-case examples that demonstrate different batch inference patterns.

Listing Examples

dw examples list

Cloning an Example

dw examples clone model-evals
cd model-evals
dw project setup
dw project info

Each example includes a dw.toml manifest, Python code, and a README with full instructions.

Available Examples

Model Evals

Evaluate LLM accuracy at batch pricing. Runs the full GSM8K test set and scores model answers against ground truth.

dw examples clone model-evals

Embeddings

Batch embeddings for semantic search. Downloads Wikipedia abstracts, generates embeddings, and builds a searchable HNSW index.

dw examples clone embeddings

Synthetic Data Generation

Generate training data at scale. Three-stage pipeline: scenario generation, conversation generation, and quality filtering.

dw examples clone synthetic-data-generation

Data Processing Pipelines

Clean and enrich company records. Normalize names, deduplicate, and classify industries using real SEC EDGAR data.

dw examples clone data-processing-pipelines

Image Summarization

Vision-language batch inference. Fetches images from Unsplash, encodes them, and generates social media-style summaries.

dw examples clone image-summarization

Structured Extraction

Extract fields from scanned documents. Receipt data extraction with ensemble voting on the SROIE dataset.

dw examples clone structured-extraction

Bug Detection Ensemble

Classify security vulnerabilities. CWE classification on the CVEfixes dataset with calibration via running twice.

dw examples clone bug-detection-ensemble

Dataset Compilation

Compile exhaustive datasets with LLM + search. Recursive query expansion, web search, extraction, and filtering.

dw examples clone dataset-compilation

Async Agents

Deep research with recursive multi-agent orchestration. A root agent spawns sub-agents that independently search the web and synthesize findings.

dw examples clone async-agents

Running an Example

Every example follows the same pattern:

dw examples clone <name>
cd <name>
dw project setup       # Install dependencies
dw project info        # See the workflow
dw project run-all     # Run everything

Or run steps individually — see dw project info for the full workflow.

Command Reference

Full reference for all dw commands. Run dw <command> --help for details on any command.

Auth

CommandDescription
dw loginAuthenticate via browser or API key
dw login --api-key <KEY>Headless authentication
dw login --org <ORG>Login within an organization
dw login --as <NAME>Set a custom account name
dw logoutRemove active account credentials
dw logout --allRemove all stored credentials
dw whoamiShow authenticated user

Accounts

CommandDescription
dw account listList all stored accounts
dw account currentShow the active account
dw account switch <NAME>Switch the active account
dw account rename <OLD> <NEW>Rename an account
dw account remove <NAME>Remove a stored account

Models

CommandDescription
dw models listList available models
dw models list --type chatFilter by type (chat, embeddings, reranker)
dw models get <MODEL>Get model details

Files

Remote (requires auth)

CommandDescription
dw files upload <PATH>Upload a JSONL file
dw files listList uploaded files
dw files list --allList all files (auto-paginate)
dw files list --purpose allInclude output and error files
dw files get <ID>Get file metadata
dw files delete <ID>Delete a file
dw files content <ID>Download file content
dw files cost-estimate <ID>Get processing cost estimate

Local (no auth needed)

CommandDescription
dw files validate <PATH>Validate JSONL format
dw files prepare <PATH>Transform JSONL (model, params, images)
dw files stats <PATH>Show line count, models, token estimates
dw files sample <PATH> -n <N>Random sample from JSONL
dw files merge <FILES...>Merge multiple JSONL files
dw files split <PATH>Split JSONL into chunks
dw files diff <A> <B>Compare two result files

Batches

CommandDescription
dw batches run <PATH>Upload + create batch (one step)
dw batches run <PATH> --watchUpload + create + watch progress
dw batches create --file <ID>Create batch from uploaded file
dw batches listList batches
dw batches get <ID>Get batch details
dw batches cancel <ID>Cancel a running batch
dw batches retry <ID>Retry failed requests
dw batches results <ID>Download results
dw batches watch <IDS...>Watch batch progress
dw batches analytics <ID>Show batch analytics

Stream

CommandDescription
dw stream <PATH>Upload, batch, watch, and pipe results

Realtime

CommandDescription
dw realtime <MODEL> <PROMPT>One-shot streaming inference

Usage & Requests

CommandDescription
dw usageShow usage summary (tokens, cost, requests)
dw usage --since 2026-03-01Usage from a specific date
dw usage --since 2026-03-01 --until 2026-03-31Usage for a date range
dw requestsList recent requests

Keys

CommandDescription
dw keys create --name <NAME>Create an API key
dw keys listList API keys (secrets masked)
dw keys delete <ID>Delete an API key

Webhooks

CommandDescription
dw webhooks create --url <URL>Create a webhook
dw webhooks listList webhooks
dw webhooks delete <ID>Delete a webhook
dw webhooks rotate-secret <ID>Rotate signing secret

Projects

CommandDescription
dw project init [NAME]Create a new project from template
dw project setupRun project setup command
dw project run <STEP>Run a named step
dw project run-allRun full workflow
dw project run-all --continueResume from last completed step
dw project statusShow run progress
dw project cleanRemove artifacts
dw project infoShow steps and workflow

Examples

CommandDescription
dw examples listList available examples
dw examples clone <NAME>Clone an example project

Config

CommandDescription
dw config showShow current configuration
dw config set-url <URL>Set both API URLs
dw config set-ai-url <URL>Set inference API URL
dw config set-admin-url <URL>Set admin API URL
dw config reset-urlsReset URLs to defaults

Other

CommandDescription
dw updateSelf-update to latest release
dw completions <SHELL>Generate shell completions

Accounts & Configuration

The CLI supports multiple accounts (personal and org contexts), similar to kubectl contexts.

Accounts

Multiple Accounts

Each dw login creates a new account. You can log in to multiple accounts and switch between them:

# Login to personal account
dw login

# Login to an org
dw login --org my-company --as company

# Login to a self-hosted deployment
dw login --as work --server https://dw.internal.example.com

Switching Accounts

dw account list
dw account switch company

Using a Specific Account for One Command

dw batches list --account company

The --account flag overrides the active account for a single command.

Managing Accounts

# Rename
dw account rename old-name new-name

# Remove
dw account remove old-account

# Show active
dw account current

Configuration

Configuration is stored in ~/.dw/config.toml:

active_account = "you@example.com"

[client]
timeout_secs = 300
connect_timeout_secs = 10
max_retries = 1
poll_interval_secs = 2

Server URLs

For self-hosted or custom deployments:

# Point both APIs to one server
dw config set-url https://dw.example.com

# Or set individually
dw config set-ai-url https://api.example.com
dw config set-admin-url https://app.example.com

# Reset to defaults
dw config reset-urls

Client Settings

Configure in ~/.dw/config.toml under the [client] section:

SettingDefaultDescription
timeout_secs300HTTP request timeout in seconds
connect_timeout_secs10TCP connect timeout in seconds
max_retries1Max retries on transient errors (0–10)
poll_interval_secs2Seconds between polls for watch and stream (min: 1)

All fields are optional. Omit individual fields or the entire [client] section to use defaults.

Viewing Configuration

dw config show

Shows active account, default output format, and server URLs.

Output Formats

The CLI auto-detects the best output format:

ContextFormatDescription
Interactive terminaltableHuman-readable tables
Piped to another commandjsonOne JSON object per line

Override with the --output flag:

dw batches list --output json
dw models list --output plain

Available formats: table, json, plain.

API Keys & Webhooks

API Keys

Create and manage API keys for programmatic access.

Create a Key

dw keys create --name "ci-pipeline"
dw keys create --name "my-agent" --description "Used by the research agent"

The key secret is shown once at creation time. Store it securely.

List Keys

dw keys list

Secrets are masked in the output. Only metadata (name, ID, creation date) is shown.

Delete a Key

dw keys delete <key-id>
dw keys delete <key-id> --yes  # Skip confirmation

Webhooks

Webhooks notify your endpoints when batch events occur.

Create a Webhook

dw webhooks create --url https://example.com/webhook

With specific events:

dw webhooks create --url https://example.com/webhook --events "batch.completed,batch.failed"

With a description:

dw webhooks create --url https://example.com/webhook --description "Notify Slack on batch completion"

The webhook signing secret is shown once at creation time. Use it to verify webhook payloads.

List Webhooks

dw webhooks list

Delete a Webhook

dw webhooks delete <webhook-id>
dw webhooks delete <webhook-id> --yes  # Skip confirmation

Rotate Signing Secret

dw webhooks rotate-secret <webhook-id>

Generates a new signing secret. The old secret stops working immediately.

Usage & Analytics

Usage Summary

dw usage

Shows total tokens, requests, and cost broken down by model.

Date Filtering

# Usage since a specific date
dw usage --since 2026-03-01

# Usage for a date range
dw usage --since 2026-03-01 --until 2026-03-31

Dates can be YYYY-MM-DD (date-only) or full RFC 3339 timestamps (2026-03-01T00:00:00Z). Date-only values are treated as midnight UTC.

Recent Requests

dw requests

Lists recent requests with model, status, latency, and token counts.

Note: dw requests requires the RequestViewer role and a platform key (browser login). It is not available with dw login --api-key.

Filtering

dw requests --model Qwen/Qwen3-VL-30B-A3B-Instruct-FP8 --since 2026-03-27

Batch Analytics

For per-batch analytics:

dw batches analytics <batch-id>

Shows token usage (prompt, completion, total), average latency, average TTFB, and cost for a completed batch.

Global Flags

These flags are available on every dw command.

FlagDescription
--output <FORMAT>Output format: table, json, or plain. Auto-detected from TTY by default.
--account <NAME>Use a specific account instead of the active one.
--server <URL>Override both inference and admin API URLs.
--server-ai <URL>Override the inference API URL (default: https://api.doubleword.ai).
--server-admin <URL>Override the admin API URL (default: https://app.doubleword.ai).
--helpShow help for any command.
--versionShow the CLI version.

Output Format

The CLI auto-detects the output format based on whether stdout is a TTY:

  • TTY (interactive terminal): table — human-readable tables with headers and alignment
  • Pipe or redirect: json — JSON output suitable for jq processing (NDJSON for lists, pretty-printed for single items)

Override with --output:

# Force JSON in terminal
dw batches list --output json

# Force table when piping (not common, but possible)
dw batches list --output table | less

# Plain text (tab-separated, no headers)
dw batches list --output plain

Server Overrides

Useful for self-hosted or custom deployments:

# Both APIs on the same server
dw batches list --server https://dw.example.com

# Different URLs for inference and admin
dw stream batch.jsonl --server-ai https://api.example.com --server-admin https://app.example.com

For persistent server overrides, use dw config set-url instead. See Accounts & Configuration.

Account Override

Run a command as a different account without switching:

dw batches list --account my-org
dw models list --account company