orchid-cli
Command-line interface for interacting with Orchid without running the API.
orchid-cli runs the full Orchid framework in-process from the terminal — no server, no Docker, no external database required. It imports orchid-ai directly and mirrors the lifecycle of orchid-api, giving you the same agents, tools, RAG, and persistence accessible from a shell script or interactive REPL. The default storage is SQLite (~/.orchid/chats.db); swap in PostgreSQL via orchid-storage-postgres when you need it.
The CLI bundles the orchid-rag-chroma plugin as a dependency for zero-infrastructure RAG — vectors live on disk at ~/.orchid/chroma/, no Qdrant container required. Set VECTOR_BACKEND=qdrant and install orchid-rag-qdrant to switch when you need sparse/hybrid search or scope promotion.
Installation
pip install orchid-ai orchid-cli
# orchid-rag-chroma is included — no extra install needed for on-disk RAG
After installation the `orchid` command is available in your shell.
## Quick start
```bash
# Validate a config before deploying
orchid config validate examples/basketball/orchid.yml
# Start an interactive chat session
orchid chat interactive --config examples/basketball/orchid.yml
# Send a single message and get the response
orchid chat send <chat_id> "Who scored the most points last season?" \
--config examples/basketball/orchid.ymlCommand tree
orchid auth — OAuth 2.0 authentication
| Command | Purpose |
|---|---|
orchid auth login --config <path> | Opens the browser for OAuth 2.0 + PKCE login; exchanges the code and stores tokens at ~/.orchid/tokens.json |
orchid auth status --config <path> | Shows current token state, expiry, tenant, and user |
orchid auth logout --config <path> | Clears stored tokens |
Authentication is required when MCP servers or tools need a real Bearer token. When auth.dev_bypass: true is set in the config a dev fallback token is used automatically.
orchid chat — Full CRUD and messaging
| Command | Purpose |
|---|---|
orchid chat create --config <path> | Create a new chat session |
orchid chat list --config <path> | List all chat sessions |
orchid chat history <id> --config <path> | Show message history |
orchid chat send <id> "msg" --config <path> | Send a single message and stream the response |
orchid chat interactive --config <path> | Interactive REPL with slash commands (/switch, /new, /share) |
orchid chat rename <id> "title" --config <path> | Rename a chat |
orchid chat share <id> --config <path> | Promote chat RAG data to user scope |
orchid chat delete <id> --config <path> | Delete a chat session |
orchid config — Validation
| Command | Purpose |
|---|---|
orchid config validate <agents.yaml> | Validates the agent config against the Pydantic schema; exits non-zero on any error |
Use this in CI pipelines to catch schema errors before deployment.
orchid index — RAG ingestion
| Command | Purpose |
|---|---|
orchid index file <path> -n <ns> --config <path> | Index a single file |
orchid index dir <path> -n <ns> --config <path> | Index all files in a directory |
orchid index text "..." -n <ns> --config <path> | Index inline text |
orchid index json-file <path> -n <ns> --config <path> | Bulk-index from a JSON entries file |
orchid generate-flower — Project scaffolding wizard
Interactive wizard that guides you through creating a complete Orchid project skeleton — orchid.yml, agents.yaml, and Python scaffold files — packaged as a zip or written directly to a directory.
| Command | Purpose |
|---|---|
orchid generate-flower | Start the interactive wizard |
orchid generate-flower --no-zip --output ./my-project | Write directly to a directory |
orchid generate-flower --ai --ai-model openai/gpt-4o | Enable AI-assisted question answering |
orchid generate-flower --from-seed answers.json | Reproduce from a seed file |
orchid generate-flower --verbose | Show all questions including defaults |
The wizard walks through nine phases: project identity, infrastructure (LLM, auth, vector backend, storage), supervisor configuration, agent definitions (repeatable loop), global tools, cross-agent skills, guardrails, events (Pollen + Bloom), and MCP gateway customization. Before generating, a review phase validates all answers against the Pydantic schema and lets you edit any value.
Generated projects include valid orchid.yml and agents.yaml, Python scaffold files for custom agents/tools/identity/hooks/storage, __init__.py files for proper packaging, and a basic test suite. All code follows project SOLID conventions.
orchid mcp — MCP server OAuth
| Command | Purpose |
|---|---|
orchid mcp status --config <path> | Show OAuth auth status for all configured MCP servers |
orchid mcp revoke <server> --config <path> | Revoke the stored token for a specific server |
orchid external-agents — External CLI delegation
Delegates sub-tasks from an Orchid agent to third-party AI CLIs (like Copilot,
Gemini CLI, or any local assistant binary) installed on the operator's machine.
The Orchid agent's LLM emits a tool_call, the CLI runs as a subprocess with
the delegated prompt, and the captured output flows back into the agentic loop
as a ToolMessage — exactly like any built-in or MCP tool.
Declared in agents.yaml via the external_agents: top-level block:
external_agents:
ask_assistant:
command: ["my-cli-tool"] # argv list — never shell-interpolated
args: ["--non-interactive"] # extra fixed flags
timeout: 600 # seconds (default 600, 10 minutes)
description: "Delegate to an external AI assistant."
requires_approval: true # HITL gate (default: true)
stdin_mode: arg # "arg" (append to argv) or "stdin" (pipe)
normalizer: passthrough # "passthrough" | "llm"
normalizer_instruction: "" # system prompt when normalizer: llmAgents reference external-agent tools by name in their tools: list:
agents:
orchestrator:
tools:
- ask_assistantConfiguration reference:
| Field | Type | Default | Description |
|---|---|---|---|
command | list[str] | (required) | Executable path and base flags |
args | list[str] | [] | Extra fixed arguments merged with command |
timeout | float | 600.0 | Seconds before the process is killed |
description | str | "" | Tool description shown to the LLM and in external-agents list |
requires_approval | bool | true | Pause for operator confirmation before every delegation |
cwd | str | "" | Working directory (empty = inherit orchid-cli CWD) |
env | dict | {} | Extra env vars merged over os.environ |
stdin_mode | "arg"|"stdin" | "arg" | How the prompt reaches the subprocess |
normalizer | str | "passthrough" | Prompt reformulation: "passthrough" or "llm" |
normalizer_instruction | str | "" | System instruction for normalizer: llm |
parallel_safe | bool | false | Declare the tool safe for parallel dispatch |
inject_to_rag | bool | false | Store subprocess output in RAG for future retrieval |
rag_ttl | int|null | null | TTL override for injected chunks |
Security model:
- Approval gate —
requires_approval: true(default) triggers the existing HITLinterrupt(). The operator must confirm every delegation in the terminal before the subprocess runs. - No shell — the command runs via
asyncio.create_subprocess_execwith an argv list. Nevershell=True. The executable, flags, working directory, and timeout come from trusted operator YAML — onlypromptis LLM-controlled. - Timeout kill — runaway processes are killed after the configured timeout.
The tool result is
{"error": "timeout", "timeout_s": …}. - Per-tool allowlisting — each external CLI must be explicitly declared in
YAML. An agent only sees tools listed in its
tools:array.
Listing configured tools: orchid external-agents list <agents.yaml>
renders a Rich table with the command, timeout, approval status, and whether
the binary is resolvable on PATH (✓/✗).
Tips: Use stdin_mode: stdin for CLIs that read prompts from standard
input. Increase timeout for long-running delegations. When the external CLI
requires authentication, either bake it into env: or use a wrapper
script.
Example session
$ orchid chat interactive --config examples/basketball/orchid.yml
Orchid — interactive mode
Type /help for available commands, /exit to quit.
You: Who has the most career points in NBA history?
[basketball] LeBron James surpassed Kareem Abdul-Jabbar in February 2023...
You: How does that compare to the top three?
[basketball] Here is a comparison of the top three all-time scorers:
1. LeBron James — 40,000+ points (active)
2. Kareem Abdul-Jabbar — 38,387
3. Karl Malone — 36,928
You: /exit
Goodbye.How the CLI mirrors the API lifespan
orchid-cli/orchid_cli/bootstrap.py performs the same startup sequence as orchid-api/orchid_api/main.py:
- Load
OrchidAgentsConfigfrom the config path. - Call
build_graph()to wire the LangGraph supervisor and agent nodes. - Initialise
OrchidChatStorage(SQLite by default). - Warm MCP capability caches for all
auth.mode: noneservers.
Every chat, index, and mcp command goes through commands/_session.py:resolve_session(), which bootstraps the framework, resolves auth, and warms passthrough/oauth MCP caches once per (tenant_key, user_id). The result is an Orchid facade and an OrchidAuthContext — the same objects the API hands to its routers.
The CLI is an independent OAuth 2.0 client: it runs a full Authorization Code + PKCE flow against the upstream IdP, stores tokens in ~/.orchid/tokens.json (permissions 0o600), and refreshes them automatically when they expire. It never delegates auth to orchid-api.
CLI-specific RAG configuration
When orchid.yml includes a cli_rag: section, the CLI uses it instead of rag:. This lets you run Docker-based examples locally without Qdrant:
rag:
vector_backend: qdrant # used by orchid-api (Docker)
qdrant_url: http://qdrant:6333
embedding_model: gemini/gemini-embedding-001
cli_rag:
vector_backend: chroma # used by orchid-cli (local, on-disk)
embedding_model: ollama/nomic-embed-textWhen cli_rag: is absent, the CLI falls back to rag: as usual. The cli_rag: section supports the same keys as rag:: vector_backend, qdrant_url, embedding_model, openai_api_key, and gemini_api_key.
Precedence: CLI args > env vars > cli_rag: (if present) > rag: > CLI defaults (chroma).