Skip to main content

Add your description here

Project description

crow-cli

crow-cli is an Agent Client Protocol (ACP) native agent implementation that serves as the core execution engine for the Crow agent framework.

Installation

# Ensure you're in the correct project directory
git clone https://github.com/crow-cli/crow-cli.git
uv venv
# Install dependencies using uv
uv --project /path/to/crow/crow-cli sync

Or run directly

uvx crow-cli --help

if you like having it available globally, you can install it using pip

uv tool install crow-cli --python 3.14

Quick Start

uvx crow-cli init

Run Programmatically

import asyncio
from crow_acp.agent import AcpAgent, agent_run

async def main():
    await agent_run()

if __name__ == "__main__":
    asyncio.run(main())

Configuration

Features

1. ACP Protocol Native

  • Implements all ACP agent endpoints (initialize, new_session, load_session, prompt, cancel)
  • Full streaming support for token-by-token responses
  • Session persistence to SQLite database

2. MCP Tool Integration

  • Automatically discovers tools from connected MCP servers
  • Supports both MCP and ACP-native tool execution
  • Tool execution with progress updates

3. Streaming ReAct Loop

  • Real-time streaming of thinking tokens (for reasoning models)
  • Content token streaming
  • Tool call progress updates (pending → in_progress → completed/failed)

4. Cancellation Support

  • Immediate task cancellation via async events
  • Persists partial state on cancellation
  • Safe resource cleanup on cancel

5. ACP Terminal Support

When the ACP client supports terminals (clientCapabilities.terminal: true):

  • Uses ACP-native terminals instead of MCP terminal calls
  • Better terminal display in the client
  • Live output streaming
  • Proper terminal lifecycle management

Built-in Tools

The agent automatically discovers and registers tools from connected MCP servers:

  • crow-mcp_terminal - Execute shell commands in the workspace
  • crow-mcp_write - Write content to files
  • crow-mcp_read - Read files with line numbers
  • crow-mcp_edit - Fuzzy string replacement in files
  • crow-mcp_web_search - Search the web using a search engine
  • crow-mcp_web_fetch - Fetch URL content as markdown

Session Management

Creating a New Session

# When connecting via ACP, a new session is created automatically
# with the working directory and MCP servers provided by the client

Loading an Existing Session

# Sessions persist to the database and can be loaded by ID
# The load_session endpoint handles this automatically

Session Data Storage

Sessions are stored in SQLite with three main tables:

  • Prompt - System prompt templates (Jinja2)
  • Session - Session metadata (config, tools, model, cwd)
  • Event - Conversation turns (messages, tool calls, results)

Usage with ACP Clients

crow-cli is designed to work with any ACP-compatible client:

// In Zed
{
  "agent_servers": {
      "crow-cli": {
        "type": "custom",
        "command": "uvx",
        "args": ["crow-cli", "acp"],
      },
...
}

ACP Client Capabilities

The agent automatically detects and uses client capabilities:

Capability When Enabled Behavior
terminal Client supports ACP terminals Uses ACP-native terminals
fs.write_text_file Client supports file writing Uses ACP file write
fs.read_text_file Client supports file reading Uses ACP file read

Project Structure

crow-cli/
├── src/crow_cli/
│   ├── __init__.py
│   ├── agent/
│   │   ├── __init__.py
│   │   ├── compact.py        # Conversation compaction
│   │   ├── configure.py      # Agent configuration
│   │   ├── context.py        # Context providers (directory tree, file fetching)
│   │   ├── db.py             # SQLAlchemy database models
│   │   ├── llm.py            # LLM client configuration
│   │   ├── logger.py         # Logging utilities
│   │   ├── main.py           # Agent entry point
│   │   ├── mcp_client.py     # MCP client creation + tool extraction
│   │   ├── prompt.py         # Prompt building
│   │   ├── react.py          # ReAct loop implementation
│   │   ├── session.py        # Session management + persistence
│   │   ├── skills.py         # Skills handling
│   │   ├── tools.py          # Tool definitions
│   │   └── prompts/          # Jinja2 system prompt templates
│   │       ├── system_prompt.jinja2
│   │       ├── self_documentation.jinja2
│   │       ├── skill_knowledge_info.jinja2
│   │       └── system_message_suffix.jinja2
│   ├── cli/
│   │   ├── __init__.py
│   │   ├── init_cmd.py       # `crow init` command
│   │   └── main.py           # CLI entry point
│   └── client/
│       ├── __init__.py
│       └── main.py           # Programmatic client
├── config/
│   ├── compose.yaml          # Docker compose for services
│   ├── config.yaml           # Default configuration
│   ├── .env.example          # Environment variables template
│   ├── searxng/
│   │   └── settings.yml      # SearXNG search config
│   └── prompts/              # Override prompts (user customization)
│       ├── system_prompt.jinja2
│       ├── self_documentation.jinja2
│       ├── skill_knowledge_info.jinja2
│       └── system_message_suffix.jinja2
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── test_agent_init.py
│   └── unit/
│       └── test_session.py
├── examples/
│   ├── mc_escher_loop.py
│   └── quick_test.py
├── pyproject.toml
├── README.md
├── TODO.md
└── run_tests.sh

Development

Running Tests

# From the project root
uv run --project /home/thomas/src/nid pytest crow-cli/tests/

Building

# Build the package
uv build --project /home/thomas/src/nid/crow-cli

# Install locally
pip install --force-reinstall ./crow-cli/dist/*.whl

ReAct Loop Logic

┌─────────────────────────────────────────────────────────────────────────┐
│                           REACT LOOP (Turn N)                           │
└─────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
                    ┌───────────────────────────────┐
                    │   cancel_event.is_set()?      │
                    └───────────────────────────────┘
                          │                  │
                         YES                 NO
                          │                  │
                          ▼                  ▼
                    ┌──────────┐    ┌────────────────────────┐
                    │  RETURN  │    │  send_request(LLM)     │
                    └──────────┘    └────────────────────────┘
                                            │
                                            ▼
                              ┌──────────────────────────────┐
                              │  process_response() stream   │
                              │  ┌────────────────────────┐  │
                              │  │ Yield: thinking/token  │  │
                              │  │ Yield: content/token   │  │
                              │  │ Yield: tool_args/token │  │
                              │  └────────────────────────┘  │
                              │           │                  │
                              │           ▼                  │
                              │    Collect in              │
                              │    state_accumulator       │
                              └──────────────────────────────┘
                                            │
                                            ▼
                              ┌──────────────────────────────┐
                              │  Cancelled during stream?    │
                              └──────────────────────────────┘
                          ┌────────┴────────┐
                         YES                NO
                          │                  │
                          ▼                  ▼
                    ┌──────────────┐  ┌────────────────────────┐
                    │ Add partial  │  │ Yield: final           │
                    │ response     │  │ (thinking, content,    │
                    │ + results    │  │  tool_call_inputs)     │
                    │ Raise        │  └────────────────────────┘
                    │ CancelledErr │                │
                    └──────────────┘                ▼
                          │                  ┌────────────────────────┐
                          │                  │ Log pre-tool usage     │
                          ▼                  └────────────────────────┘
                    ┌──────────┐                         │
                    │  RETURN  │                 ┌────────────────────────┐
                    └──────────┘                 │ tokens > threshold?    │
                          │                      └────────────────────────┘
┌──────────────────────────────┐                           │              │
│  Turn Loop: for turn in      │                          YES             NO
│    range(max_turns):         │                           │              │
└──────────────────────────────┘                           ▼              ▼
                          │                      ┌──────────────┐  ┌──────────┐
                          ▼                      │  COMPACT     │  │  SKIP  │
              ┌──────────────────────────┐      │  session()   │  │ COMPACT│
              │  process_response DONE   │      └──────────────┘  └──────────┘
              │  Extract: thinking       │           │                │
              │         content          │           └────────┬───────┘
              │         tool_call_inputs │                    │
              │         usage            │                    ▼
              └──────────────────────────┘         ┌────────────────────────┐
                          │                         │  Has tools to call?  │
                          ▼                         └────────────────────────┘
              ┌──────────────────────────┐                           │
              │  Cancelled after stream? │                      ┌────┴────┐
              └──────────────────────────┘                     YES      NO
                          │                                       │          │
                         YES                                      ▼          ▼
                          │                              ┌──────────────┐  ┌──────────────┐
                          ▼                              │  EXECUTE     │  │  NO TOOLS    │
                    ┌──────────────┐                     │  TOOLS       │  │  (final msg) │
                    │ Add partial  │                     └──────────────┘  └──────────────┘
                    │ response     │                            │              │
                    │ + tool       │                            │              │
                    │ results      │                            ▼              ▼
                    │ RETURN       │                    ┌──────────────┐  ┌──────────────┐
                    └──────────────┘                    │ Add tools    │  │ Add assistant│
                                                        │ to results   │  │ response     │
                                                        └──────────────┘  └──────────────┘
                                                        │              │              │
                                                        ▼              ▼              ▼
                              ┌──────────────────────────────────────────────────┐
                              │  Cancelled after tool execution?               │
                              └──────────────────────────────────────────────────┘
                                          │
                                 ┌────────┴────────┐
                                YES                NO
                                 │                  │
                                 ▼                  ▼
                        ┌──────────────┐  ┌────────────────────────┐
                        │ Add partial  │  │ Add assistant response │
                        │ response +   │  │ + tool results         │
                        │ tool results │  └────────────────────────┘
                        │ RETURN       │              │
                        └──────────────┘              │
                                                    │
                                                    ▼
                                        ┌────────────────────────┐
                                        │  Turn N complete       │
                                        │  ───────────────────── │
                                        │  Loop back to turn N+1 │
                                        │  (or max_turns reached)│
                                        └────────────────────────┘

Troubleshooting

Connection Issues

If the agent can't connect to MCP servers:

  1. Verify MCP server config in ~/.crow/mcp.json
  2. Check that the MCP server path is correct
  3. Ensure the server is executable

Session Loading Failures

If sessions fail to load:

  1. Check database exists: ls ~/.crow/crow.db
  2. Verify database permissions: chmod 644 ~/.crow/crow.db
  3. Check session ID exists in database

Terminal Not Working

If ACP terminals aren't working:

  1. Check client capabilities: clientCapabilities.terminal should be true
  2. Verify MCP terminal fallback is configured
  3. Check terminal command is valid in the workspace directory

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crow_cli-0.1.6.tar.gz (125.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

crow_cli-0.1.6-py3-none-any.whl (47.6 kB view details)

Uploaded Python 3

File details

Details for the file crow_cli-0.1.6.tar.gz.

File metadata

  • Download URL: crow_cli-0.1.6.tar.gz
  • Upload date:
  • Size: 125.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for crow_cli-0.1.6.tar.gz
Algorithm Hash digest
SHA256 79ce9bd5f6e79522e5b9a4982e21c81b84a8522678b4b516f2b6be8b9a6ea25b
MD5 da1c3ec74660fb2ee87b19a8701a2be6
BLAKE2b-256 1edc0adc7964128f11d4d11dbc65c9f33f1519a1252a0245a5f28ae91169106b

See more details on using hashes here.

File details

Details for the file crow_cli-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: crow_cli-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 47.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for crow_cli-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 bccf13726dc1e24627c0392c9e5dc4589af201a635e7b979ce15bc267e4ee094
MD5 ca504ff67365308244b17dafe118daa6
BLAKE2b-256 63fa4c8d842615a2ea0e98ad89f5ef3eb7f6b14d100da56588c19fac4d475d01

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page