click-agentcli 0.1.0__tar.gz → 0.3.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.
Files changed (21) hide show
  1. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/.github/workflows/ci.yml +1 -1
  2. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/PKG-INFO +94 -4
  3. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/README.md +91 -1
  4. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/pyproject.toml +3 -3
  5. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/candidates.py +0 -2
  6. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/candidates_test.py +0 -2
  7. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/exits.py +0 -2
  8. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/exits_test.py +0 -2
  9. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/group.py +0 -2
  10. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/group_test.py +0 -2
  11. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/guide.py +0 -2
  12. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/guide_test.py +0 -2
  13. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/output.py +0 -2
  14. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/output_test.py +0 -2
  15. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/skill.py +0 -2
  16. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/skill_test.py +0 -2
  17. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/uv.lock +2 -2
  18. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/.github/workflows/release.yml +0 -0
  19. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/.gitignore +0 -0
  20. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/LICENSE +0 -0
  21. {click_agentcli-0.1.0 → click_agentcli-0.3.0}/src/agentcli/__init__.py +0 -0
@@ -13,7 +13,7 @@ jobs:
13
13
  strategy:
14
14
  fail-fast: false
15
15
  matrix:
16
- python-version: ["3.11", "3.12", "3.13"]
16
+ python-version: ["3.12", "3.13", "3.14"]
17
17
 
18
18
  steps:
19
19
  - uses: actions/checkout@v7
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: click-agentcli
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Shared CLI conventions for agent-facing tools: exit codes, JSON output, skill installation, and the in-binary guide.
5
5
  Project-URL: Homepage, https://github.com/owahltinez/click-agentcli
6
6
  Author: owahltinez
@@ -13,12 +13,12 @@ Classifier: Intended Audience :: Developers
13
13
  Classifier: License :: OSI Approved :: MIT License
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
19
  Classifier: Topic :: Software Development :: Libraries
20
20
  Classifier: Topic :: Utilities
21
- Requires-Python: >=3.11
21
+ Requires-Python: >=3.12
22
22
  Requires-Dist: click>=8.1
23
23
  Description-Content-Type: text/markdown
24
24
 
@@ -28,7 +28,97 @@ Shared conventions for command-line tools whose primary callers are agents.
28
28
  It owns no food domain: it owns predictable errors, JSON output, skills,
29
29
  in-binary guides, and the candidate record used for composition.
30
30
 
31
- ## Install and test
31
+ ## Use it in a package
32
+
33
+ Install the distribution (the import name remains `agentcli`):
34
+
35
+ ```sh
36
+ uv add click-agentcli
37
+ ```
38
+
39
+ Register the shared output, guide, and skill commands on a Click CLI:
40
+
41
+ ```python
42
+ import click
43
+
44
+ from agentcli import (
45
+ JsonAwareGroup,
46
+ emit,
47
+ guide_command,
48
+ json_option,
49
+ skill_group,
50
+ )
51
+
52
+ GUIDE = """# acme guide
53
+
54
+ Use `acme hello` to print a greeting.
55
+ """
56
+
57
+
58
+ @click.group(cls=JsonAwareGroup)
59
+ def cli() -> None:
60
+ """Acme's agent-facing CLI."""
61
+
62
+
63
+ @cli.command()
64
+ @json_option
65
+ def hello(json_output: bool) -> None:
66
+ """Print a greeting."""
67
+ emit(
68
+ {"message": "hello"},
69
+ json_output=json_output,
70
+ human=lambda result: [result["message"]],
71
+ )
72
+
73
+
74
+ cli.add_command(guide_command(GUIDE))
75
+ cli.add_command(skill_group(name="acme", package="acme"))
76
+ ```
77
+
78
+ The command has readable output for people and one stable document for agents:
79
+
80
+ ```console
81
+ $ acme hello
82
+ hello
83
+ $ acme hello --json
84
+ {"ok":true,"data":{"message":"hello"}}
85
+ $ acme guide
86
+ # acme guide
87
+ ...
88
+ $ acme skill install
89
+ copied /home/me/.agents/skills/acme
90
+ ```
91
+
92
+ Declare the entry point and ship the skill inside the import package. For
93
+ Hatchling, a project-root `SKILL.md` can be mapped into the required wheel
94
+ location like this:
95
+
96
+ ```toml
97
+ [project.scripts]
98
+ acme = "acme.cli:cli"
99
+
100
+ [tool.hatch.build.targets.wheel.force-include]
101
+ "SKILL.md" = "acme/skills/acme/SKILL.md"
102
+ ```
103
+
104
+ `skill_group(name="acme", package="acme")` expects an installed wheel to
105
+ contain `acme/skills/acme/SKILL.md`. The same file may stay at the repository
106
+ root for source-checkout use. Its frontmatter name must match the skill name:
107
+
108
+ ```markdown
109
+ ---
110
+ name: acme
111
+ description: Use Acme from an agent.
112
+ ---
113
+
114
+ Run `acme guide` for the complete manual.
115
+ ```
116
+
117
+ Add `@json_option` to each command that supports structured output and call
118
+ `emit` once with both the data and its human renderer. `JsonAwareGroup` then
119
+ keeps parse failures structured when `--json` was requested.
120
+
121
+ ## Develop this package
32
122
 
