CLI Guide

The DevSpeak CLI wraps the public API for terminal workflows. It currently targets POST /api/v1/translate for full document generation and POST /api/v1/refine for iterative revisions. The old devspeak optimize command is still available, but only as a deprecated alias to devspeak translate.

Installation

``bash

npm install -g @devspeak/cli

`

`bash

npx @devspeak/cli translate "We need a login page that works with Google and saves user data"

`

> Version note. This guide documents 1.5.0. Features marked (1.5.0+)logout,

> whoami, update, doctor, the passive update notice, and the global --no-color flag —

> are not available on 1.4.0 or earlier. Features marked (1.4.0+) — the completion

> command, the XDG config path, local flag validation, and the www default endpoint — are

> not available on 1.3.0 or earlier. On 1.3.0, config lives at ~/.devspeakrc and the

> default endpoint is the apex https://devspeak.dev. Upgrade with

> npm install -g @devspeak/cli@latest or devspeak update.

Command-to-endpoint mapping

| CLI command | API route | Notes |

| ----------------------------------- | ------------------------ | -------------------------------------------------------------------------------------- |

| devspeak login | GET /api/v1/health | Connectivity check only; stores config locally |

| devspeak logout | None | Removes the stored API key from the local config file |

| devspeak whoami | None | Prints the masked key, key source, endpoint, and config path |

| devspeak translate [input] | POST /api/v1/translate | Primary command. The --file flag attaches local files as context via attachments[] |

| devspeak optimize [input] | POST /api/v1/translate | Deprecated alias; does not call POST /api/v1/optimize |

| devspeak refine | POST /api/v1/refine | Sends previous output, feedback, and optional original input |

| devspeak config show | None | Reads the local config file only |

| devspeak config set | None | Updates the local config file only |

| devspeak update | npm registry | Checks registry.npmjs.org for a newer version; --yes installs it |

| devspeak doctor | GET /api/v1/health | Environment audit: Node, config, key, permissions, health, version |

| devspeak completion | None | Prints a bash, zsh, or fish completion script to stdout |

devspeak translate and the deprecated devspeak optimize alias both serialize the Stage 2 /api/v1/translate body. The CLI does not invoke POST /api/v1/optimize.

If you need Stage 1 lexical optimization, use the web app or call POST /api/v1/optimize directly. The CLI does not expose a command for that endpoint.

Authentication

(1.4.0+) The CLI stores configuration in $XDG_CONFIG_HOME/devspeak/config.json, defaulting to ~/.config/devspeak/config.json with chmod 600. On 1.3.0 the path is ~/.devspeakrc.

A pre-existing ~/.devspeakrc from an earlier version is still read, and is migrated to the new location the first time the config is written. The old file is preserved as ~/.devspeakrc.migrated.

`json

{

"apiKey": "dsk_live_a1b2c3d4...",

"endpoint": "https://www.devspeak.dev",

"defaults": {

"audience": "Senior Dev",

"context": "Backend",

"format": "Technical Spec",

"tone": 75

}

}

`

Supported key prefixes:

| Prefix | Meaning |

| ----------- | ----------------------------- |

| dsk_live_ | Production API key |

| dsk_test_ | Development / staging API key |

| dsk_sess_ | Ephemeral session key |

devspeak login

`bash

devspeak login

`

`bash

devspeak login --key dsk_live_a1b2c3d4... --endpoint https://www.devspeak.dev

