coding-agent-cli 0.1.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.
- coding_agent_cli-0.1.0/.editorconfig +12 -0
- coding_agent_cli-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +31 -0
- coding_agent_cli-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- coding_agent_cli-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +17 -0
- coding_agent_cli-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- coding_agent_cli-0.1.0/.github/dependabot.yml +6 -0
- coding_agent_cli-0.1.0/.github/workflows/ci.yml +47 -0
- coding_agent_cli-0.1.0/.github/workflows/pr-title.yml +18 -0
- coding_agent_cli-0.1.0/.github/workflows/release.yml +116 -0
- coding_agent_cli-0.1.0/.gitignore +8 -0
- coding_agent_cli-0.1.0/.release-please-manifest.json +3 -0
- coding_agent_cli-0.1.0/AGENTS.md +47 -0
- coding_agent_cli-0.1.0/CHANGELOG.md +12 -0
- coding_agent_cli-0.1.0/CLAUDE.md +1 -0
- coding_agent_cli-0.1.0/CODE_OF_CONDUCT.md +30 -0
- coding_agent_cli-0.1.0/CONTRIBUTING.md +91 -0
- coding_agent_cli-0.1.0/LICENSE +21 -0
- coding_agent_cli-0.1.0/PKG-INFO +217 -0
- coding_agent_cli-0.1.0/README.md +194 -0
- coding_agent_cli-0.1.0/SECURITY.md +26 -0
- coding_agent_cli-0.1.0/docs/plans/coding-agent-cli/.handover.md +30 -0
- coding_agent_cli-0.1.0/docs/plans/coding-agent-cli/DESIGN.md +300 -0
- coding_agent_cli-0.1.0/docs/plans/coding-agent-cli/PLAN.md +265 -0
- coding_agent_cli-0.1.0/docs/plans/coding-agent-cli/journal-phase4.md +169 -0
- coding_agent_cli-0.1.0/docs/plans/coding-agent-cli/journal-phase5.md +195 -0
- coding_agent_cli-0.1.0/pyproject.toml +65 -0
- coding_agent_cli-0.1.0/release-please-config.json +21 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/__init__.py +47 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_args.py +66 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_classify.py +170 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/__init__.py +1 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/_common.py +330 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/_usage.py +77 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/agy.py +340 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/claude.py +304 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/codex.py +333 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/codex_rollout.py +439 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_drivers/pi.py +333 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_platform.py +171 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/_process.py +338 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/api.py +190 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/events.py +109 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/py.typed +0 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/registry.py +67 -0
- coding_agent_cli-0.1.0/src/coding_agent_cli/types.py +90 -0
- coding_agent_cli-0.1.0/tests/__init__.py +0 -0
- coding_agent_cli-0.1.0/tests/cli_stub.py +144 -0
- coding_agent_cli-0.1.0/tests/conftest.py +1 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/echo_stdin.py +8 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/emit_both.py +6 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/exit_now.py +5 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/exit_status.py +6 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/fake_cli.py +46 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/grandchild.py +10 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/long_line.py +6 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/many_lines.py +6 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/non_utf8.py +6 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/sleeper.py +6 -0
- coding_agent_cli-0.1.0/tests/fixtures/fake_cli/spawn_and_sleep.py +11 -0
- coding_agent_cli-0.1.0/tests/fixtures/usage/agy.jsonl +6 -0
- coding_agent_cli-0.1.0/tests/fixtures/usage/claude.jsonl +12 -0
- coding_agent_cli-0.1.0/tests/fixtures/usage/codex.jsonl +7 -0
- coding_agent_cli-0.1.0/tests/fixtures/usage/pi.jsonl +55 -0
- coding_agent_cli-0.1.0/tests/launchers.py +42 -0
- coding_agent_cli-0.1.0/tests/test_agy_driver.py +723 -0
- coding_agent_cli-0.1.0/tests/test_api_contract.py +135 -0
- coding_agent_cli-0.1.0/tests/test_args.py +42 -0
- coding_agent_cli-0.1.0/tests/test_classify.py +88 -0
- coding_agent_cli-0.1.0/tests/test_claude_driver.py +735 -0
- coding_agent_cli-0.1.0/tests/test_codex_driver.py +692 -0
- coding_agent_cli-0.1.0/tests/test_codex_rollout.py +610 -0
- coding_agent_cli-0.1.0/tests/test_events.py +68 -0
- coding_agent_cli-0.1.0/tests/test_live.py +41 -0
- coding_agent_cli-0.1.0/tests/test_packaging.py +53 -0
- coding_agent_cli-0.1.0/tests/test_pi_driver.py +746 -0
- coding_agent_cli-0.1.0/tests/test_process.py +394 -0
- coding_agent_cli-0.1.0/tests/test_registry.py +55 -0
- coding_agent_cli-0.1.0/tests/test_stream.py +53 -0
- coding_agent_cli-0.1.0/tests/test_types.py +101 -0
- coding_agent_cli-0.1.0/tests/test_usage.py +87 -0
- coding_agent_cli-0.1.0/tests/toy_driver.py +68 -0
- coding_agent_cli-0.1.0/uv.lock +156 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something does not work as documented
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: what
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened
|
|
9
|
+
description: Include the `Result.outcome` and `Result.error` if relevant. Remove prompts, tokens, and private paths.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: repro
|
|
14
|
+
attributes:
|
|
15
|
+
label: Steps to reproduce
|
|
16
|
+
render: python
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: expected
|
|
21
|
+
attributes:
|
|
22
|
+
label: Expected behavior
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
- type: input
|
|
26
|
+
id: versions
|
|
27
|
+
attributes:
|
|
28
|
+
label: Versions
|
|
29
|
+
description: coding-agent-cli, Python, OS, and the CLI's `--version` output
|
|
30
|
+
validations:
|
|
31
|
+
required: true
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new driver, option, or behavior
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem
|
|
9
|
+
description: What are you trying to do, and what blocks you today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposal
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What changes and why. Link the issue: Fixes #123 -->
|
|
4
|
+
|
|
5
|
+
## Checklist
|
|
6
|
+
|
|
7
|
+
- [ ] `uv run ruff format --check`, `uv run ruff check`, `uv run pyright`, and `uv run pytest` pass
|
|
8
|
+
- [ ] Tests cover the change
|
|
9
|
+
- [ ] PR title follows Conventional Commits, such as `feat: add X` or `fix(codex): handle Y`
|
|
10
|
+
- [ ] README updated if public behavior or signatures changed
|
|
11
|
+
- [ ] No driver adds a permission, approval, or sandbox-bypass flag
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ci-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
lint:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
- run: uv sync --locked
|
|
25
|
+
- run: uv run ruff format --check
|
|
26
|
+
- run: uv run ruff check
|
|
27
|
+
- run: uv run pyright
|
|
28
|
+
|
|
29
|
+
test:
|
|
30
|
+
strategy:
|
|
31
|
+
fail-fast: false
|
|
32
|
+
matrix:
|
|
33
|
+
include:
|
|
34
|
+
- { os: ubuntu-latest, python: "3.12" }
|
|
35
|
+
- { os: macos-latest, python: "3.12" }
|
|
36
|
+
- { os: windows-latest, python: "3.12" }
|
|
37
|
+
- { os: ubuntu-latest, python: "3.13" }
|
|
38
|
+
- { os: ubuntu-latest, python: "3.14" }
|
|
39
|
+
runs-on: ${{ matrix.os }}
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v7
|
|
42
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
43
|
+
with:
|
|
44
|
+
python-version: ${{ matrix.python }}
|
|
45
|
+
- run: uv sync --locked
|
|
46
|
+
- run: uv run pytest
|
|
47
|
+
- run: uv run pyright
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: PR title
|
|
2
|
+
|
|
3
|
+
# Squash merges use the PR title as the commit message, and release-please reads those commits.
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
pull_request_target:
|
|
7
|
+
types: [opened, edited, reopened, synchronize]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
pull-requests: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
conventional:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
17
|
+
env:
|
|
18
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Pushes to main run release-please, which keeps a release PR open with the next version and changelog.
|
|
4
|
+
# Merging that PR creates the tag and GitHub Release, then this workflow builds and publishes to PyPI.
|
|
5
|
+
# Pushing a v* tag by hand also publishes; use it for the first release.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: release-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
release-please:
|
|
21
|
+
if: github.ref == 'refs/heads/main'
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
permissions:
|
|
24
|
+
contents: write
|
|
25
|
+
pull-requests: write
|
|
26
|
+
outputs:
|
|
27
|
+
release_created: ${{ steps.release.outputs.release_created }}
|
|
28
|
+
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
29
|
+
steps:
|
|
30
|
+
- id: release
|
|
31
|
+
uses: googleapis/release-please-action@v5
|
|
32
|
+
# release-please bumps pyproject.toml but not uv.lock, so `uv sync --locked` would fail on the release PR.
|
|
33
|
+
- if: steps.release.outputs.pr
|
|
34
|
+
uses: actions/checkout@v7
|
|
35
|
+
with:
|
|
36
|
+
ref: ${{ fromJSON(steps.release.outputs.pr).headBranchName }}
|
|
37
|
+
- if: steps.release.outputs.pr
|
|
38
|
+
uses: astral-sh/setup-uv@v10.3.3
|
|
39
|
+
- if: steps.release.outputs.pr
|
|
40
|
+
run: |
|
|
41
|
+
uv lock
|
|
42
|
+
if ! git diff --quiet uv.lock; then
|
|
43
|
+
git config user.name "github-actions[bot]"
|
|
44
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
45
|
+
git commit -am "chore: update uv.lock for release"
|
|
46
|
+
git push
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
build:
|
|
50
|
+
needs: release-please
|
|
51
|
+
if: >-
|
|
52
|
+
!failure() && !cancelled() &&
|
|
53
|
+
(needs.release-please.outputs.release_created == 'true' || startsWith(github.ref, 'refs/tags/v'))
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
outputs:
|
|
56
|
+
tag: ${{ steps.tag.outputs.tag }}
|
|
57
|
+
steps:
|
|
58
|
+
- id: tag
|
|
59
|
+
run: echo "tag=${RP_TAG:-$GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
|
|
60
|
+
env:
|
|
61
|
+
RP_TAG: ${{ needs.release-please.outputs.tag_name }}
|
|
62
|
+
- uses: actions/checkout@v7
|
|
63
|
+
with:
|
|
64
|
+
ref: ${{ steps.tag.outputs.tag }}
|
|
65
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.12"
|
|
68
|
+
- name: Check tag matches package version
|
|
69
|
+
run: |
|
|
70
|
+
version=$(uv version --short)
|
|
71
|
+
test "v$version" = "$TAG" || { echo "::error::tag $TAG does not match version $version"; exit 1; }
|
|
72
|
+
env:
|
|
73
|
+
TAG: ${{ steps.tag.outputs.tag }}
|
|
74
|
+
- run: uv sync --locked
|
|
75
|
+
- run: uv run pytest
|
|
76
|
+
- run: uv build
|
|
77
|
+
- uses: actions/upload-artifact@v7
|
|
78
|
+
with:
|
|
79
|
+
name: dist
|
|
80
|
+
path: dist/
|
|
81
|
+
|
|
82
|
+
publish:
|
|
83
|
+
needs: build
|
|
84
|
+
if: ${{ !failure() && !cancelled() && needs.build.result == 'success' }}
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
environment:
|
|
87
|
+
name: pypi
|
|
88
|
+
url: https://pypi.org/project/coding-agent-cli/
|
|
89
|
+
permissions:
|
|
90
|
+
id-token: write
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/download-artifact@v8
|
|
93
|
+
with:
|
|
94
|
+
name: dist
|
|
95
|
+
path: dist/
|
|
96
|
+
- uses: pypa/gh-action-pypi-publish@v1.14.3
|
|
97
|
+
|
|
98
|
+
github-release:
|
|
99
|
+
needs: [build, publish]
|
|
100
|
+
if: ${{ !failure() && !cancelled() && needs.publish.result == 'success' }}
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
permissions:
|
|
103
|
+
contents: write
|
|
104
|
+
steps:
|
|
105
|
+
- uses: actions/download-artifact@v8
|
|
106
|
+
with:
|
|
107
|
+
name: dist
|
|
108
|
+
path: dist/
|
|
109
|
+
- name: Attach artifacts, creating the release for hand-pushed tags
|
|
110
|
+
run: |
|
|
111
|
+
gh release view "$TAG" >/dev/null 2>&1 || gh release create "$TAG" --verify-tag --generate-notes --title "$TAG"
|
|
112
|
+
gh release upload "$TAG" dist/* --clobber
|
|
113
|
+
env:
|
|
114
|
+
GH_TOKEN: ${{ github.token }}
|
|
115
|
+
GH_REPO: ${{ github.repository }}
|
|
116
|
+
TAG: ${{ needs.build.outputs.tag }}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI coding agents working in this repository. Humans should read [CONTRIBUTING.md](CONTRIBUTING.md), which this file follows.
|
|
4
|
+
|
|
5
|
+
## Project
|
|
6
|
+
|
|
7
|
+
`coding-agent-cli` is a stdlib-only Python 3.12+ library. It runs coding-agent CLIs (`claude`, `codex`, `pi`, `agy`) as subprocesses, streams typed events, and returns a classified `Result`.
|
|
8
|
+
|
|
9
|
+
## Layout
|
|
10
|
+
|
|
11
|
+
| Path | Contents |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `src/coding_agent_cli/api.py` | Public entry points: `run`, `stream`, `run_sync`, `check` |
|
|
14
|
+
| `src/coding_agent_cli/types.py`, `events.py` | Public frozen dataclasses |
|
|
15
|
+
| `src/coding_agent_cli/registry.py` | `Driver` protocol and `DriverRegistry` |
|
|
16
|
+
| `src/coding_agent_cli/_process.py`, `_platform.py` | Subprocess transport and process-tree kill |
|
|
17
|
+
| `src/coding_agent_cli/_args.py`, `_classify.py` | Argument validation and outcome classification |
|
|
18
|
+
| `src/coding_agent_cli/_drivers/` | Built-in drivers and shared `CliDriver` helpers |
|
|
19
|
+
| `tests/fixtures/fake_cli/` | Fake CLIs used by all unit tests |
|
|
20
|
+
| `docs/plans/coding-agent-cli/` | Design, plan, and phase journals |
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
Prefix uv commands with `export VIRTUAL_ENV=;` if a foreign virtualenv is active.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv sync
|
|
28
|
+
uv run ruff format && uv run ruff check --fix
|
|
29
|
+
uv run pyright
|
|
30
|
+
uv run pytest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
All four must pass before you finish. Do not run `pytest -m live` unless asked; it calls real CLIs and spends tokens.
|
|
34
|
+
|
|
35
|
+
## Hard rules
|
|
36
|
+
|
|
37
|
+
- Never add a runtime dependency.
|
|
38
|
+
- Never make a driver add a permission, approval, or sandbox-bypass flag.
|
|
39
|
+
- Never log prompts, argv, or environment values.
|
|
40
|
+
- Every exit path must kill the process tree and delete temp files.
|
|
41
|
+
- Reuse helpers in `_drivers/_common.py` and `_args.py` before writing new ones.
|
|
42
|
+
- Keep public signatures in sync with the README examples.
|
|
43
|
+
- Do not push, tag, or publish.
|
|
44
|
+
|
|
45
|
+
## Style
|
|
46
|
+
|
|
47
|
+
Follow the coding standard in [CONTRIBUTING.md](CONTRIBUTING.md#coding-standard). Match the surrounding code. Keep diffs minimal and add a test for every behavior change.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
First release. Extracted from the CLI-driver layer of Refract.
|
|
6
|
+
|
|
7
|
+
- `run`, `stream`, `run_sync`, and `check` entry points for running coding-agent CLIs from Python.
|
|
8
|
+
- Typed events with a strictly increasing `sequence`, ending with exactly one `RunCompleted`.
|
|
9
|
+
- A classified `Result` with `Outcome` and `Diagnostic`.
|
|
10
|
+
- Built-in drivers for `claude`, `pi`, `codex`, and `agy`, and a `DriverRegistry` for custom drivers.
|
|
11
|
+
- Process-tree cleanup on completion, cancel, timeout, and callback failure.
|
|
12
|
+
- No permission or approval flag is ever added; callers pass them through `args`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project adopts the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
|
4
|
+
|
|
5
|
+
## Our pledge
|
|
6
|
+
|
|
7
|
+
We pledge to make participation in this project a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
|
8
|
+
|
|
9
|
+
## Expected behavior
|
|
10
|
+
|
|
11
|
+
- Show empathy and kindness toward other people.
|
|
12
|
+
- Respect differing opinions, viewpoints, and experiences.
|
|
13
|
+
- Give and gracefully accept constructive feedback.
|
|
14
|
+
- Take responsibility for mistakes and learn from them.
|
|
15
|
+
|
|
16
|
+
## Unacceptable behavior
|
|
17
|
+
|
|
18
|
+
- Sexualized language or imagery, and sexual attention or advances of any kind.
|
|
19
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks.
|
|
20
|
+
- Public or private harassment.
|
|
21
|
+
- Publishing others' private information without their explicit permission.
|
|
22
|
+
- Other conduct that could reasonably be considered inappropriate in a professional setting.
|
|
23
|
+
|
|
24
|
+
## Reporting
|
|
25
|
+
|
|
26
|
+
Report unacceptable behavior to the maintainer, [@sitien173](https://github.com/sitien173), by private contact through GitHub. You can also use GitHub's [report content](https://docs.github.com/en/communities/maintaining-your-safety-on-github/reporting-abuse-or-spam) feature. Reports are reviewed promptly and kept confidential.
|
|
27
|
+
|
|
28
|
+
## Enforcement
|
|
29
|
+
|
|
30
|
+
The maintainer may remove, edit, or reject comments, commits, code, issues, and other contributions that violate this code, and may warn, suspend, or ban contributors. The full enforcement guidelines are in the [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/#enforcement-guidelines).
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve coding-agent-cli. This guide covers setup, the coding standard, and how changes get merged.
|
|
4
|
+
|
|
5
|
+
## Ground rules
|
|
6
|
+
|
|
7
|
+
- Be respectful. All participation follows the [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
8
|
+
- Report security problems privately. See [SECURITY.md](SECURITY.md). Do not open a public issue.
|
|
9
|
+
- Open an issue before a large change, so the design can be agreed first.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
You need Python 3.12 or later and [uv](https://docs.astral.sh/uv/).
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/sitien173/coding-agent-cli.git
|
|
17
|
+
cd coding-agent-cli
|
|
18
|
+
uv sync
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Checks
|
|
22
|
+
|
|
23
|
+
Every pull request must pass the same checks CI runs:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv run ruff format --check
|
|
27
|
+
uv run ruff check
|
|
28
|
+
uv run pyright
|
|
29
|
+
uv run pytest
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`uv run ruff format` and `uv run ruff check --fix` correct most style problems.
|
|
33
|
+
|
|
34
|
+
Live tests run the real CLIs and are excluded by default. Run them only with the CLIs installed and logged in:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv run pytest -m live -rP
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Coding standard
|
|
41
|
+
|
|
42
|
+
### Style
|
|
43
|
+
|
|
44
|
+
- Ruff formats and lints the code. The line length is 120. Configuration lives in `pyproject.toml`.
|
|
45
|
+
- Pyright checks types. New code is fully annotated, and `pyright` must report 0 errors.
|
|
46
|
+
- Write `from __future__ import annotations` at the top of each module.
|
|
47
|
+
- Public names are listed in `__all__`. Modules and names that start with `_` are private.
|
|
48
|
+
|
|
49
|
+
### Design rules
|
|
50
|
+
|
|
51
|
+
- **No runtime dependencies.** The library uses the standard library only.
|
|
52
|
+
- **No implicit permissions.** A driver never adds a permission, approval, or sandbox-bypass flag. Callers pass these through `Request.args`.
|
|
53
|
+
- **No leaked processes.** Every exit path kills the CLI's whole process tree: completion, cancel, timeout, and a raising callback.
|
|
54
|
+
- **No sensitive logging.** Never log prompts, argv, or environment values.
|
|
55
|
+
- **Typed, frozen values.** Requests, results, and events are frozen dataclasses. Unknown values are `None`, never zero.
|
|
56
|
+
- **One `RunCompleted`.** Each run emits exactly one, last, after the process tree is gone, with a strictly increasing `sequence`.
|
|
57
|
+
|
|
58
|
+
### Tests
|
|
59
|
+
|
|
60
|
+
- Every behavior change comes with a test. Write the failing test first when you can.
|
|
61
|
+
- Tests use the fake CLIs in `tests/fixtures/fake_cli`. Unit tests never call a real coding-agent CLI.
|
|
62
|
+
- A new driver needs argv tests proving it adds no permission flag for any option combination.
|
|
63
|
+
|
|
64
|
+
### Adding a driver
|
|
65
|
+
|
|
66
|
+
1. Subclass `CliDriver` in `src/coding_agent_cli/_drivers/`. Follow `claude.py` or `pi.py`.
|
|
67
|
+
2. Declare the driver-owned transport flags and the `portable_flags` it supports.
|
|
68
|
+
3. Register it in `_builtin_drivers()` in `registry.py`.
|
|
69
|
+
4. Add a driver test module, argv policy tests, and a row in each README table.
|
|
70
|
+
|
|
71
|
+
## Commits and pull requests
|
|
72
|
+
|
|
73
|
+
- Use [Conventional Commits](https://www.conventionalcommits.org/): `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `chore:`. Mark breaking changes with `!`, as in `feat!:`.
|
|
74
|
+
- Pull requests are squash-merged, so the PR title becomes the commit message. A check enforces the Conventional Commits format on PR titles.
|
|
75
|
+
- Keep each pull request to one change. Every changed line should trace to that change.
|
|
76
|
+
- Do not edit `CHANGELOG.md` or the version by hand. Both are generated from commit messages at release time.
|
|
77
|
+
- Fill in the pull request template.
|
|
78
|
+
|
|
79
|
+
## Releases
|
|
80
|
+
|
|
81
|
+
Releases are automated with [release-please](https://github.com/googleapis/release-please):
|
|
82
|
+
|
|
83
|
+
1. Each push to `main` updates an open release PR. It bumps the version in `pyproject.toml`, `__init__.py`, and `uv.lock`, and adds the changelog entry.
|
|
84
|
+
2. While the version is below 1.0, `feat:` bumps the minor version and `fix:` bumps the patch version. A breaking change also bumps the minor version.
|
|
85
|
+
3. A maintainer merges the release PR when ready. The workflow tags `vX.Y.Z`, creates the GitHub Release, tests, builds, publishes to PyPI through trusted publishing, and attaches the wheel and sdist to the release.
|
|
86
|
+
|
|
87
|
+
Publishing waits for approval on the `pypi` environment. Pushing a `vX.Y.Z` tag by hand runs the same build and publish; the tag must match the version in `pyproject.toml`.
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
By contributing, you agree that your contributions are licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sitien173
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|