33
123
  ```sh
34
124
  uv sync --project .
@@ -4,7 +4,97 @@ Shared conventions for command-line tools whose primary callers are agents.
4
4
  It owns no food domain: it owns predictable errors, JSON output, skills,
5
5
  in-binary guides, and the candidate record used for composition.
6
6
 
7
- ## Install and test
7
+ ## Use it in a package
8
+
9
+ Install the distribution (the import name remains `agentcli`):
10
+
11
+ ```sh
12
+ uv add click-agentcli
13
+ ```
14
+
15
+ Register the shared output, guide, and skill commands on a Click CLI:
16
+
17
+ ```python
18
+ import click
19
+
20
+ from agentcli import (
21
+ JsonAwareGroup,
22
+ emit,
23
+ guide_command,
24
+ json_option,
25
+ skill_group,
26
+ )
27
+
28
+ GUIDE = """# acme guide
29
+
30
+ Use `acme hello` to print a greeting.
31
+ """
32
+
33
+
34
+ @click.group(cls=JsonAwareGroup)
35
+ def cli() -> None:
36
+ """Acme's agent-facing CLI."""
37
+
38
+
39
+ @cli.command()
40
+ @json_option
41
+ def hello(json_output: bool) -> None:
42
+ """Print a greeting."""
43
+ emit(
44
+ {"message": "hello"},
45
+ json_output=json_output,
46
+ human=lambda result: [result["message"]],
47
+ )
48
+
49
+
50
+ cli.add_command(guide_command(GUIDE))
51
+ cli.add_command(skill_group(name="acme", package="acme"))
52
+ ```
53
+
54
+ The command has readable output for people and one stable document for agents:
55
+
56
+ ```console
57
+ $ acme hello
58
+ hello
59
+ $ acme hello --json
60
+ {"ok":true,"data":{"message":"hello"}}
61
+ $ acme guide
62
+ # acme guide
63
+ ...
64
+ $ acme skill install
65
+ copied /home/me/.agents/skills/acme
66
+ ```
67
+
68
+ Declare the entry point and ship the skill inside the import package. For
69
+ Hatchling, a project-root `SKILL.md` can be mapped into the required wheel
70
+ location like this:
71
+
72
+ ```toml
73
+ [project.scripts]
74
+ acme = "acme.cli:cli"
75
+
76
+ [tool.hatch.build.targets.wheel.force-include]
77
+ "SKILL.md" = "acme/skills/acme/SKILL.md"
78
+ ```
79
+
80
+ `skill_group(name="acme", package="acme")` expects an installed wheel to
81
+ contain `acme/skills/acme/SKILL.md`. The same file may stay at the repository
82
+ root for source-checkout use. Its frontmatter name must match the skill name:
83
+
84
+ ```markdown
85
+ ---
86
+ name: acme
87
+ description: Use Acme from an agent.
88
+ ---
89
+
90
+ Run `acme guide` for the complete manual.
91
+ ```
92
+
93
+ Add `@json_option` to each command that supports structured output and call
94
+ `emit` once with both the data and its human renderer. `JsonAwareGroup` then
95
+ keeps parse failures structured when `--json` was requested.
96
+
97
+ ## Develop this package
8
98
 
9
99
  ```sh
10
100
  uv sync --project .
@@ -10,10 +10,10 @@ build-backend = "hatchling.build"
10
10
  # Dependents must name the distribution, not the import, in both their
11
11
  # dependencies and their [tool.uv.sources] key.
12
12
  name = "click-agentcli"
13
- version = "0.1.0"
13
+ version = "0.3.0"
14
14
  description = "Shared CLI conventions for agent-facing tools: exit codes, JSON output, skill installation, and the in-binary guide."
15
15
  readme = "README.md"
16
- requires-python = ">=3.11"
16
+ requires-python = ">=3.12"
17
17
  license = "MIT"
18
18
  authors = [{ name = "owahltinez" }]