`

Behavior:

  • Accepts --key, the DEVSPEAK_API_KEY environment variable, or prompts interactively.
  • Fails fast when stdin is not a TTY and no key was supplied, instead of blocking on the prompt.
  • Rejects keys that do not start with dsk_.
  • Verifies connectivity by calling GET /api/v1/health.
  • Validates the endpoint is an absolute http(s) URL and trims a trailing slash.
  • Successful login prints (on stderr, so stdout stays pipeable):

    `text

    Authenticated successfully.

    Config saved to /Users/you/.config/devspeak/config.json

    `

    devspeak whoami (1.5.0+)

    Prints the active identity to stdout: masked API key, key source, endpoint, and config path.

    `bash

    devspeak whoami

    `

    `text

    API key: dsk_live_a1b2...c3d4

    Source: config file

    Endpoint: https://www.devspeak.dev

    Config: /Users/you/.config/devspeak/config.json

    `

  • --json emits a machine-readable object (authenticated, apiKey masked, keySource, endpoint, configPath).
  • The DEVSPEAK_API_KEY environment variable takes precedence over the stored key and is reported as environment.
  • When no key is available, whoami prints Not authenticated. with guidance to run devspeak login and exits 1.
  • The full key is never printed — including in --json output.
  • devspeak logout (1.5.0+)

    Removes the stored API key while preserving the endpoint and generation defaults.

    `bash

    devspeak logout

    `

  • Idempotent: with no stored key it reports No API key stored — nothing to remove. and exits 0.
  • When DEVSPEAK_API_KEY is set, the CLI warns that the environment variable still grants access and must be unset manually — it does not pretend to remove what it cannot.
  • Configuration commands

    devspeak config show

    Prints the current configuration and masks the API key.

    `bash

    devspeak config show

    `

    Example output:

    `text

    {

    "apiKey": "dsk_live_a1b2...c3d4",

    "endpoint": "https://www.devspeak.dev",

    "defaults": {

    "audience": "Senior Dev",

    "context": "Backend",

    "format": "Technical Spec",

    "tone": 75

    }

    }

    Config path: /Users/you/.config/devspeak/config.json

    `

    The JSON goes to stdout and the config path to stderr, so devspeak config show | jq works.

    devspeak config set

    Supported keys:

  • endpoint
  • audience
  • context
  • format
  • tone
  • `bash

    devspeak config set audience "Tech Lead"

    devspeak config set format "RFC"

    devspeak config set tone 90

    devspeak config set endpoint "https://www.devspeak.dev"

    `

    Values are validated against the same allowed sets the API enforces, so an invalid audience, context, format, tone, or endpoint fails locally and is never persisted.

    Each successful update prints Set = .

    devspeak completion (1.4.0+)

    Prints a completion script for bash, zsh, or fish to stdout.

    `bash

    devspeak completion bash >> ~/.bashrc

    devspeak completion zsh > "${fpath[1]}/_devspeak"

    devspeak completion fish > ~/.config/fish/completions/devspeak.fish

    `

    Maintenance commands

    devspeak update (1.5.0+)

    Checks the npm registry (https://registry.npmjs.org/@devspeak/cli/latest) for a newer version.

    `bash

    devspeak update # report status and print the exact upgrade command

    devspeak update --yes # install via npm install -g @devspeak/cli@

    `

  • Up to date → confirms and exits 0.
  • Outdated → prints npm install -g @devspeak/cli@; with --yes it runs the install itself with a pinned, revalidated version (no shell interpolation, nothing piped from the network).
  • Registry unreachable → a clear offline message and exit 1, never a crash.
  • Passive update notification (1.5.0+)

    At most once every 24 hours, a detached background process refreshes the latest known registry version into $XDG_CONFIG_HOME/devspeak/update-check.json. When that cached version is newer than the running CLI, the next invocation prints one line on stderr:

    `text

    Update available: 1.5.0 → 1.6.0. Run devspeak update.

    `

    The check runs only on a TTY, is skipped when the CI environment variable is set, never blocks or fails a command, and can be disabled entirely:

    `bash

    `

    devspeak doctor (1.5.0+)

    One-shot environment audit. Each check prints / with an actionable fix line on failure.

    `bash

    devspeak doctor

    devspeak doctor --json

    `

    Checks, in order:

    1. Node.js version ≥ 18

    2. Config file parses as JSON

    3. API key present and dsk_-prefixed

    4. Config file permissions are 0600

    5. Endpoint answers GET /api/v1/health

    6. Installed version vs the npm registry latest

    Exits 0 only when every check passes. --json emits { ok, checks: [{ name, ok, detail, fix? }] }.

    Global --no-color (1.5.0+)

    Forces colored output off regardless of TTY detection and FORCE_COLOR. NO_COLOR and automatic non-TTY detection continue to work as before.

    `bash

    devspeak --no-color doctor

    `

    Translation commands

    devspeak translate [input]

    Primary command for full Stage 2 generation via POST /api/v1/translate.

    Options

    | Flag | Meaning | Default |

    | --------------------------- | --------------------------------------------------------------- | ---------------- |

    | -a, --audience | Target audience | Senior Dev |

    | -c, --context | Technical context | Backend |

    | -f, --format | Output format | Technical Spec |

    | -t, --tone | Verbosity 0..100 | 75 |

    | -i, --instructions | Custom instructions | none |

    | --file | Attach a local file as context (PDF, Markdown, TXT — max 10 MB) | none |

    | -o, --output | Write output to file | none |

    | --json | Print the raw data payload as JSON | false |

    Enum values

    | Option | Values |

    | ---------- | ----------------------------------------------------------------------------------------- |

    | audience | Junior Dev, Senior Dev, Tech Lead, SRE, Data Engineer |

    | context | Backend, Frontend, Mobile, Data/ML, DevOps |

    | format | Technical Spec, Jira Tickets, API Design, RFC, Data Model, Prompt, Optimize |

    Examples:

    `bash

    devspeak translate "We need user auth with Google SSO"

    `

    `bash

    cat requirements.txt | devspeak translate --format "Jira Tickets" --output tickets.md

    `

    `bash

    devspeak translate "Add Redis caching for API responses" \

    --audience "SRE" \

    --context "DevOps" \

    --format "RFC" \

    --tone 90 \

    --instructions "Include monitoring and alerting requirements"

    `

    If no positional input is supplied, the CLI reads from stdin. When the command is run interactively without a positional argument or piped input, it exits with a usage hint.

    Output behavior:

  • Without --output, the generated Markdown is written to stdout.
  • Summary metadata (wordCount, latencyMs, model) is written to stderr.
  • With --json, the CLI prints the raw data payload returned by the API, not the full { success, data } envelope.
  • With --output, the CLI writes the file and prints Written to to stderr before the metadata summary.
  • Attaching files as context (--file)

    The --file flag reads a local file, base64-encodes it, and sends it in the attachments field of the POST /api/v1/translate request body. Server-side, text file content is decoded and injected as a context block alongside the workspace context sent to the LLM.

    Supported types: .pdf, .md, .mdx, .txt

    Limit: 10 MB — validated locally before any network call.

    `bash

    Attach a PDF PRD as context

    devspeak translate "Implement the user authentication flow" \

    --file ./docs/product-requirements.pdf \

    --audience "Tech Lead" \

    --format "Technical Spec" \

    --tone 85

    `

    `bash

    Attach a Markdown runbook for an SRE RFC

    devspeak translate "Add Redis caching for API responses" \

    --audience "SRE" \

    --context "DevOps" \

    --format "RFC" \

    --tone 90 \

    --instructions "Include monitoring and alerting requirements" \

    --file ./runbooks/caching-standards.md

    `

    `bash

    Combine stdin input with an attached file

    cat feature-notes.txt | devspeak translate \

    --file ./architecture/current-state.md \

    --format "RFC"

    `

    Error behavior:

  • Nonexistent file → the CLI exits with the full path before making any network request.
  • File larger than 10 MB → the CLI rejects it and reports the actual size.
  • Unsupported extension → the CLI lists the accepted types.
  • The attached filename and size are printed to stderr (they do not pollute stdout).
  • > Note on PDFs: .pdf files are base64-encoded and sent to the model as a document attachment, so their contents are read in full. Text extraction quality depends on the PDF — a scanned image without an embedded text layer yields little usable context.

    devspeak optimize [input]

    Deprecated compatibility alias. It uses the exact same flags and sends the exact same request body to POST /api/v1/translate.

    `bash

    devspeak optimize "We need user auth with Google SSO"

    `

    When used, the CLI prints a deprecation warning on stderr:

    `text

    [DEPRECATED] devspeak optimize is deprecated. Use devspeak translate instead.

    `

    Refinement command

    devspeak refine

    Wraps POST /api/v1/refine.

    Required options

    | Flag | Meaning |

    | ----------------------- | -------------------------------------------------------------------- |

    | -p, --previous | Previous output to refine. Use @path/to/file.md to load from disk. |

    | -F, --feedback | Targeted change request |

    Optional flags

    | Flag | Meaning | Default |

    | ------------------------ | ------------------------------------ | ---------------- |

    | -r, --original | Original input text for context | "" |

    | -a, --audience | Target audience | Senior Dev |

    | -c, --context | Technical context | Backend |

    | -f, --format | Output format | Technical Spec |

    | -t, --tone | Verbosity 0..100 | 75 |

    | -o, --output | Write output to file | none |

    | --json | Print the raw data payload as JSON | false |

    Examples:

    `bash

    devspeak refine \

    --previous @spec.md \

    --feedback "Add a section on rate limiting and explicit error codes" \

    --original "We need a login page that works with Google and saves user data"

    `

    `bash

    devspeak refine \

    --previous "## Technical Specification..." \

    --feedback "Make it more concise" \

    --tone 40 \

    --json

    `

    Refinement output follows the same stdout / stderr conventions as translate.

    When --previous starts with @, the CLI loads the file from disk and exits if the file does not exist.

    Errors and operational notes

    | Message | Meaning |

    | ---------------------------------------------------------------- | ------------------------------------------------------------------------ |

    | No API key configured. Run \devspeak login\ first. | Missing local credentials |

    | Invalid API key format. Keys start with dsk_live_ or dsk_test_ | Key prefix check failed |

    | Cannot reach API at ... | Endpoint connectivity test failed |

    | Provide input text as argument or pipe via stdin | translate was run interactively without positional input or piped data |

    | Input must be at least 10 characters | translate input is below the server minimum |

    | File not found: ... | refine --previous @path pointed to a missing file |

    | Previous output must not be empty | refine --previous resolved to an empty value |

    | Feedback must not be empty | refine --feedback` is missing or empty |

    Security

  • The CLI never logs full API keys.
  • Stored config uses owner-only permissions.
  • Production traffic uses HTTPS.
  • API keys can be revoked from the DevSpeak dashboard at any time.
  • For the underlying REST contracts, see [/docs/api-reference](/docs/api-reference).