cli-agent-yzf 0.6.0__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.
- cli_agent_yzf-0.6.0/PKG-INFO +161 -0
- cli_agent_yzf-0.6.0/README.md +143 -0
- cli_agent_yzf-0.6.0/pyproject.toml +81 -0
- cli_agent_yzf-0.6.0/pyproject.toml.orig +66 -0
- cli_agent_yzf-0.6.0/src/cli_agent/__init__.py +3 -0
- cli_agent_yzf-0.6.0/src/cli_agent/__main__.py +8 -0
- cli_agent_yzf-0.6.0/src/cli_agent/agent.py +388 -0
- cli_agent_yzf-0.6.0/src/cli_agent/checkpoint.py +345 -0
- cli_agent_yzf-0.6.0/src/cli_agent/cli.py +755 -0
- cli_agent_yzf-0.6.0/src/cli_agent/config.py +173 -0
- cli_agent_yzf-0.6.0/src/cli_agent/log.py +39 -0
- cli_agent_yzf-0.6.0/src/cli_agent/mcp.py +306 -0
- cli_agent_yzf-0.6.0/src/cli_agent/messages.py +127 -0
- cli_agent_yzf-0.6.0/src/cli_agent/permissions.py +294 -0
- cli_agent_yzf-0.6.0/src/cli_agent/prompt.py +79 -0
- cli_agent_yzf-0.6.0/src/cli_agent/providers/__init__.py +0 -0
- cli_agent_yzf-0.6.0/src/cli_agent/providers/anthropic.py +283 -0
- cli_agent_yzf-0.6.0/src/cli_agent/providers/base.py +116 -0
- cli_agent_yzf-0.6.0/src/cli_agent/providers/fake.py +81 -0
- cli_agent_yzf-0.6.0/src/cli_agent/providers/openai.py +301 -0
- cli_agent_yzf-0.6.0/src/cli_agent/py.typed +0 -0
- cli_agent_yzf-0.6.0/src/cli_agent/sandbox.py +117 -0
- cli_agent_yzf-0.6.0/src/cli_agent/session.py +274 -0
- cli_agent_yzf-0.6.0/src/cli_agent/tools/__init__.py +13 -0
- cli_agent_yzf-0.6.0/src/cli_agent/tools/base.py +118 -0
- cli_agent_yzf-0.6.0/src/cli_agent/tools/files.py +522 -0
- cli_agent_yzf-0.6.0/src/cli_agent/tools/shell.py +224 -0
- cli_agent_yzf-0.6.0/src/cli_agent/ui.py +283 -0
- cli_agent_yzf-0.6.0/src/cli_agent/workspace.py +59 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cli-agent-yzf
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: An autonomous coding agent for the terminal
|
|
5
|
+
Author: yezhoufan2005
|
|
6
|
+
Author-email: yezhoufan2005 <176495279+yezhoufan2005@users.noreply.github.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Requires-Dist: httpx==0.28.1
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# cli-agent
|
|
20
|
+
|
|
21
|
+
An autonomous coding agent for your terminal. Give it a task in plain language; it reads your code, edits files, runs commands, and checks its own work — inside one workspace directory, under a permission policy you control.
|
|
22
|
+
|
|
23
|
+
Status: early (0.x). See [docs/progress.md](docs/progress.md) for what is verified and what is not.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
Requires Python 3.11+ and [uv](https://docs.astral.sh/uv/) (or pip).
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv tool install cli-agent-yzf # from PyPI; installs the `cli-agent` command
|
|
31
|
+
# or a GitHub release wheel:
|
|
32
|
+
uv tool install https://github.com/yezhoufan2005/CLI-Agent/releases/download/v0.6.0/cli_agent_yzf-0.6.0-py3-none-any.whl
|
|
33
|
+
# or the latest main:
|
|
34
|
+
uv tool install git+https://github.com/yezhoufan2005/CLI-Agent
|
|
35
|
+
# or, from a checkout:
|
|
36
|
+
uv tool install .
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Set credentials in the environment (never in a config file):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
43
|
+
# or, for an Anthropic-compatible proxy:
|
|
44
|
+
export ANTHROPIC_BASE_URL=https://proxy.example
|
|
45
|
+
export ANTHROPIC_AUTH_TOKEN=...
|
|
46
|
+
cli-agent doctor # checks config and makes one tiny model call
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Any OpenAI-compatible Chat Completions endpoint (OpenAI, OpenRouter, Ollama, vLLM, LiteLLM, …) also works:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
export OPENAI_API_KEY=... # optional for local servers
|
|
53
|
+
export OPENAI_BASE_URL=http://localhost:11434/v1 # default: https://api.openai.com/v1
|
|
54
|
+
cli-agent --provider openai --model qwen2.5-coder "explain src/main.py"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Use
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cli-agent "the tests in tests/test_parser.py fail; fix them" # one task, then exit
|
|
61
|
+
echo "add a --verbose flag" | cli-agent --mode auto-edit # task from stdin
|
|
62
|
+
cli-agent # interactive session
|
|
63
|
+
cli-agent --continue "now update the docs" # continue last session here
|
|
64
|
+
cli-agent --json "summarize this repo" | jq . # JSON-lines events for scripts
|
|
65
|
+
cli-agent sessions # list saved sessions
|
|
66
|
+
cli-agent undo # revert file changes of the last prompt
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`cli-agent undo` (or `/undo` in a session) puts back the files the agent's file tools changed during the most recent prompt, and deletes files it created. Each further undo goes back one more prompt, up to 20. If you edited a file yourself after the agent wrote it, undo leaves that file alone. Changes made through shell commands are not tracked; undo tells you how many shell commands ran in that prompt, so check `git status` for those. The agent is instructed to change file contents only through its file tools, so most edits are covered.
|
|
70
|
+
|
|
71
|
+
Exit codes: `0` done, `1` error (model/API failure, refusal), `2` usage/config error, `3` stopped incomplete (turn limit, output-token limit, or `--max-session-tokens` budget), `130` interrupted (Ctrl-C), `129`/`143` terminated by SIGHUP/SIGTERM (the running command is killed and the session saved first). An interrupted or failed session is saved and can be resumed with `--resume ID`.
|
|
72
|
+
|
|
73
|
+
## Permissions
|
|
74
|
+
|
|
75
|
+
| Mode | Read tools | File writes | Shell commands |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| `read-only` | allow | deny | deny |
|
|
78
|
+
| `ask` (default) | allow | ask | ask |
|
|
79
|
+
| `auto-edit` | allow | allow | ask |
|
|
80
|
+
| `auto` | allow | allow | allow |
|
|
81
|
+
|
|
82
|
+
When there is no terminal to ask on (stdin piped, `--json`), "ask" means "deny".
|
|
83
|
+
|
|
84
|
+
Rules refine the mode: `--allow 'run_shell:pytest*'`, `--deny 'run_shell:git push*'`, or `allow = [...]` / `deny = [...]` in `~/.config/cli-agent/config.toml`. Deny rules win over allow rules.
|
|
85
|
+
|
|
86
|
+
- Path rules match the path normalized relative to the workspace, so `src/../.env` is matched as `.env`.
|
|
87
|
+
- A shell allow glob never matches a command line that contains shell metacharacters (`; & | $ ` < > ( )`, newlines). `run_shell:pytest*` allows `pytest -q tests/`, but `pytest; curl … | sh` still asks. The same applies to harmless pipes such as `pytest -q | tail`; in a headless run the agent is told which rule nearly matched, so it can retry the plain command.
|
|
88
|
+
- Shell deny rules are also checked against each simple command in a line (`cd x && git push` matches `git push*`). They are best-effort, not a security boundary.
|
|
89
|
+
- "Always" for a shell command approves exactly that command line for the session.
|
|
90
|
+
- Writes under `.git/` (hooks, config) always ask, even in `auto` and `auto-edit`, unless an explicit path rule such as `write_file:.git/info/*` allows them.
|
|
91
|
+
- A small built-in guard blocks catastrophic shell commands (`rm -rf ~`, `mkfs`, force-push, …) in every mode.
|
|
92
|
+
|
|
93
|
+
Each shell command runs with empty stdin, a timeout (default 120 s, max 600 s), and a 50 MB output cap. When it finishes, anything it left running (`&` jobs and, on Linux, `setsid`/`nohup` escapees) is killed, so an agent cannot leave daemons behind.
|
|
94
|
+
|
|
95
|
+
### Shell sandbox (Linux)
|
|
96
|
+
|
|
97
|
+
`--sandbox auto` (or `sandbox = "auto"` in the config file, or `CLI_AGENT_SANDBOX=auto`) runs every shell command inside [bubblewrap](https://github.com/containers/bubblewrap):
|
|
98
|
+
- The filesystem is read-only except for the workspace and a private `/tmp`.
|
|
99
|
+
- Your home directory is replaced by an empty directory, so `~/.ssh` and `~/.aws` are not visible.
|
|
100
|
+
- There is no network unless you set `sandbox_network = true`.
|
|
101
|
+
- The command runs in its own PID namespace.
|
|
102
|
+
|
|
103
|
+
`auto` falls back to unsandboxed execution with a warning when bubblewrap cannot run. `required` refuses to start in that case. Bubblewrap needs unprivileged user namespaces, so it does not work inside most Docker containers. On Ubuntu 24.04 it may need `kernel.apparmor_restrict_unprivileged_userns=0` or an AppArmor profile. The default is `off`.
|
|
104
|
+
|
|
105
|
+
File tools cannot touch paths outside the workspace (symlinks are resolved first; list/search skip symlinks). Shell commands run with your user's privileges and are **not sandboxed**: the workspace boundary applies only to file tools, and an approved command can read or change anything your user can. Credential-like environment variables (`*TOKEN*`, `*KEY*`, `*SECRET*`, `*_PASS`, `DATABASE_URL`, `SSH_AUTH_SOCK`, …) are removed from the environment of shell commands, and on Linux the agent marks itself non-dumpable so commands cannot read its environment through `/proc`. Credential *files* your user can read (e.g. `~/.aws/credentials`) remain readable to shell commands.
|
|
106
|
+
|
|
107
|
+
`AGENTS.md` / `CLAUDE.md` in the workspace root are given to the model as project conventions; they cannot change permissions.
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
`~/.config/cli-agent/config.toml` (override with `CLI_AGENT_CONFIG` or `--config`):
|
|
112
|
+
|
|
113
|
+
```toml
|
|
114
|
+
model = "claude-sonnet-4-6"
|
|
115
|
+
mode = "auto-edit"
|
|
116
|
+
allow = ["run_shell:pytest*", "run_shell:git status*", "run_shell:git diff*"]
|
|
117
|
+
deny = ["run_shell:git push*"]
|
|
118
|
+
max_turns = 50
|
|
119
|
+
max_session_tokens = 2000000 # optional cost cap per session (input + output tokens)
|
|
120
|
+
shell_timeout = 120
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### MCP servers
|
|
124
|
+
|
|
125
|
+
Tools from [MCP](https://modelcontextprotocol.io) stdio servers can be added in the user config file only; a repository cannot add servers:
|
|
126
|
+
|
|
127
|
+
```toml
|
|
128
|
+
[mcp_servers.fs]
|
|
129
|
+
command = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
|
|
130
|
+
env = { SOME_SETTING = "value" } # optional; passed to the server as-is
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
They appear to the model as `mcp__<server>__<tool>`. Every MCP tool counts as a command: it asks in `ask` and `auto-edit` mode and is denied in `read-only` mode. You can allow one with a rule such as `--allow mcp__fs__read_file`. Servers get the same scrubbed environment as shell commands, plus their configured `env`. They are not sandboxed. Only the tools part of MCP is supported; resources, prompts and sampling are not.
|
|
134
|
+
|
|
135
|
+
Precedence: defaults < config file < environment (`CLI_AGENT_PROVIDER`, `CLI_AGENT_MODEL`, `CLI_AGENT_MODE`, `ANTHROPIC_*` / `OPENAI_*`) < flags. `provider = "openai"` in the config file selects the OpenAI-compatible provider.
|
|
136
|
+
|
|
137
|
+
## How well does it work?
|
|
138
|
+
|
|
139
|
+
Measured with real models; full method and caveats in [docs/progress.md](docs/progress.md):
|
|
140
|
+
|
|
141
|
+
| Benchmark | claude-sonnet-4-6 | claude-haiku-4-5 |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| Built-in E2E tasks (`scripts/e2e.sh`, 11 tasks) | 11/11 | 11/11 |
|
|
144
|
+
| Exercism Python, 30 exercises, hidden tests (`scripts/bench.py`) | 27/30 | 27/30 |
|
|
145
|
+
| SWE-bench Lite sympy, 2 samples of 20, Docker-free (`scripts/swebench_sympy.py`) | 29/40 | 30/40 |
|
|
146
|
+
|
|
147
|
+
These are single runs on small samples, not official leaderboard numbers.
|
|
148
|
+
|
|
149
|
+
## Development
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
./scripts/setup-dev.sh # once: sync deps, enable the pre-commit hook
|
|
153
|
+
./scripts/check.sh # format, lint, type-check, tests — the same gate CI runs
|
|
154
|
+
./scripts/e2e.sh # real-model tasks (needs credentials; not run in CI)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Release procedure: [docs/release.md](docs/release.md).
|
|
158
|
+
|
|
159
|
+
Docs: [product spec](docs/product.md) · [architecture](docs/architecture.md) · [operating model](docs/operating-model.md) · [backlog](docs/backlog.md) · [progress](docs/progress.md).
|
|
160
|
+
|
|
161
|
+
License: MIT.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# cli-agent
|
|
2
|
+
|
|
3
|
+
An autonomous coding agent for your terminal. Give it a task in plain language; it reads your code, edits files, runs commands, and checks its own work — inside one workspace directory, under a permission policy you control.
|
|
4
|
+
|
|
5
|
+
Status: early (0.x). See [docs/progress.md](docs/progress.md) for what is verified and what is not.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Requires Python 3.11+ and [uv](https://docs.astral.sh/uv/) (or pip).
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv tool install cli-agent-yzf # from PyPI; installs the `cli-agent` command
|
|
13
|
+
# or a GitHub release wheel:
|
|
14
|
+
uv tool install https://github.com/yezhoufan2005/CLI-Agent/releases/download/v0.6.0/cli_agent_yzf-0.6.0-py3-none-any.whl
|
|
15
|
+
# or the latest main:
|
|
16
|
+
uv tool install git+https://github.com/yezhoufan2005/CLI-Agent
|
|
17
|
+
# or, from a checkout:
|
|
18
|
+
uv tool install .
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Set credentials in the environment (never in a config file):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
25
|
+
# or, for an Anthropic-compatible proxy:
|
|
26
|
+
export ANTHROPIC_BASE_URL=https://proxy.example
|
|
27
|
+
export ANTHROPIC_AUTH_TOKEN=...
|
|
28
|
+
cli-agent doctor # checks config and makes one tiny model call
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Any OpenAI-compatible Chat Completions endpoint (OpenAI, OpenRouter, Ollama, vLLM, LiteLLM, …) also works:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
export OPENAI_API_KEY=... # optional for local servers
|
|
35
|
+
export OPENAI_BASE_URL=http://localhost:11434/v1 # default: https://api.openai.com/v1
|
|
36
|
+
cli-agent --provider openai --model qwen2.5-coder "explain src/main.py"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Use
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cli-agent "the tests in tests/test_parser.py fail; fix them" # one task, then exit
|
|
43
|
+
echo "add a --verbose flag" | cli-agent --mode auto-edit # task from stdin
|
|
44
|
+
cli-agent # interactive session
|
|
45
|
+
cli-agent --continue "now update the docs" # continue last session here
|
|
46
|
+
cli-agent --json "summarize this repo" | jq . # JSON-lines events for scripts
|
|
47
|
+
cli-agent sessions # list saved sessions
|
|
48
|
+
cli-agent undo # revert file changes of the last prompt
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`cli-agent undo` (or `/undo` in a session) puts back the files the agent's file tools changed during the most recent prompt, and deletes files it created. Each further undo goes back one more prompt, up to 20. If you edited a file yourself after the agent wrote it, undo leaves that file alone. Changes made through shell commands are not tracked; undo tells you how many shell commands ran in that prompt, so check `git status` for those. The agent is instructed to change file contents only through its file tools, so most edits are covered.
|
|
52
|
+
|
|
53
|
+
Exit codes: `0` done, `1` error (model/API failure, refusal), `2` usage/config error, `3` stopped incomplete (turn limit, output-token limit, or `--max-session-tokens` budget), `130` interrupted (Ctrl-C), `129`/`143` terminated by SIGHUP/SIGTERM (the running command is killed and the session saved first). An interrupted or failed session is saved and can be resumed with `--resume ID`.
|
|
54
|
+
|
|
55
|
+
## Permissions
|
|
56
|
+
|
|
57
|
+
| Mode | Read tools | File writes | Shell commands |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| `read-only` | allow | deny | deny |
|
|
60
|
+
| `ask` (default) | allow | ask | ask |
|
|
61
|
+
| `auto-edit` | allow | allow | ask |
|
|
62
|
+
| `auto` | allow | allow | allow |
|
|
63
|
+
|
|
64
|
+
When there is no terminal to ask on (stdin piped, `--json`), "ask" means "deny".
|
|
65
|
+
|
|
66
|
+
Rules refine the mode: `--allow 'run_shell:pytest*'`, `--deny 'run_shell:git push*'`, or `allow = [...]` / `deny = [...]` in `~/.config/cli-agent/config.toml`. Deny rules win over allow rules.
|
|
67
|
+
|
|
68
|
+
- Path rules match the path normalized relative to the workspace, so `src/../.env` is matched as `.env`.
|
|
69
|
+
- A shell allow glob never matches a command line that contains shell metacharacters (`; & | $ ` < > ( )`, newlines). `run_shell:pytest*` allows `pytest -q tests/`, but `pytest; curl … | sh` still asks. The same applies to harmless pipes such as `pytest -q | tail`; in a headless run the agent is told which rule nearly matched, so it can retry the plain command.
|
|
70
|
+
- Shell deny rules are also checked against each simple command in a line (`cd x && git push` matches `git push*`). They are best-effort, not a security boundary.
|
|
71
|
+
- "Always" for a shell command approves exactly that command line for the session.
|
|
72
|
+
- Writes under `.git/` (hooks, config) always ask, even in `auto` and `auto-edit`, unless an explicit path rule such as `write_file:.git/info/*` allows them.
|
|
73
|
+
- A small built-in guard blocks catastrophic shell commands (`rm -rf ~`, `mkfs`, force-push, …) in every mode.
|
|
74
|
+
|
|
75
|
+
Each shell command runs with empty stdin, a timeout (default 120 s, max 600 s), and a 50 MB output cap. When it finishes, anything it left running (`&` jobs and, on Linux, `setsid`/`nohup` escapees) is killed, so an agent cannot leave daemons behind.
|
|
76
|
+
|
|
77
|
+
### Shell sandbox (Linux)
|
|
78
|
+
|
|
79
|
+
`--sandbox auto` (or `sandbox = "auto"` in the config file, or `CLI_AGENT_SANDBOX=auto`) runs every shell command inside [bubblewrap](https://github.com/containers/bubblewrap):
|
|
80
|
+
- The filesystem is read-only except for the workspace and a private `/tmp`.
|
|
81
|
+
- Your home directory is replaced by an empty directory, so `~/.ssh` and `~/.aws` are not visible.
|
|
82
|
+
- There is no network unless you set `sandbox_network = true`.
|
|
83
|
+
- The command runs in its own PID namespace.
|
|
84
|
+
|
|
85
|
+
`auto` falls back to unsandboxed execution with a warning when bubblewrap cannot run. `required` refuses to start in that case. Bubblewrap needs unprivileged user namespaces, so it does not work inside most Docker containers. On Ubuntu 24.04 it may need `kernel.apparmor_restrict_unprivileged_userns=0` or an AppArmor profile. The default is `off`.
|
|
86
|
+
|
|
87
|
+
File tools cannot touch paths outside the workspace (symlinks are resolved first; list/search skip symlinks). Shell commands run with your user's privileges and are **not sandboxed**: the workspace boundary applies only to file tools, and an approved command can read or change anything your user can. Credential-like environment variables (`*TOKEN*`, `*KEY*`, `*SECRET*`, `*_PASS`, `DATABASE_URL`, `SSH_AUTH_SOCK`, …) are removed from the environment of shell commands, and on Linux the agent marks itself non-dumpable so commands cannot read its environment through `/proc`. Credential *files* your user can read (e.g. `~/.aws/credentials`) remain readable to shell commands.
|
|
88
|
+
|
|
89
|
+
`AGENTS.md` / `CLAUDE.md` in the workspace root are given to the model as project conventions; they cannot change permissions.
|
|
90
|
+
|
|
91
|
+
## Configuration
|
|
92
|
+
|
|
93
|
+
`~/.config/cli-agent/config.toml` (override with `CLI_AGENT_CONFIG` or `--config`):
|
|
94
|
+
|
|
95
|
+
```toml
|
|
96
|
+
model = "claude-sonnet-4-6"
|
|
97
|
+
mode = "auto-edit"
|
|
98
|
+
allow = ["run_shell:pytest*", "run_shell:git status*", "run_shell:git diff*"]
|
|
99
|
+
deny = ["run_shell:git push*"]
|
|
100
|
+
max_turns = 50
|
|
101
|
+
max_session_tokens = 2000000 # optional cost cap per session (input + output tokens)
|
|
102
|
+
shell_timeout = 120
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### MCP servers
|
|
106
|
+
|
|
107
|
+
Tools from [MCP](https://modelcontextprotocol.io) stdio servers can be added in the user config file only; a repository cannot add servers:
|
|
108
|
+
|
|
109
|
+
```toml
|
|
110
|
+
[mcp_servers.fs]
|
|
111
|
+
command = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
|
|
112
|
+
env = { SOME_SETTING = "value" } # optional; passed to the server as-is
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
They appear to the model as `mcp__<server>__<tool>`. Every MCP tool counts as a command: it asks in `ask` and `auto-edit` mode and is denied in `read-only` mode. You can allow one with a rule such as `--allow mcp__fs__read_file`. Servers get the same scrubbed environment as shell commands, plus their configured `env`. They are not sandboxed. Only the tools part of MCP is supported; resources, prompts and sampling are not.
|
|
116
|
+
|
|
117
|
+
Precedence: defaults < config file < environment (`CLI_AGENT_PROVIDER`, `CLI_AGENT_MODEL`, `CLI_AGENT_MODE`, `ANTHROPIC_*` / `OPENAI_*`) < flags. `provider = "openai"` in the config file selects the OpenAI-compatible provider.
|
|
118
|
+
|
|
119
|
+
## How well does it work?
|
|
120
|
+
|
|
121
|
+
Measured with real models; full method and caveats in [docs/progress.md](docs/progress.md):
|
|
122
|
+
|
|
123
|
+
| Benchmark | claude-sonnet-4-6 | claude-haiku-4-5 |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| Built-in E2E tasks (`scripts/e2e.sh`, 11 tasks) | 11/11 | 11/11 |
|
|
126
|
+
| Exercism Python, 30 exercises, hidden tests (`scripts/bench.py`) | 27/30 | 27/30 |
|
|
127
|
+
| SWE-bench Lite sympy, 2 samples of 20, Docker-free (`scripts/swebench_sympy.py`) | 29/40 | 30/40 |
|
|
128
|
+
|
|
129
|
+
These are single runs on small samples, not official leaderboard numbers.
|
|
130
|
+
|
|
131
|
+
## Development
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
./scripts/setup-dev.sh # once: sync deps, enable the pre-commit hook
|
|
135
|
+
./scripts/check.sh # format, lint, type-check, tests — the same gate CI runs
|
|
136
|
+
./scripts/e2e.sh # real-model tasks (needs credentials; not run in CI)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Release procedure: [docs/release.md](docs/release.md).
|
|
140
|
+
|
|
141
|
+
Docs: [product spec](docs/product.md) · [architecture](docs/architecture.md) · [operating model](docs/operating-model.md) · [backlog](docs/backlog.md) · [progress](docs/progress.md).
|
|
142
|
+
|
|
143
|
+
License: MIT.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "cli-agent-yzf"
|
|
3
|
+
version = "0.6.0"
|
|
4
|
+
description = "An autonomous coding agent for the terminal"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
dependencies = ["httpx==0.28.1"]
|
|
8
|
+
license = "MIT"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Programming Language :: Python :: 3.11",
|
|
11
|
+
"Programming Language :: Python :: 3.12",
|
|
12
|
+
"Programming Language :: Python :: 3.13",
|
|
13
|
+
"Programming Language :: Python :: 3.14",
|
|
14
|
+
"Environment :: Console",
|
|
15
|
+
"Operating System :: POSIX :: Linux",
|
|
16
|
+
"Operating System :: MacOS",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[[project.authors]]
|
|
20
|
+
name = "yezhoufan2005"
|
|
21
|
+
email = "176495279+yezhoufan2005@users.noreply.github.com"
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
cli-agent = "cli_agent.cli:main"
|
|
25
|
+
|
|
26
|
+
[build-system]
|
|
27
|
+
requires = ["uv_build>=0.11.31,<0.12.0"]
|
|
28
|
+
build-backend = "uv_build"
|
|
29
|
+
|
|
30
|
+
[tool.uv.build-backend]
|
|
31
|
+
module-name = "cli_agent"
|
|
32
|
+
|
|
33
|
+
[tool.ruff]
|
|
34
|
+
line-length = 100
|
|
35
|
+
target-version = "py311"
|
|
36
|
+
extend-exclude = ["tests/e2e"]
|
|
37
|
+
|
|
38
|
+
[tool.ruff.lint]
|
|
39
|
+
select = [
|
|
40
|
+
"E",
|
|
41
|
+
"F",
|
|
42
|
+
"W",
|
|
43
|
+
"I",
|
|
44
|
+
"B",
|
|
45
|
+
"UP",
|
|
46
|
+
"S",
|
|
47
|
+
"BLE",
|
|
48
|
+
"RUF",
|
|
49
|
+
]
|
|
50
|
+
ignore = [
|
|
51
|
+
"S603",
|
|
52
|
+
"S607",
|
|
53
|
+
"S101",
|
|
54
|
+
"RUF001",
|
|
55
|
+
"RUF012",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint.per-file-ignores]
|
|
59
|
+
"tests/**" = [
|
|
60
|
+
"S",
|
|
61
|
+
"BLE",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[tool.mypy]
|
|
65
|
+
python_version = "3.11"
|
|
66
|
+
strict = true
|
|
67
|
+
files = ["src"]
|
|
68
|
+
|
|
69
|
+
[tool.pytest.ini_options]
|
|
70
|
+
testpaths = ["tests"]
|
|
71
|
+
timeout = 60
|
|
72
|
+
addopts = "-q"
|
|
73
|
+
norecursedirs = ["tests/e2e"]
|
|
74
|
+
|
|
75
|
+
[dependency-groups]
|
|
76
|
+
dev = [
|
|
77
|
+
"mypy==1.18.2",
|
|
78
|
+
"pytest==8.4.2",
|
|
79
|
+
"pytest-timeout==2.4.0",
|
|
80
|
+
"ruff==0.14.3",
|
|
81
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "cli-agent-yzf"
|
|
3
|
+
version = "0.6.0"
|
|
4
|
+
description = "An autonomous coding agent for the terminal"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "yezhoufan2005", email = "176495279+yezhoufan2005@users.noreply.github.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"httpx==0.28.1",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
license = "MIT"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Programming Language :: Python :: 3.13",
|
|
19
|
+
"Programming Language :: Python :: 3.14",
|
|
20
|
+
"Environment :: Console",
|
|
21
|
+
"Operating System :: POSIX :: Linux",
|
|
22
|
+
"Operating System :: MacOS",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.scripts]
|
|
26
|
+
cli-agent = "cli_agent.cli:main"
|
|
27
|
+
|
|
28
|
+
[build-system]
|
|
29
|
+
requires = ["uv_build>=0.11.31,<0.12.0"]
|
|
30
|
+
build-backend = "uv_build"
|
|
31
|
+
|
|
32
|
+
# "cli-agent" is taken on PyPI; the distribution is "cli-agent-yzf", the module and command stay cli_agent / cli-agent
|
|
33
|
+
[tool.uv.build-backend]
|
|
34
|
+
module-name = "cli_agent"
|
|
35
|
+
|
|
36
|
+
[dependency-groups]
|
|
37
|
+
dev = [
|
|
38
|
+
"mypy==1.18.2",
|
|
39
|
+
"pytest==8.4.2",
|
|
40
|
+
"pytest-timeout==2.4.0",
|
|
41
|
+
"ruff==0.14.3",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[tool.ruff]
|
|
45
|
+
line-length = 100
|
|
46
|
+
target-version = "py311"
|
|
47
|
+
# E2E fixture repos are test inputs for the agent, not project code.
|
|
48
|
+
extend-exclude = ["tests/e2e"]
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint]
|
|
51
|
+
select = ["E", "F", "W", "I", "B", "UP", "S", "BLE", "RUF"]
|
|
52
|
+
ignore = ["S603", "S607", "S101", "RUF001", "RUF012"]
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint.per-file-ignores]
|
|
55
|
+
"tests/**" = ["S", "BLE"]
|
|
56
|
+
|
|
57
|
+
[tool.mypy]
|
|
58
|
+
python_version = "3.11"
|
|
59
|
+
strict = true
|
|
60
|
+
files = ["src"]
|
|
61
|
+
|
|
62
|
+
[tool.pytest.ini_options]
|
|
63
|
+
testpaths = ["tests"]
|
|
64
|
+
timeout = 60
|
|
65
|
+
addopts = "-q"
|
|
66
|
+
norecursedirs = ["tests/e2e"]
|