agentic-coding-harness 0.7.1__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.
- agentic_coding_harness-0.7.1/.gitignore +6 -0
- agentic_coding_harness-0.7.1/PKG-INFO +61 -0
- agentic_coding_harness-0.7.1/README.md +33 -0
- agentic_coding_harness-0.7.1/pyproject.toml +53 -0
- agentic_coding_harness-0.7.1/src/agentic_coding_harness/__init__.py +10 -0
- agentic_coding_harness-0.7.1/src/agentic_coding_harness/_cli.py +126 -0
- agentic_coding_harness-0.7.1/src/agentic_coding_harness/_vendor/ach.mjs +4201 -0
- agentic_coding_harness-0.7.1/src/agentic_coding_harness/py.typed +0 -0
- agentic_coding_harness-0.7.1/tests/test_cli.py +65 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: agentic-coding-harness
|
|
3
|
+
Version: 0.7.1
|
|
4
|
+
Summary: Run, watch, and meter Claude Code, Codex CLI, Gemini CLI, OpenCode, and Kiro from one CLI — verified cost tracking, token usage, budget caps, OTel gen_ai spans, Langfuse traces, and a live dashboard + MCP server.
|
|
5
|
+
Project-URL: Homepage, https://github.com/sblattj/agentic-coding-harness
|
|
6
|
+
Project-URL: Repository, https://github.com/sblattj/agentic-coding-harness
|
|
7
|
+
Project-URL: Issues, https://github.com/sblattj/agentic-coding-harness/issues
|
|
8
|
+
Author: Stephen Blatt
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: agent-observability,ai-agents,claude-code,cli,codex-cli,coding-agent,cost-tracking,gemini-cli,kiro,langfuse,llm,mcp-server,opencode,opentelemetry,token-usage
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Software Development
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# agentic-coding-harness (Python wrapper)
|
|
30
|
+
|
|
31
|
+
[](https://pypi.org/project/agentic-coding-harness/)
|
|
32
|
+
|
|
33
|
+
Run, watch, and meter coding agents from the command line. This Python
|
|
34
|
+
package wraps the compiled `ach` CLI (vendored inside the wheel) and launches
|
|
35
|
+
it with whatever JavaScript runtime you have installed — Bun if available,
|
|
36
|
+
otherwise Node.js >= 18.19. No Python runtime dependencies; stdlib only.
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
# run without installing (the alias name matters for uvx)
|
|
40
|
+
uvx agentic-coding-harness --help
|
|
41
|
+
|
|
42
|
+
# or install
|
|
43
|
+
uv tool install agentic-coding-harness
|
|
44
|
+
ach --help
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Requirements
|
|
48
|
+
|
|
49
|
+
- Python 3.9+
|
|
50
|
+
- Bun or Node.js >= 18.19 on your PATH (or in the usual install dirs), or set
|
|
51
|
+
`AGENTIC_CODING_HARNESS_RUNTIME=/path/to/runtime` to force one.
|
|
52
|
+
|
|
53
|
+
## What it does
|
|
54
|
+
|
|
55
|
+
The console scripts `ach` and `agentic-coding-harness` both locate a JS
|
|
56
|
+
runtime, then `exec` the vendored `ach.mjs` bundle with full argument, stdio,
|
|
57
|
+
signal, and exit-code passthrough. If no runtime is found they print install
|
|
58
|
+
instructions and exit 127.
|
|
59
|
+
|
|
60
|
+
See the [project README](https://github.com/sblattj/agentic-coding-harness)
|
|
61
|
+
for the full `ach` CLI documentation.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# agentic-coding-harness (Python wrapper)
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/agentic-coding-harness/)
|
|
4
|
+
|
|
5
|
+
Run, watch, and meter coding agents from the command line. This Python
|
|
6
|
+
package wraps the compiled `ach` CLI (vendored inside the wheel) and launches
|
|
7
|
+
it with whatever JavaScript runtime you have installed — Bun if available,
|
|
8
|
+
otherwise Node.js >= 18.19. No Python runtime dependencies; stdlib only.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
# run without installing (the alias name matters for uvx)
|
|
12
|
+
uvx agentic-coding-harness --help
|
|
13
|
+
|
|
14
|
+
# or install
|
|
15
|
+
uv tool install agentic-coding-harness
|
|
16
|
+
ach --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
|
|
21
|
+
- Python 3.9+
|
|
22
|
+
- Bun or Node.js >= 18.19 on your PATH (or in the usual install dirs), or set
|
|
23
|
+
`AGENTIC_CODING_HARNESS_RUNTIME=/path/to/runtime` to force one.
|
|
24
|
+
|
|
25
|
+
## What it does
|
|
26
|
+
|
|
27
|
+
The console scripts `ach` and `agentic-coding-harness` both locate a JS
|
|
28
|
+
runtime, then `exec` the vendored `ach.mjs` bundle with full argument, stdio,
|
|
29
|
+
signal, and exit-code passthrough. If no runtime is found they print install
|
|
30
|
+
instructions and exit 127.
|
|
31
|
+
|
|
32
|
+
See the [project README](https://github.com/sblattj/agentic-coding-harness)
|
|
33
|
+
for the full `ach` CLI documentation.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agentic-coding-harness"
|
|
7
|
+
version = "0.7.1"
|
|
8
|
+
description = "Run, watch, and meter Claude Code, Codex CLI, Gemini CLI, OpenCode, and Kiro from one CLI — verified cost tracking, token usage, budget caps, OTel gen_ai spans, Langfuse traces, and a live dashboard + MCP server."
|
|
9
|
+
keywords = ["claude-code", "codex-cli", "gemini-cli", "opencode", "kiro", "coding-agent", "agent-observability", "cost-tracking", "token-usage", "opentelemetry", "langfuse", "mcp-server", "llm", "ai-agents", "cli"]
|
|
10
|
+
authors = [{ name = "Stephen Blatt" }]
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.9"
|
|
14
|
+
dependencies = []
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Operating System :: MacOS",
|
|
21
|
+
"Operating System :: POSIX :: Linux",
|
|
22
|
+
"Operating System :: Microsoft :: Windows",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.9",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Topic :: Software Development",
|
|
30
|
+
"Typing :: Typed",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/sblattj/agentic-coding-harness"
|
|
35
|
+
Repository = "https://github.com/sblattj/agentic-coding-harness"
|
|
36
|
+
Issues = "https://github.com/sblattj/agentic-coding-harness/issues"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
ach = "agentic_coding_harness._cli:main"
|
|
40
|
+
agentic-coding-harness = "agentic_coding_harness._cli:main"
|
|
41
|
+
|
|
42
|
+
[tool.hatch.build.targets.wheel]
|
|
43
|
+
packages = ["src/agentic_coding_harness"]
|
|
44
|
+
artifacts = ["src/agentic_coding_harness/_vendor/ach.mjs"]
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.sdist]
|
|
47
|
+
include = [
|
|
48
|
+
"src/agentic_coding_harness",
|
|
49
|
+
"tests",
|
|
50
|
+
"README.md",
|
|
51
|
+
"pyproject.toml",
|
|
52
|
+
]
|
|
53
|
+
artifacts = ["src/agentic_coding_harness/_vendor/ach.mjs"]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""agentic-coding-harness: run/watch/meter coding agents.
|
|
2
|
+
|
|
3
|
+
Python wrapper that locates a JavaScript runtime (Bun preferred, then
|
|
4
|
+
Node.js >= 18.19) and execs the vendored ach.mjs CLI bundle with full
|
|
5
|
+
argument passthrough.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "0.7.1"
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Console-script entry point: locate a JS runtime and exec the vendored ach.mjs.
|
|
2
|
+
|
|
3
|
+
Stdlib only. Prefers Bun, then Node >= 18.19. The runtime may be forced via
|
|
4
|
+
the AGENTIC_CODING_HARNESS_RUNTIME environment variable. On POSIX we execv so
|
|
5
|
+
stdio, signals, and exit codes pass through untouched; on Windows we fall back
|
|
6
|
+
to subprocess.call.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
_PACKAGE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
17
|
+
_BUNDLE = os.path.join(_PACKAGE_DIR, "_vendor", "ach.mjs")
|
|
18
|
+
_RUNTIME_ENV = "AGENTIC_CODING_HARNESS_RUNTIME"
|
|
19
|
+
|
|
20
|
+
_COMMON_DIRS = (
|
|
21
|
+
"/opt/homebrew/bin",
|
|
22
|
+
"/usr/local/bin",
|
|
23
|
+
os.path.expanduser("~/.bun/bin"),
|
|
24
|
+
os.path.expanduser("~/.volta/bin"),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
_MISSING_RUNTIME_MESSAGE = """ach: no JavaScript runtime found.
|
|
28
|
+
|
|
29
|
+
agentic-coding-harness needs Bun or Node.js (>= 18.19) to run.
|
|
30
|
+
|
|
31
|
+
Install one of:
|
|
32
|
+
curl -fsSL https://bun.sh/install | bash # Bun (recommended)
|
|
33
|
+
https://nodejs.org/en/download # Node.js >= 18.19
|
|
34
|
+
|
|
35
|
+
Or point {env} at an existing runtime binary, e.g.:
|
|
36
|
+
export {env}=/usr/local/bin/node
|
|
37
|
+
""".format(env=_RUNTIME_ENV)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _candidate_paths(name: str):
|
|
41
|
+
found = shutil.which(name)
|
|
42
|
+
if found:
|
|
43
|
+
yield found
|
|
44
|
+
seen = {found} if found else set()
|
|
45
|
+
for directory in _COMMON_DIRS:
|
|
46
|
+
candidate = os.path.join(directory, name)
|
|
47
|
+
if candidate not in seen and os.path.isfile(candidate) and os.access(candidate, os.X_OK):
|
|
48
|
+
seen.add(candidate)
|
|
49
|
+
yield candidate
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _node_major_minor(path: str):
|
|
53
|
+
"""Return (major, minor) for a node binary, or None if it can't be probed."""
|
|
54
|
+
try:
|
|
55
|
+
out = subprocess.run(
|
|
56
|
+
[path, "--version"],
|
|
57
|
+
capture_output=True,
|
|
58
|
+
text=True,
|
|
59
|
+
timeout=10,
|
|
60
|
+
check=False,
|
|
61
|
+
)
|
|
62
|
+
except (OSError, subprocess.SubprocessError):
|
|
63
|
+
return None
|
|
64
|
+
version = (out.stdout or "").strip().lstrip("v")
|
|
65
|
+
if not version:
|
|
66
|
+
return None
|
|
67
|
+
parts = version.split(".")
|
|
68
|
+
try:
|
|
69
|
+
return int(parts[0]), int(parts[1])
|
|
70
|
+
except (ValueError, IndexError):
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def find_runtime(env=None):
|
|
75
|
+
"""Return the path to a usable JS runtime, or None.
|
|
76
|
+
|
|
77
|
+
Honors AGENTIC_CODING_HARNESS_RUNTIME when set.
|
|
78
|
+
"""
|
|
79
|
+
environ = env if env is not None else os.environ
|
|
80
|
+
override = environ.get(_RUNTIME_ENV)
|
|
81
|
+
if override:
|
|
82
|
+
if os.path.isfile(override) and os.access(override, os.X_OK):
|
|
83
|
+
return override
|
|
84
|
+
resolved = shutil.which(override)
|
|
85
|
+
if resolved:
|
|
86
|
+
return resolved
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
for bun in _candidate_paths("bun"):
|
|
90
|
+
return bun
|
|
91
|
+
|
|
92
|
+
for node in _candidate_paths("node"):
|
|
93
|
+
version = _node_major_minor(node)
|
|
94
|
+
if version is None:
|
|
95
|
+
# Unprobeable (e.g. broken install) - skip rather than fail hard.
|
|
96
|
+
continue
|
|
97
|
+
major, minor = version
|
|
98
|
+
if (major, minor) >= (18, 19):
|
|
99
|
+
return node
|
|
100
|
+
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main(argv=None):
|
|
105
|
+
runtime = find_runtime()
|
|
106
|
+
if runtime is None:
|
|
107
|
+
sys.stderr.write(_MISSING_RUNTIME_MESSAGE)
|
|
108
|
+
return 127
|
|
109
|
+
if not os.path.isfile(_BUNDLE):
|
|
110
|
+
sys.stderr.write(
|
|
111
|
+
"ach: vendored bundle missing ({}). The install is broken; "
|
|
112
|
+
"reinstall agentic-coding-harness.\n".format(_BUNDLE)
|
|
113
|
+
)
|
|
114
|
+
return 127
|
|
115
|
+
|
|
116
|
+
args = list(sys.argv[1:] if argv is None else argv)
|
|
117
|
+
|
|
118
|
+
if os.name == "posix":
|
|
119
|
+
os.execv(runtime, [runtime, _BUNDLE] + args) # never returns
|
|
120
|
+
return 127 # pragma: no cover - execv failed to replace us
|
|
121
|
+
|
|
122
|
+
return subprocess.call([runtime, _BUNDLE] + args)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
sys.exit(main())
|