crow-cli 0.1.26__tar.gz → 0.1.28__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crow_cli-0.1.28/PKG-INFO +199 -0
- crow_cli-0.1.28/README.md +176 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/crow-cli.spec +0 -2
- {crow_cli-0.1.26 → crow_cli-0.1.28}/pyproject.toml +1 -2
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/configure.py +4 -6
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/context.py +8 -2
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/default/defaults.py +46 -4
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/main.py +16 -46
- crow_cli-0.1.28/src/crow_cli/agent/memory.py +267 -0
- crow_cli-0.1.28/src/crow_cli/agent/session.py +478 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/cli/init_cmd.py +35 -46
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/cli/main.py +89 -60
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/client/main.py +4 -1
- crow_cli-0.1.28/tests/conftest.py +271 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_compact.py +19 -20
- crow_cli-0.1.28/tests/unit/test_session.py +59 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/uv.lock +1 -50
- crow_cli-0.1.26/PKG-INFO +0 -597
- crow_cli-0.1.26/README.md +0 -573
- crow_cli-0.1.26/src/crow_cli/agent/db.py +0 -129
- crow_cli-0.1.26/src/crow_cli/agent/session.py +0 -473
- crow_cli-0.1.26/tests/conftest.py +0 -162
- crow_cli-0.1.26/tests/e2e/test_live_llm_integration.py +0 -355
- crow_cli-0.1.26/tests/unit/test_persistence_integrity.py +0 -893
- crow_cli-0.1.26/tests/unit/test_session.py +0 -297
- {crow_cli-0.1.26 → crow_cli-0.1.28}/.gitignore +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/.python-version +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/agent.json +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/examples/mc_escher_loop.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/examples/quick_test.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/run_tests.sh +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/__init__.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/__init__.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/compact.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/default/__init__.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/default/searxng_settings.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/hooks.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/llm.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/logger.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/mcp_client.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/prompt.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/react.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/slash.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent/tools.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/agent_runner.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/cli/__init__.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/cli/install.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/client/__init__.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/src/crow_cli/client/terminal.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/test_send_request_error_handling.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/__init__.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/analyze_payload_cache_invalidation.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/analyze_payload_deep.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/e2e/test_session_update_transmission.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/integration/test_agent_init.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/integration/test_auth_validation.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_client_terminal.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_compact_last_messages_list_content.json +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_compact_last_messages_list_content.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_json_repair.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_request_logging.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_stream_processing.py +0 -0
- {crow_cli-0.1.26 → crow_cli-0.1.28}/tests/unit/test_uv_project_enforcement.py +0 -0
crow_cli-0.1.28/PKG-INFO
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: crow-cli
|
|
3
|
+
Version: 0.1.28
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Project-URL: Homepage, https://github.com/crow-cli/crow-cli
|
|
6
|
+
Project-URL: Repository, https://github.com/crow-cli/crow-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/crow-cli/crow-cli/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/crow-cli/crow-cli#readme
|
|
9
|
+
Requires-Python: >=3.14
|
|
10
|
+
Requires-Dist: agent-client-protocol>=0.9.0
|
|
11
|
+
Requires-Dist: coolname>=2.2.0
|
|
12
|
+
Requires-Dist: directory-tree>=1.0.0
|
|
13
|
+
Requires-Dist: fastmcp>=2.14.5
|
|
14
|
+
Requires-Dist: httpx>=0.28.1
|
|
15
|
+
Requires-Dist: ipython>=9.10.0
|
|
16
|
+
Requires-Dist: jinja2>=3.1.6
|
|
17
|
+
Requires-Dist: json-schema-to-pydantic>=0.4.9
|
|
18
|
+
Requires-Dist: openai>=2.21.0
|
|
19
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
20
|
+
Requires-Dist: rich>=14.3.3
|
|
21
|
+
Requires-Dist: typer>=0.24.1
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# crow-cli
|
|
25
|
+
|
|
26
|
+
<p>
|
|
27
|
+
<a href="https://pypi.org/project/crow-cli/"><img src="https://img.shields.io/pypi/v/crow-cli" alt="PyPI version"></a>
|
|
28
|
+
<a href="https://pypi.org/project/crow-cli/"><img src="https://img.shields.io/pypi/pyversions/crow-cli" alt="Python versions"></a>
|
|
29
|
+
<a href="#license"><img src="https://img.shields.io/pypi/l/crow-cli" alt="License"></a>
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
[Documentation](https://crow-ai.dev)
|
|
33
|
+
|
|
34
|
+
`crow-cli` is an [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) coding agent that runs in your terminal and inside ACP-compatible editors. It reads and edits code, runs shell commands, searches the web, and remembers your work across sessions.
|
|
35
|
+
|
|
36
|
+
Most agent toolkits treat persistence as an afterthought. crow-cli treats it as the point: every session lives in a dedicated memory service ([crow-memory](#crow-memory--persistence--memory-api)) built on [LanceDB](https://lancedb.github.io/lancedb/) with ColBERT and ColPali embeddings, so agents recall past conversations semantically and can delegate work to one another. Sessions get memorable coolname ids (like `taupe-squirrel-of-splendid-potency`) you can resume or read from any other agent.
|
|
37
|
+
|
|
38
|
+
## Requirements
|
|
39
|
+
|
|
40
|
+
- Python 3.14+, managed with [uv](https://docs.astral.sh/uv/)
|
|
41
|
+
- Docker, for the crow-memory and SearXNG services
|
|
42
|
+
- An API key for an OpenAI-compatible LLM provider (OpenRouter, OpenAI, your own endpoint, …)
|
|
43
|
+
|
|
44
|
+
| Platform | Notes |
|
|
45
|
+
|----------|-------|
|
|
46
|
+
| Linux | glibc 2.35+ (Ubuntu 22.04+, Debian 12+, or equivalent) |
|
|
47
|
+
| macOS | 13+ (Ventura), Intel and Apple Silicon |
|
|
48
|
+
| Windows | 10+ (64-bit); WSL2 recommended |
|
|
49
|
+
|
|
50
|
+
## Setup
|
|
51
|
+
|
|
52
|
+
Install the CLI:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git clone https://github.com/crow-cli/crow-cli.git
|
|
56
|
+
cd crow-cli
|
|
57
|
+
uv tool install crow-cli --python 3.14 # or run without installing: uvx crow-cli --help
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Initialize your configuration and start the backing services:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
crow-cli init # scaffolds ~/.crow (config.yaml, .env, docker-compose)
|
|
64
|
+
cd ~/.crow && docker compose up -d # starts crow-memory + SearXNG
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`crow-cli init` walks you through provider and model selection and writes your secrets to `~/.crow/.env`, referenced from the config as `${VAR}`.
|
|
68
|
+
|
|
69
|
+
## Quick start
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# One-shot prompt — prints the response and exits
|
|
73
|
+
crow-cli run "explain what this repo does"
|
|
74
|
+
|
|
75
|
+
# Continue an existing session by id
|
|
76
|
+
crow-cli run -s <session-id> "now add tests"
|
|
77
|
+
|
|
78
|
+
# Send a long, pre-written prompt from a file or stdin
|
|
79
|
+
crow-cli run -f delegation.md -s <session-id>
|
|
80
|
+
cat prompt.md | crow-cli run -
|
|
81
|
+
|
|
82
|
+
# Interactive REPL
|
|
83
|
+
crow-cli run -i
|
|
84
|
+
|
|
85
|
+
# Run as an ACP agent server (for editors)
|
|
86
|
+
crow-cli acp
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Inspect stored sessions with `crow-cli inspect` (add `--session <id> --messages` to see a session's messages).
|
|
90
|
+
|
|
91
|
+
## Using crow-cli in your editor
|
|
92
|
+
|
|
93
|
+
crow-cli speaks ACP, so it works with any ACP-compatible client. For [Zed](https://zed.dev/), add to `~/.config/zed/settings.json`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"agent_servers": {
|
|
98
|
+
"crow-cli": {
|
|
99
|
+
"type": "custom",
|
|
100
|
+
"command": "crow-cli",
|
|
101
|
+
"args": ["acp"]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The agent detects client capabilities (terminals, file read/write) and uses the native ACP versions when available, falling back to MCP tools otherwise.
|
|
108
|
+
|
|
109
|
+
## What's in the box
|
|
110
|
+
|
|
111
|
+
crow-cli is a monorepo. The pieces:
|
|
112
|
+
|
|
113
|
+
### crow-cli — the agent
|
|
114
|
+
|
|
115
|
+
The ACP-native agent: a streaming ReAct loop with tool calling, cancellation, conversation compaction, and multimodal input. Provider and model configuration lives in `~/.crow/config.yaml`.
|
|
116
|
+
|
|
117
|
+
### crow-memory — persistence + memory API
|
|
118
|
+
|
|
119
|
+
A standalone service — a LanceDB store with ColBERT (text) and ColPali (image) multivector embeddings — that the agent talks to over HTTP. It backs both session persistence and a semantic memory API, exposed to agents as three tools:
|
|
120
|
+
|
|
121
|
+
- `list_sessions()` — sessions ordered by recent activity (who's working on what)
|
|
122
|
+
- `query_memory(query)` — find which session discussed something, across all sessions
|
|
123
|
+
- `query_session(session_id)` — read or search within one session (spans all of that session's agents)
|
|
124
|
+
|
|
125
|
+
This is what makes multi-agent delegation work: launch a worker, then read its thoughts from any other agent. Today crow-memory runs as a Docker container the agent connects to; longer-term it moves toward an always-on daemon, in line with the ACP v2 direction.
|
|
126
|
+
|
|
127
|
+
### crow-mcp — the tool server
|
|
128
|
+
|
|
129
|
+
The built-in [MCP](https://modelcontextprotocol.io/) server providing the agent's tools:
|
|
130
|
+
|
|
131
|
+
| Tool | What it does |
|
|
132
|
+
|------|--------------|
|
|
133
|
+
| `read` / `write` / `edit` | File access — `edit` does precise, fuzzy-matched string replacement |
|
|
134
|
+
| `terminal` | Run shell commands in the workspace |
|
|
135
|
+
| `web_search` / `web_fetch` | Search the web (via SearXNG) and fetch pages as markdown |
|
|
136
|
+
| `capture_webcam` / `read_image_file` | Vision input |
|
|
137
|
+
| `list_sessions` / `query_memory` / `query_session` | Memory (see above) |
|
|
138
|
+
|
|
139
|
+
**Extensible by design:** register any MCP server in `~/.crow/config.yaml` and its tools appear alongside these automatically.
|
|
140
|
+
|
|
141
|
+
> ⚠️ **Tool names are not namespaced.** crow-mcp registers its tools as `read`, `edit`, `terminal`, … — not `crow-mcp_read`. When you add your own MCP servers, watch for name collisions.
|
|
142
|
+
|
|
143
|
+
### SearXNG — web search
|
|
144
|
+
|
|
145
|
+
crow-cli ships a maintained SearXNG configuration (stored as JSON so the agent can drive it over MCP) so web search works out of the box, without hand-editing SearXNG settings.
|
|
146
|
+
|
|
147
|
+
### Skills
|
|
148
|
+
|
|
149
|
+
Agents load reusable skills from `~/.crow/skills/` — each a directory with a `SKILL.md` describing when and how to use it. Skill distribution is still being worked out; today skills are local directories.
|
|
150
|
+
|
|
151
|
+
## Configuration
|
|
152
|
+
|
|
153
|
+
`~/.crow/config.yaml` holds providers, models, and MCP servers; secrets live in `~/.crow/.env` and are interpolated with `${VAR}`.
|
|
154
|
+
|
|
155
|
+
```yaml
|
|
156
|
+
providers:
|
|
157
|
+
openrouter:
|
|
158
|
+
api_key: ${OPENROUTER_API_KEY}
|
|
159
|
+
base_url: https://openrouter.ai/api/v1
|
|
160
|
+
models:
|
|
161
|
+
my-model:
|
|
162
|
+
provider: openrouter
|
|
163
|
+
model: anthropic/claude-sonnet-4
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Development
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
git clone https://github.com/crow-cli/crow-cli.git
|
|
170
|
+
cd crow-cli
|
|
171
|
+
uv sync --project crow-cli
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Run the unit tests — fast and hermetic, no services required (tests that touch sessions use an in-memory fake of the memory service):
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
uv run --project crow-cli pytest crow-cli/tests/unit
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The persistence layer itself is tested in `crow-memory`. Integration and end-to-end tiers are opt-in:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
uv run --project crow-cli pytest crow-cli/tests --run-integration # spawn the agent
|
|
184
|
+
uv run --project crow-cli pytest crow-cli/tests --run-e2e # live LLM calls (costs $)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Project layout
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
crow-cli/ the agent — ACP server, ReAct loop, CLI
|
|
191
|
+
crow-mcp/ built-in MCP tool server
|
|
192
|
+
crow-memory/ persistence + memory service (LanceDB, ColBERT/ColPali)
|
|
193
|
+
crow-task-mcp/ task-list MCP server for delegation (being reworked)
|
|
194
|
+
crow-orchestrator-mcp/ orchestration MCP server for delegation (being reworked)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# crow-cli
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://pypi.org/project/crow-cli/"><img src="https://img.shields.io/pypi/v/crow-cli" alt="PyPI version"></a>
|
|
5
|
+
<a href="https://pypi.org/project/crow-cli/"><img src="https://img.shields.io/pypi/pyversions/crow-cli" alt="Python versions"></a>
|
|
6
|
+
<a href="#license"><img src="https://img.shields.io/pypi/l/crow-cli" alt="License"></a>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
[Documentation](https://crow-ai.dev)
|
|
10
|
+
|
|
11
|
+
`crow-cli` is an [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) coding agent that runs in your terminal and inside ACP-compatible editors. It reads and edits code, runs shell commands, searches the web, and remembers your work across sessions.
|
|
12
|
+
|
|
13
|
+
Most agent toolkits treat persistence as an afterthought. crow-cli treats it as the point: every session lives in a dedicated memory service ([crow-memory](#crow-memory--persistence--memory-api)) built on [LanceDB](https://lancedb.github.io/lancedb/) with ColBERT and ColPali embeddings, so agents recall past conversations semantically and can delegate work to one another. Sessions get memorable coolname ids (like `taupe-squirrel-of-splendid-potency`) you can resume or read from any other agent.
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Python 3.14+, managed with [uv](https://docs.astral.sh/uv/)
|
|
18
|
+
- Docker, for the crow-memory and SearXNG services
|
|
19
|
+
- An API key for an OpenAI-compatible LLM provider (OpenRouter, OpenAI, your own endpoint, …)
|
|
20
|
+
|
|
21
|
+
| Platform | Notes |
|
|
22
|
+
|----------|-------|
|
|
23
|
+
| Linux | glibc 2.35+ (Ubuntu 22.04+, Debian 12+, or equivalent) |
|
|
24
|
+
| macOS | 13+ (Ventura), Intel and Apple Silicon |
|
|
25
|
+
| Windows | 10+ (64-bit); WSL2 recommended |
|
|
26
|
+
|
|
27
|
+
## Setup
|
|
28
|
+
|
|
29
|
+
Install the CLI:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/crow-cli/crow-cli.git
|
|
33
|
+
cd crow-cli
|
|
34
|
+
uv tool install crow-cli --python 3.14 # or run without installing: uvx crow-cli --help
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Initialize your configuration and start the backing services:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
crow-cli init # scaffolds ~/.crow (config.yaml, .env, docker-compose)
|
|
41
|
+
cd ~/.crow && docker compose up -d # starts crow-memory + SearXNG
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`crow-cli init` walks you through provider and model selection and writes your secrets to `~/.crow/.env`, referenced from the config as `${VAR}`.
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# One-shot prompt — prints the response and exits
|
|
50
|
+
crow-cli run "explain what this repo does"
|
|
51
|
+
|
|
52
|
+
# Continue an existing session by id
|
|
53
|
+
crow-cli run -s <session-id> "now add tests"
|
|
54
|
+
|
|
55
|
+
# Send a long, pre-written prompt from a file or stdin
|
|
56
|
+
crow-cli run -f delegation.md -s <session-id>
|
|
57
|
+
cat prompt.md | crow-cli run -
|
|
58
|
+
|
|
59
|
+
# Interactive REPL
|
|
60
|
+
crow-cli run -i
|
|
61
|
+
|
|
62
|
+
# Run as an ACP agent server (for editors)
|
|
63
|
+
crow-cli acp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Inspect stored sessions with `crow-cli inspect` (add `--session <id> --messages` to see a session's messages).
|
|
67
|
+
|
|
68
|
+
## Using crow-cli in your editor
|
|
69
|
+
|
|
70
|
+
crow-cli speaks ACP, so it works with any ACP-compatible client. For [Zed](https://zed.dev/), add to `~/.config/zed/settings.json`:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"agent_servers": {
|
|
75
|
+
"crow-cli": {
|
|
76
|
+
"type": "custom",
|
|
77
|
+
"command": "crow-cli",
|
|
78
|
+
"args": ["acp"]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The agent detects client capabilities (terminals, file read/write) and uses the native ACP versions when available, falling back to MCP tools otherwise.
|
|
85
|
+
|
|
86
|
+
## What's in the box
|
|
87
|
+
|
|
88
|
+
crow-cli is a monorepo. The pieces:
|
|
89
|
+
|
|
90
|
+
### crow-cli — the agent
|
|
91
|
+
|
|
92
|
+
The ACP-native agent: a streaming ReAct loop with tool calling, cancellation, conversation compaction, and multimodal input. Provider and model configuration lives in `~/.crow/config.yaml`.
|
|
93
|
+
|
|
94
|
+
### crow-memory — persistence + memory API
|
|
95
|
+
|
|
96
|
+
A standalone service — a LanceDB store with ColBERT (text) and ColPali (image) multivector embeddings — that the agent talks to over HTTP. It backs both session persistence and a semantic memory API, exposed to agents as three tools:
|
|
97
|
+
|
|
98
|
+
- `list_sessions()` — sessions ordered by recent activity (who's working on what)
|
|
99
|
+
- `query_memory(query)` — find which session discussed something, across all sessions
|
|
100
|
+
- `query_session(session_id)` — read or search within one session (spans all of that session's agents)
|
|
101
|
+
|
|
102
|
+
This is what makes multi-agent delegation work: launch a worker, then read its thoughts from any other agent. Today crow-memory runs as a Docker container the agent connects to; longer-term it moves toward an always-on daemon, in line with the ACP v2 direction.
|
|
103
|
+
|
|
104
|
+
### crow-mcp — the tool server
|
|
105
|
+
|
|
106
|
+
The built-in [MCP](https://modelcontextprotocol.io/) server providing the agent's tools:
|
|
107
|
+
|
|
108
|
+
| Tool | What it does |
|
|
109
|
+
|------|--------------|
|
|
110
|
+
| `read` / `write` / `edit` | File access — `edit` does precise, fuzzy-matched string replacement |
|
|
111
|
+
| `terminal` | Run shell commands in the workspace |
|
|
112
|
+
| `web_search` / `web_fetch` | Search the web (via SearXNG) and fetch pages as markdown |
|
|
113
|
+
| `capture_webcam` / `read_image_file` | Vision input |
|
|
114
|
+
| `list_sessions` / `query_memory` / `query_session` | Memory (see above) |
|
|
115
|
+
|
|
116
|
+
**Extensible by design:** register any MCP server in `~/.crow/config.yaml` and its tools appear alongside these automatically.
|
|
117
|
+
|
|
118
|
+
> ⚠️ **Tool names are not namespaced.** crow-mcp registers its tools as `read`, `edit`, `terminal`, … — not `crow-mcp_read`. When you add your own MCP servers, watch for name collisions.
|
|
119
|
+
|
|
120
|
+
### SearXNG — web search
|
|
121
|
+
|
|
122
|
+
crow-cli ships a maintained SearXNG configuration (stored as JSON so the agent can drive it over MCP) so web search works out of the box, without hand-editing SearXNG settings.
|
|
123
|
+
|
|
124
|
+
### Skills
|
|
125
|
+
|
|
126
|
+
Agents load reusable skills from `~/.crow/skills/` — each a directory with a `SKILL.md` describing when and how to use it. Skill distribution is still being worked out; today skills are local directories.
|
|
127
|
+
|
|
128
|
+
## Configuration
|
|
129
|
+
|
|
130
|
+
`~/.crow/config.yaml` holds providers, models, and MCP servers; secrets live in `~/.crow/.env` and are interpolated with `${VAR}`.
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
providers:
|
|
134
|
+
openrouter:
|
|
135
|
+
api_key: ${OPENROUTER_API_KEY}
|
|
136
|
+
base_url: https://openrouter.ai/api/v1
|
|
137
|
+
models:
|
|
138
|
+
my-model:
|
|
139
|
+
provider: openrouter
|
|
140
|
+
model: anthropic/claude-sonnet-4
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Development
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
git clone https://github.com/crow-cli/crow-cli.git
|
|
147
|
+
cd crow-cli
|
|
148
|
+
uv sync --project crow-cli
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Run the unit tests — fast and hermetic, no services required (tests that touch sessions use an in-memory fake of the memory service):
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
uv run --project crow-cli pytest crow-cli/tests/unit
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The persistence layer itself is tested in `crow-memory`. Integration and end-to-end tiers are opt-in:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
uv run --project crow-cli pytest crow-cli/tests --run-integration # spawn the agent
|
|
161
|
+
uv run --project crow-cli pytest crow-cli/tests --run-e2e # live LLM calls (costs $)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Project layout
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
crow-cli/ the agent — ACP server, ReAct loop, CLI
|
|
168
|
+
crow-mcp/ built-in MCP tool server
|
|
169
|
+
crow-memory/ persistence + memory service (LanceDB, ColBERT/ColPali)
|
|
170
|
+
crow-task-mcp/ task-list MCP server for delegation (being reworked)
|
|
171
|
+
crow-orchestrator-mcp/ orchestration MCP server for delegation (being reworked)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
MIT
|
|
@@ -15,7 +15,6 @@ a = Analysis(
|
|
|
15
15
|
+ copy_metadata('rich')
|
|
16
16
|
+ copy_metadata('openai')
|
|
17
17
|
+ copy_metadata('httpx')
|
|
18
|
-
+ copy_metadata('sqlalchemy')
|
|
19
18
|
+ copy_metadata('jinja2')
|
|
20
19
|
+ copy_metadata('pyyaml')
|
|
21
20
|
+ copy_metadata('coolname')
|
|
@@ -42,7 +41,6 @@ a = Analysis(
|
|
|
42
41
|
'fastmcp',
|
|
43
42
|
'openai',
|
|
44
43
|
'httpx',
|
|
45
|
-
'sqlalchemy',
|
|
46
44
|
'jinja2',
|
|
47
45
|
'yaml',
|
|
48
46
|
'coolname',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "crow-cli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.28"
|
|
4
4
|
description = "Add your description here"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.14"
|
|
@@ -16,7 +16,6 @@ dependencies = [
|
|
|
16
16
|
"openai>=2.21.0",
|
|
17
17
|
"pyyaml>=6.0.3",
|
|
18
18
|
"rich>=14.3.3",
|
|
19
|
-
"sqlalchemy>=2.0.46",
|
|
20
19
|
"typer>=0.24.1",
|
|
21
20
|
]
|
|
22
21
|
|
|
@@ -91,7 +91,7 @@ class LLMConfig:
|
|
|
91
91
|
class Config:
|
|
92
92
|
config_dir: Path
|
|
93
93
|
llm: LLMConfig = field(default_factory=LLMConfig)
|
|
94
|
-
|
|
94
|
+
memory_url: str = ""
|
|
95
95
|
mcp_servers: dict[str, Any] = field(default_factory=dict)
|
|
96
96
|
max_retries_per_step: int = 3
|
|
97
97
|
MAX_COMPACT_TOKENS: int = 190000
|
|
@@ -134,7 +134,7 @@ class Config:
|
|
|
134
134
|
_logger.info("No config.yaml found, returning bare Config")
|
|
135
135
|
return cls(
|
|
136
136
|
config_dir=target_dir,
|
|
137
|
-
|
|
137
|
+
memory_url="http://localhost:8901",
|
|
138
138
|
)
|
|
139
139
|
|
|
140
140
|
with open(config_file) as f:
|
|
@@ -162,9 +162,7 @@ class Config:
|
|
|
162
162
|
)
|
|
163
163
|
|
|
164
164
|
# Parse overrides
|
|
165
|
-
|
|
166
|
-
"DATABASE_PATH", str(target_dir / "crow.db")
|
|
167
|
-
)
|
|
165
|
+
memory_url = parsed.get("memory_url") or "http://localhost:8901"
|
|
168
166
|
overrides = {}
|
|
169
167
|
for key, typ in (
|
|
170
168
|
("max_retries_per_step", int),
|
|
@@ -186,7 +184,7 @@ class Config:
|
|
|
186
184
|
return cls(
|
|
187
185
|
config_dir=target_dir,
|
|
188
186
|
llm=llm,
|
|
189
|
-
|
|
187
|
+
memory_url=memory_url,
|
|
190
188
|
mcp_servers=mcp_servers,
|
|
191
189
|
system_prompt_path=system_prompt_path,
|
|
192
190
|
**overrides,
|
|
@@ -97,7 +97,13 @@ def find_line_numbers(uri: str) -> dict[str, Any]:
|
|
|
97
97
|
|
|
98
98
|
|
|
99
99
|
def get_directory_tree(cwd: str) -> str:
|
|
100
|
-
"""Returns a string representation of the directory tree rooted at cwd.
|
|
100
|
+
"""Returns a string representation of the directory tree rooted at cwd.
|
|
101
|
+
|
|
102
|
+
Always returns a string. If the tree cannot be generated (e.g. a
|
|
103
|
+
permission-denied or missing directory), DisplayTree returns None; we
|
|
104
|
+
coerce that to an empty string so the ``-> str`` contract holds and callers
|
|
105
|
+
never have to handle None.
|
|
106
|
+
"""
|
|
101
107
|
ignores = ["node_modules", "*.egg_info", "__pycache__", ".venv", "refs"]
|
|
102
108
|
tree = DisplayTree(stringRep=True, dirPath=cwd, ignoreList=ignores, maxDepth=3.0)
|
|
103
|
-
return tree
|
|
109
|
+
return tree or ""
|
|
@@ -10,6 +10,18 @@ Working directory:
|
|
|
10
10
|
AGENTS.md:
|
|
11
11
|
{{ agents_content }}
|
|
12
12
|
|
|
13
|
+
{% if skills %}
|
|
14
|
+
<SKILLS>
|
|
15
|
+
You have skills available in `~/.crow/skills/`. When a task matches a skill's
|
|
16
|
+
trigger below, read its SKILL.md and follow it.
|
|
17
|
+
|
|
18
|
+
{% for skill in skills %}
|
|
19
|
+
* **{{ skill.name }}** — {{ skill.description }}
|
|
20
|
+
Read it: `{{ skill.path }}`
|
|
21
|
+
{% endfor %}
|
|
22
|
+
</SKILLS>
|
|
23
|
+
{% endif %}
|
|
24
|
+
|
|
13
25
|
<ROLE>
|
|
14
26
|
* Your primary role is to assist users by executing commands, modifying code, and solving technical problems effectively. You should be thorough, methodical, and prioritize quality over speed.
|
|
15
27
|
* If the user asks a question, like "why is X happening", don't try to fix the problem. Just give an answer to the question.
|
|
@@ -123,11 +135,15 @@ AGENTS.md:
|
|
|
123
135
|
* Use `AGENTS.md` under the repository root as your persistent memory for repository-specific knowledge and context.
|
|
124
136
|
* Add important insights, patterns, and learnings to this file to improve future task performance.
|
|
125
137
|
* This repository skill is automatically loaded for every conversation and helps maintain context across sessions.
|
|
126
|
-
*
|
|
138
|
+
* Skills live in `~/.crow/skills/` (catalogued in the <SKILLS> block above when present). Each is a directory with a SKILL.md describing when and how to use it — read it before acting on a matching task.
|
|
139
|
+
* You can use the memory tools to access information from previous sessions:
|
|
140
|
+
`list_sessions()` (who's been working, by last activity), `query_memory(query=...)`
|
|
141
|
+
(find which session discussed something), and `query_session(session_id=...)`
|
|
142
|
+
(read/search within one session).
|
|
127
143
|
</MEMORY>
|
|
128
144
|
|
|
129
145
|
<QUERY_MEMORY>
|
|
130
|
-
When another agent finishes and you get a notification, DO NOT just sit there wondering what happened. Call `
|
|
146
|
+
When another agent finishes and you get a notification, DO NOT just sit there wondering what happened. Call `query_session(session_id=<their_sid>)` and actually read the damn message — a bare call returns their latest message, so you don't even need a limit. That is how you know what they did. To search what they worked on, add `query=...`; for surrounding detail add `context=`. To see who's been working lately, call `list_sessions()`. I PITY THE FOOL WHO IGNORES THE CONTEXT OF PREVIOUS AGENTS.
|
|
131
147
|
</QUERY_MEMORY>
|
|
132
148
|
"""
|
|
133
149
|
|
|
@@ -144,6 +160,32 @@ COMPOSE_YAML = """services:
|
|
|
144
160
|
volumes:
|
|
145
161
|
- ./searxng/:/etc/searxng
|
|
146
162
|
|
|
163
|
+
crow-memory:
|
|
164
|
+
image: ghcr.io/crow-cli/crow-memory:latest
|
|
165
|
+
# For local development, replace image with build:
|
|
166
|
+
# build:
|
|
167
|
+
# context: /path/to/crow-cli/crow-memory
|
|
168
|
+
# dockerfile: Dockerfile
|
|
169
|
+
restart: always
|
|
170
|
+
ports:
|
|
171
|
+
- "8901:8901"
|
|
172
|
+
environment:
|
|
173
|
+
- CROW_MEMORY_PATH=/data/memory.lance
|
|
174
|
+
- CROW_MEMORY_HOST=0.0.0.0
|
|
175
|
+
- CROW_MEMORY_PORT=8901
|
|
176
|
+
- CUDA_VISIBLE_DEVICES=
|
|
177
|
+
volumes:
|
|
178
|
+
- ./memory.lance:/data/memory.lance
|
|
179
|
+
# GPU acceleration — uncomment when you want hardware-accelerated embeddings.
|
|
180
|
+
# CPU mode is ~100ms text / ~2-3s image, which is fine for background agents.
|
|
181
|
+
# deploy:
|
|
182
|
+
# resources:
|
|
183
|
+
# reservations:
|
|
184
|
+
# devices:
|
|
185
|
+
# - driver: nvidia
|
|
186
|
+
# count: 1
|
|
187
|
+
# capabilities: [gpu]
|
|
188
|
+
|
|
147
189
|
litellm:
|
|
148
190
|
image: ghcr.io/berriai/litellm:main-v1.82.6-nightly
|
|
149
191
|
restart: always
|
|
@@ -172,8 +214,8 @@ mcpServers:
|
|
|
172
214
|
args:
|
|
173
215
|
- crow-mcp
|
|
174
216
|
|
|
175
|
-
# DEFAULT
|
|
176
|
-
|
|
217
|
+
# DEFAULT crow-memory service URL
|
|
218
|
+
memory_url: http://localhost:8901
|
|
177
219
|
|
|
178
220
|
# EXAMPLE PROVIDER
|
|
179
221
|
# providers:
|