19
19
  keywords = ["click", "cli", "agent", "skill", "json"]
@@ -24,9 +24,9 @@ classifiers = [
24
24
  "License :: OSI Approved :: MIT License",
25
25
  "Operating System :: OS Independent",
26
26
  "Programming Language :: Python :: 3",
27
- "Programming Language :: Python :: 3.11",
28
27
  "Programming Language :: Python :: 3.12",
29
28
  "Programming Language :: Python :: 3.13",
29
+ "Programming Language :: Python :: 3.14",
30
30
  "Topic :: Software Development :: Libraries",
31
31
  "Topic :: Utilities",
32
32
  ]
@@ -11,8 +11,6 @@ ranks, instead of special-casing each tool. Everything kind-specific goes under
11
11
  `detail`, which nothing shared ever reads.
12
12
  """
13
13
 
14
- from __future__ import annotations
15
-
16
14
  from collections.abc import Callable
17
15
  from typing import Any
18
16
 
@@ -1,7 +1,5 @@
1
1
  """The contract two independent tools have to agree on without talking."""
2
2
 
3
- from __future__ import annotations
4
-
5
3
  import itertools
6
4
 
7
5
  import click
@@ -10,8 +10,6 @@
10
10
  with a nonzero status; only the code differs per class.
11
11
  """
12
12
 
13
- from __future__ import annotations
14
-
15
13
  import click
16
14
 
17
15
  # Click exits 2 for its own parse failures, which this table documents as a
@@ -1,7 +1,5 @@
1
1
  """Exit codes are the contract an agent reads instead of prose."""
2
2
 
3
- from __future__ import annotations
4
-
5
3
  import click
6
4
  import pytest
7
5
  from click.testing import CliRunner
@@ -10,8 +10,6 @@ problem, and a tool that solves it locally is a tool the next one forgets to
10
10
  copy.
11
11
  """
12
12
 
13
- from __future__ import annotations
14
-
15
13
  import sys
16
14
  from collections.abc import Sequence
17
15
  from typing import Any, Literal, NoReturn, overload
@@ -1,7 +1,5 @@
1
1
  """A bad flag must still honour `--json`, before click has parsed it."""
2
2
 
3
- from __future__ import annotations
4
-
5
3
  import json
6
4
 
7
5
  import click
@@ -5,8 +5,6 @@ skill installed once goes stale, while the guide is upgraded with the package
5
5
  that implements it.
6
6
  """
7
7
 
8
- from __future__ import annotations
9
-
10
8
  import click
11
9
 
12
10
 
@@ -1,7 +1,5 @@
1
1
  """The manual ships in the binary, so it cannot go stale."""
2
2
 
3
- from __future__ import annotations
4
-
5
3
  from click.testing import CliRunner
6
4
 
7
5
  from agentcli.guide import guide_command
@@ -15,8 +15,6 @@ shaped object on failure -- makes every caller special-case both, which is how
15
15
  four tools end up with four contracts.
16
16
  """
17
17
 
18
- from __future__ import annotations
19
-
20
18
  import json
21
19
  from collections.abc import Callable, Iterable
22
20
  from typing import Any
@@ -1,7 +1,5 @@
1
1
  """One JSON object on stdout, or human text. Never both."""
2
2
 
3
- from __future__ import annotations
4
-
5
3
  import json
6
4
 
7
5
  import click
@@ -10,8 +10,6 @@ Parameterised by skill name and package because the two hand-written copies
10
10
  this replaces had already drifted apart in exactly the guards that matter.
11
11
  """
12
12
 
13
- from __future__ import annotations
14
-
15
13
  import shutil
16
14
  from collections.abc import Iterable
17
15
  from importlib import resources
@@ -4,8 +4,6 @@ No test may touch a real `~/.agents` or `~/.claude`, so every one of them runs
4
4
  against a `tmp_path` home and a fake installed tool.
5
5
  """
6
6
 
7
- from __future__ import annotations
8
-
9
7
  import importlib
10
8
  import json
11
9
  import shutil
@@ -1,6 +1,6 @@
1
1
  version = 1
2
2
  revision = 3
3
- requires-python = ">=3.11"
3
+ requires-python = ">=3.12"
4
4
 
5
5
  [[package]]
6
6
  name = "click"
@@ -16,7 +16,7 @@ wheels = [
16
16
 
17
17
  [[package]]
18
18
  name = "click-agentcli"
19
- version = "0.1.0"
19
+ version = "0.3.0"
20
20
  source = { editable = "." }
21
21
  dependencies = [
22
22
  { name = "click" },
File without changes