CLI Reference

Every clq command, with real example output.

clq init

clq init [project-name]

Scaffolds a new MCP server project. If you omit the project name, CLQ prompts you for one interactively. The name must be lowercase alphanumeric with hyphens (^[a-z0-9][a-z0-9-]*$) — this is validated before any files are written.

CLQ writes the project into a new subdirectory of your current directory and refuses to write outside it — path traversal attempts (e.g. ../../escape) are rejected at the name-validation step before any filesystem access.

$ clq init weather-server
Scaffolded weather-server
 
Next steps:
cd weather-server
pnpm install && pnpm build
clq inspect

What gets created

weather-server/
src/
index.ts ← createServer + tool registration
tools/
example-tool.ts ← starter tool with real description
clq.config.ts ← env var declarations
tsconfig.json
package.json ← @clq-sh/core pinned to current version
.gitignore
.env.example

The generated template builds and runs without any edits. The starter tool file has a real, non-empty description so it satisfies CLQ's mandatory-description check immediately — the project compiles before you've written a word.

Flags

FlagEffect
--forceOverwrite an existing non-empty directory. Without this flag, CLQ exits non-zero if the target directory already exists and is not empty.

clq add

clq add <tool-name>

Adds a new tool file to the current project's src/tools/ directory. The tool name follows the same slug rules as the project name. CLQ walks up from your current directory looking for clq.config.ts as the project marker — you can run this from any subdirectory inside a project. The walk is bounded to 10 levels, so a stray invocation outside a project fails fast with a clear error instead of scanning the disk.

$ clq add search-repos
Created src/tools/search-repos.ts

Generated file

import { defineTool } from "@clq-sh/core"
import { z } from "zod"

export const searchRepos = defineTool({
  name: "search_repos",
  description: "TODO: describe what search-repos does and when an agent should call it.",
  input: z.object({
    query: z.string().describe("Search query"),
  }),
  handler: async ({ input, ctx }) => {
    // TODO: implement
    return {}
  },
})

The description placeholder is intentionally a real sentence, not a comment — it satisfies CLQ's mandatory-description check so the project builds immediately. Replace it before shipping.

clq dev

clq dev

Starts a hot-reload dev server. CLQ delegates file watching to tsx watch, which handles TypeScript-aware watching and incremental re-execution. When a source file changes, the server restarts automatically.

$ clq dev
Watching src/ — MCP server running
Waiting for file changes… (Ctrl+C to stop)
 
[change detected]
Restarting…
Ready

Shutdown behavior: On Ctrl+C, CLQ sends a signal to the tsx child process and waits for it to exit before the parent process exits. This is deliberate — a dev CLI that exits immediately on Ctrl+C leaves the watcher (and the server it spawned) running as orphaned processes that hold ports and file locks. CLQ waits for the full process tree to exit before returning.

MCP client connection during dev: clq dev runs your server on stdio, the same transport Claude Desktop uses. You can connect Claude Desktop to a clq dev instance for live development, but you'll need to reconnect after each restart.

clq inspect

clq inspect

Launches a local web inspector: a browser UI where you can call your tools, inspect responses, and review the last 200 call log entries. The inspector uses a two-process design — the inspector server spawns your project's src/index.ts as a child process, communicates with it over stdio, and proxies tool calls through.

$ clq inspect
Inspector running
 
Open this URL in your browser:
http://127.0.0.1:7317/?token=a3f8…
 
This token will not be printed again. Keep this URL private.
(Ctrl+C to stop)

Security model

The inspector binds exclusively to 127.0.0.1 — never 0.0.0.0. Every request is gated by two independent checks in order: the Origin header is validated first (a mismatched Origin returns 403 before the server reveals anything about the token), then the x-clq-token header is checked (a missing or wrong token returns 401). A browser tab on a malicious page cannot forge the Origin header and is blocked outright.

All responses — tool lists, call results, and log entries — are passed through redactSecrets() before leaving the server. Any response field whose key name contains a known secret pattern (token, password, api_key, authorization, bearer, jwt, private_key, and 9 more) is replaced with "[REDACTED]" regardless of where the data came from.

Do not reload the browser tab. The token is read from the URL on load and immediately stripped from the address bar (so it doesn't appear in browser history or referrers). A page reload sends no token and receives a 401 with no recovery path. If this happens, close the tab and re-open the original URL from your terminal.

Tool list is static per session. The inspector reads your tool definitions once at startup. Adding a new tool to src/index.ts while the inspector is running requires a full clq inspect restart to appear.

Port behavior

CLQ defaults to port 7317. If that port is busy, it retries the next 5 incrementing ports (7318–7322) before failing with a clear error.

clq doctor

clq doctor

Runs three independent health checks on the current project and exits non-zero if any fail:

  1. Config validation — loads clq.config.ts in a short-lived tsx subprocess, checks all declared env vars are present and the correct type. The config subprocess reports only { ok, message, fix } — the actual env var values never cross back to the CLI process.
  2. Dependency check — confirms node_modules is installed.
  3. Secret scan — scans source files for hardcoded secrets using hand-rolled regex patterns. Reports the file, line number, and a masked preview of the match (first 3 + last 2 characters; short values are fully starred). The real matched value is never stored, returned, or logged — the masking happens at the innermost scope and the raw value is immediately unreferenced.
$ clq doctor
 
Checking project configuration…
Config valid — GITHUB_TOKEN set, PORT=3000
 
Checking dependencies…
node_modules present
 
Scanning for hardcoded secrets…
No secrets detected
 
All checks passed
$ GITHUB_TOKEN="" clq doctor
 
Checking project configuration…
Config check failed: Required environment variable 'GITHUB_TOKEN' is not set.
GitHub personal access token
Fix: Set GITHUB_TOKEN in your .env file or environment before starting the server.
 
1 check failed

No network calls. Every check is local: filesystem reads for the secret scan and dependency check, and an in-process config validation via a local tsx subprocess. There is no telemetry, no "phone home" step, no remote secret-verification service. A security tool that scans for credentials must never be the thing that exfiltrates them.