arga-cli 0.1.0__py3-none-any.whl

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.
arga_cli/mcp.py ADDED
@@ -0,0 +1,125 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from collections.abc import Callable
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+
8
+ SERVER_NAME = "arga-context"
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class McpTarget:
13
+ key: str
14
+ label: str
15
+ config_path: Path
16
+
17
+
18
+ def get_targets(home: Path | None = None) -> list[McpTarget]:
19
+ home = home or Path.home()
20
+ return [
21
+ McpTarget("cursor", "Cursor", home / ".cursor" / "mcp.json"),
22
+ McpTarget("claude", "Claude Code", home / ".claude" / "mcp.json"),
23
+ McpTarget("codex", "Codex CLI", home / ".config" / "codex" / "mcp.json"),
24
+ ]
25
+
26
+
27
+ def build_mcp_config(api_url: str, api_key: str) -> dict[str, object]:
28
+ return {
29
+ "mcpServers": {
30
+ SERVER_NAME: {
31
+ "url": f"{api_url.rstrip('/')}/mcp",
32
+ "headers": {
33
+ "Authorization": f"Bearer {api_key}",
34
+ },
35
+ }
36
+ }
37
+ }
38
+
39
+
40
+ def detect_installed_targets(home: Path | None = None) -> list[McpTarget]:
41
+ detected: list[McpTarget] = []
42
+ for target in get_targets(home):
43
+ if target.config_path.exists() or target.config_path.parent.exists():
44
+ detected.append(target)
45
+ return detected
46
+
47
+
48
+ def load_existing_config(config_path: Path) -> dict[str, object]:
49
+ if not config_path.exists():
50
+ return {}
51
+
52
+ try:
53
+ data = json.loads(config_path.read_text())
54
+ except json.JSONDecodeError as exc:
55
+ raise ValueError(f"Invalid JSON in {config_path}") from exc
56
+
57
+ if not isinstance(data, dict):
58
+ raise ValueError(f"Expected top-level object in {config_path}")
59
+ return data
60
+
61
+
62
+ def merge_mcp_config(existing: dict[str, object], mcp_config: dict[str, object]) -> dict[str, object]:
63
+ merged = dict(existing)
64
+ existing_servers = merged.get("mcpServers")
65
+ if existing_servers is None:
66
+ merged_servers: dict[str, object] = {}
67
+ elif isinstance(existing_servers, dict):
68
+ merged_servers = dict(existing_servers)
69
+ else:
70
+ raise ValueError("Expected `mcpServers` to be an object")
71
+
72
+ new_servers = mcp_config.get("mcpServers")
73
+ if not isinstance(new_servers, dict):
74
+ raise ValueError("Generated MCP config is invalid")
75
+
76
+ merged_servers.update(new_servers)
77
+ merged["mcpServers"] = merged_servers
78
+ return merged
79
+
80
+
81
+ def write_mcp_config(config_path: Path, config: dict[str, object]) -> None:
82
+ config_path.parent.mkdir(parents=True, exist_ok=True)
83
+ payload = json.dumps(config, indent=2) + "\n"
84
+ temp_path = config_path.with_suffix(f"{config_path.suffix}.tmp")
85
+ temp_path.write_text(payload)
86
+ temp_path.replace(config_path)
87
+
88
+
89
+ def install_mcp_configuration(
90
+ *,
91
+ api_url: str,
92
+ api_key: str,
93
+ home: Path | None = None,
94
+ echo: Callable[[str], None] = print,
95
+ ) -> tuple[int, int]:
96
+ detected = detect_installed_targets(home)
97
+
98
+ echo("Detected:")
99
+ if not detected:
100
+ echo("No supported IDE agents detected.")
101
+ return 0, 0
102
+
103
+ for target in detected:
104
+ echo(f"✓ {target.label}")
105
+
106
+ echo("")
107
+ echo("Installing MCP configuration...")
108
+ echo("")
109
+
110
+ installed = 0
111
+ failures = 0
112
+ generated_config = build_mcp_config(api_url, api_key)
113
+
114
+ for target in detected:
115
+ try:
116
+ existing = load_existing_config(target.config_path)
117
+ merged = merge_mcp_config(existing, generated_config)
118
+ write_mcp_config(target.config_path, merged)
119
+ echo(f"✓ {target.label} configured")
120
+ installed += 1
121
+ except ValueError as exc:
122
+ echo(f"✗ {target.label} not configured: {exc}")
123
+ failures += 1
124
+
125
+ return installed, failures
@@ -0,0 +1,298 @@
1
+ Metadata-Version: 2.4
2
+ Name: arga-cli
3
+ Version: 0.1.0
4
+ Summary: Command-line interface for Arga authentication, MCP installation, and browser validation
5
+ Author: Arga Labs
6
+ Project-URL: Homepage, https://github.com/ArgaLabs/arga-cli
7
+ Project-URL: Repository, https://github.com/ArgaLabs/arga-cli
8
+ Project-URL: Issues, https://github.com/ArgaLabs/arga-cli/issues
9
+ Keywords: arga,cli,mcp,developer-tools,validation
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: httpx>=0.27.0
20
+
21
+ # Arga CLI
22
+
23
+ `arga` is the command-line interface for authenticating with Arga, installing MCP configuration into supported coding agents, and starting validation runs against deployed apps or pull requests.
24
+
25
+ ## What It Does
26
+
27
+ - Authenticates your machine with Arga using the device login flow.
28
+ - Stores a device-scoped API key locally so each terminal/device can be revoked independently.
29
+ - Shows the currently authenticated user and workspace.
30
+ - Installs MCP configuration into supported local agents.
31
+ - Starts URL validation runs from the terminal.
32
+ - Starts pull request validation runs from the terminal.
33
+ - Wraps `git commit` and `git push` with Arga skip-validation helpers.
34
+ - Starts and inspects Arga app scans.
35
+
36
+ ## Installation
37
+
38
+ Once published to PyPI:
39
+
40
+ ```bash
41
+ uv tool install arga-cli
42
+ ```
43
+
44
+ You can also install it with `pipx` or `pip`:
45
+
46
+ ```bash
47
+ pipx install arga-cli
48
+ pip install arga-cli
49
+ ```
50
+
51
+ After installation, the executable is:
52
+
53
+ ```bash
54
+ arga --help
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ Authenticate:
60
+
61
+ ```bash
62
+ arga login
63
+ arga whoami
64
+ ```
65
+
66
+ Remove the saved device credential:
67
+
68
+ ```bash
69
+ arga logout
70
+ ```
71
+
72
+ Install MCP configuration for detected agents:
73
+
74
+ ```bash
75
+ arga mcp install
76
+ ```
77
+
78
+ Start a browser validation run:
79
+
80
+ ```bash
81
+ arga test url --url https://demo-app.com --prompt "test the login flow"
82
+ ```
83
+
84
+ Start a pull request validation run:
85
+
86
+ ```bash
87
+ arga validate pr --repo arga-labs/validation-server --pr 182
88
+ ```
89
+
90
+ Create a commit that skips Arga validation:
91
+
92
+ ```bash
93
+ arga commit -m "docs: update examples" --skip
94
+ arga push --skip
95
+ ```
96
+
97
+ Inspect or update automatic validation settings:
98
+
99
+ ```bash
100
+ arga validate install arga-labs/validation-server
101
+ arga validate config arga-labs/validation-server
102
+ arga validate config set arga-labs/validation-server --trigger branch --branch main --comments on
103
+ ```
104
+
105
+ Start an app scan and inspect it later:
106
+
107
+ ```bash
108
+ arga scan https://demo-app.com --budget 200
109
+ arga scan status <run_id>
110
+ arga scan report <run_id>
111
+ ```
112
+
113
+ List and inspect recent validation runs:
114
+
115
+ ```bash
116
+ arga runs list --repo arga-labs/validation-server --limit 20
117
+ arga runs status <run_id>
118
+ arga runs cancel <run_id>
119
+ ```
120
+
121
+ `arga validate url` is also available and currently behaves the same as `arga test url`:
122
+
123
+ ```bash
124
+ arga validate url --url https://demo-app.com --prompt "test checkout"
125
+ ```
126
+
127
+ ## Command Reference
128
+
129
+ ### Authentication
130
+
131
+ ```bash
132
+ arga login
133
+ arga whoami
134
+ arga logout
135
+ ```
136
+
137
+ - `arga login` opens the browser to complete Arga's device authorization flow.
138
+ - `arga whoami` verifies the saved API key and prints the GitHub login plus workspace.
139
+ - `arga logout` removes the local credential and attempts to revoke the current device on the server.
140
+
141
+ ### Validation
142
+
143
+ ```bash
144
+ arga test url --url https://demo-app.com --prompt "test login flow"
145
+ arga validate url --url https://demo-app.com --prompt "test checkout"
146
+ arga validate pr --repo arga-labs/validation-server --pr 182
147
+ arga validate install arga-labs/validation-server
148
+ arga validate config arga-labs/validation-server
149
+ arga validate config set arga-labs/validation-server --trigger branch --branch main --comments on
150
+ ```
151
+
152
+ - `arga test url` starts a one-off validation against a deployed URL.
153
+ - `arga validate url` is an equivalent URL-validation entry point under the `validate` namespace.
154
+ - `arga validate pr` starts GitHub-backed PR validation for a repository and pull request number.
155
+ - `arga validate install <repo>` installs the GitHub webhook for automatic validation on a repository.
156
+ - `arga validate config <repo>` shows the current automatic validation settings, including install state, trigger mode, selected branch, and PR comment behavior.
157
+ - `arga validate config set <repo>` updates the automatic validation settings. Any omitted options keep their current value.
158
+
159
+ For URL validation, you can optionally provide credentials:
160
+
161
+ ```bash
162
+ arga test url \
163
+ --url https://demo-app.com \
164
+ --prompt "log in and create an order" \
165
+ --email test@company.com \
166
+ --password supersecret
167
+ ```
168
+
169
+ Both `--email` and `--password` must be supplied together.
170
+
171
+ ### App Scans
172
+
173
+ ```bash
174
+ arga scan https://demo-app.com --budget 200
175
+ arga scan status <run_id>
176
+ arga scan report <run_id>
177
+ ```
178
+
179
+ - `arga scan <url>` starts an app scan, waits for the generated scan plan to be ready, and auto-approves it so execution can begin.
180
+ - `--budget` controls the red-team action budget and defaults to `200`.
181
+ - `arga scan status <run_id>` prints the current run status and anomaly count.
182
+ - `arga scan report <run_id>` prints the final JSON report once the scan has completed.
183
+
184
+ ### Validation Runs
185
+
186
+ ```bash
187
+ arga runs list --repo arga-labs/validation-server --status running --limit 20
188
+ arga runs status <run_id>
189
+ arga runs cancel <run_id>
190
+ ```
191
+
192
+ - `arga runs list` shows recent PR and branch validation runs in table form.
193
+ - `--repo` narrows the list to a single repository.
194
+ - `--status` accepts `completed`, `failed`, or `running`. The `running` filter includes non-terminal states such as `queued`.
195
+ - `arga runs status <run_id>` prints a detailed summary for a specific run.
196
+ - `arga runs cancel <run_id>` cancels the run through the validation API.
197
+
198
+ ### Git Wrappers
199
+
200
+ ```bash
201
+ arga commit -m "docs: update examples" --skip
202
+ arga push --skip
203
+ ```
204
+
205
+ - `arga commit` delegates to `git commit`.
206
+ - `arga commit --skip` appends a final `[skip arga]` paragraph to the commit message so Arga skips validation for that head commit.
207
+ - `arga push` delegates to `git push`.
208
+ - `arga push --skip` verifies the current `HEAD` commit already contains `[skip arga]` before pushing. This is safest when the commit was created with `arga commit --skip`.
209
+
210
+ ## Supported MCP Targets
211
+
212
+ `arga mcp install` writes or updates MCP configuration for supported agents when they are detected locally:
213
+
214
+ - `~/.cursor/mcp.json`
215
+ - `~/.claude/mcp.json`
216
+ - `~/.config/codex/mcp.json`
217
+
218
+ The installed server is named `arga-context` and points to:
219
+
220
+ ```text
221
+ <api-url>/mcp
222
+ ```
223
+
224
+ using an `Authorization: Bearer <api_key>` header generated from your saved CLI login.
225
+
226
+ ## MCP Installation
227
+
228
+ Install or update MCP config after you have logged in:
229
+
230
+ ```bash
231
+ arga login
232
+ arga mcp install
233
+ ```
234
+
235
+ The installer:
236
+
237
+ - Detects supported local agent config directories.
238
+ - Preserves existing `mcpServers` entries.
239
+ - Merges in the generated `arga-context` server definition.
240
+ - Returns a non-zero exit code if no supported targets are detected or if any target cannot be updated.
241
+
242
+ If you need to add the server manually, the generated config looks like:
243
+
244
+ ```json
245
+ {
246
+ "mcpServers": {
247
+ "arga-context": {
248
+ "url": "https://api.argalabs.com/mcp",
249
+ "headers": {
250
+ "Authorization": "Bearer <your-api-key>"
251
+ }
252
+ }
253
+ }
254
+ }
255
+ ```
256
+
257
+ ## Using A Custom API URL
258
+
259
+ By default, the CLI targets `https://api.argalabs.com`.
260
+
261
+ To point it at another environment, pass `--api-url` or set `ARGA_API_URL`:
262
+
263
+ ```bash
264
+ arga login --api-url http://localhost:8000
265
+ arga mcp install --api-url http://localhost:8000
266
+ arga test url --api-url http://localhost:8000 --url https://demo-app.com --prompt "test checkout"
267
+ arga validate url --api-url http://localhost:8000 --url https://demo-app.com --prompt "test checkout"
268
+ arga validate pr --api-url http://localhost:8000 --repo arga-labs/validation-server --pr 182
269
+ ```
270
+
271
+ ```bash
272
+ export ARGA_API_URL=http://localhost:8000
273
+ arga login
274
+ ```
275
+
276
+ ## Local Development
277
+
278
+ ```bash
279
+ uv sync
280
+ uv run pytest
281
+ uv run arga --help
282
+ ```
283
+
284
+ To install the current checkout as a shell command:
285
+
286
+ ```bash
287
+ uv tool install -e .
288
+ ```
289
+
290
+ ## Config Storage
291
+
292
+ The CLI stores its local auth state in:
293
+
294
+ ```bash
295
+ ~/.config/arga/config.json
296
+ ```
297
+
298
+ That file contains the saved API key plus device metadata returned during `arga login`.
@@ -0,0 +1,8 @@
1
+ arga_cli/__init__.py,sha256=LAW9JWDNyNyHSyGOE1kdkqHVEKIH96pyAId4nXElvEY,24
2
+ arga_cli/main.py,sha256=SkdAcx7n6-2L84FP_GTaVL3YjuJVhk6LthgdcfAIT60,39472
3
+ arga_cli/mcp.py,sha256=W9OZbI_SjQARJR2bd2vz-0V0vzjTfqsKD1tZc0myR6s,3653
4
+ arga_cli-0.1.0.dist-info/METADATA,sha256=P6DZ2JbUOEAc7AaENBy-zrbUAXKF5aXYz_y36iQQ1is,8386
5
+ arga_cli-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
6
+ arga_cli-0.1.0.dist-info/entry_points.txt,sha256=oBp8vAj2Cot6llfpaf0ovJJ12jdNLpjaiZYxUnVvb4c,44
7
+ arga_cli-0.1.0.dist-info/top_level.txt,sha256=ud5gQ95maAJ777TDrNnf4lMiYaikKV3xCsNEgbU5pjU,9
8
+ arga_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ arga = arga_cli.main:main
@@ -0,0 +1 @@
1
+ arga_cli