recx-cli 0.0.4__tar.gz → 0.1.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.
- {recx_cli-0.0.4 → recx_cli-0.1.1}/.gitignore +3 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/PKG-INFO +46 -6
- {recx_cli-0.0.4 → recx_cli-0.1.1}/README.md +45 -5
- {recx_cli-0.0.4 → recx_cli-0.1.1}/pyproject.toml +2 -1
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/SPEC.md +8 -2
- recx_cli-0.1.1/spec/index.schema.json +653 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/check.py +47 -6
- recx_cli-0.1.1/src/recx_cli/cli.py +215 -0
- recx_cli-0.1.1/src/recx_cli/drift.py +312 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/hook.py +37 -9
- recx_cli-0.1.1/src/recx_cli/index.py +65 -0
- recx_cli-0.1.1/src/recx_cli/index_cache.py +261 -0
- recx_cli-0.1.1/src/recx_cli/match.py +260 -0
- recx_cli-0.1.1/src/recx_cli/search-result.schema.json +300 -0
- recx_cli-0.1.1/src/recx_cli/search.py +162 -0
- recx_cli-0.1.1/tests/fixtures/search/anomr.yaml +30 -0
- recx_cli-0.1.1/tests/fixtures/search/argwise.yaml +44 -0
- recx_cli-0.1.1/tests/fixtures/search/confyaml.yaml +29 -0
- recx_cli-0.1.1/tests/fixtures/search/cronexpr.yaml +28 -0
- recx_cli-0.1.1/tests/fixtures/search/feedparse.yaml +47 -0
- recx_cli-0.1.1/tests/fixtures/search/feedwatch.yaml +42 -0
- recx_cli-0.1.1/tests/fixtures/search/kustomize-secrets.yaml +27 -0
- recx_cli-0.1.1/tests/fixtures/search/mcp-sqlite.yaml +30 -0
- recx_cli-0.1.1/tests/fixtures/search/mdhtml.yaml +40 -0
- recx_cli-0.1.1/tests/fixtures/search/mdlint.yaml +38 -0
- recx_cli-0.1.1/tests/fixtures/search/nextver.yaml +27 -0
- recx_cli-0.1.1/tests/fixtures/search/patient.yaml +29 -0
- recx_cli-0.1.1/tests/fixtures/search/pdfmine.yaml +42 -0
- recx_cli-0.1.1/tests/fixtures/search/pr-labeler.yaml +26 -0
- recx_cli-0.1.1/tests/fixtures/search/quickjson.yaml +28 -0
- recx_cli-0.1.1/tests/fixtures/search/schemacheck.yaml +29 -0
- recx_cli-0.1.1/tests/fixtures/search/sealbox.yaml +28 -0
- recx_cli-0.1.1/tests/fixtures/search/sitemapgen.yaml +27 -0
- recx_cli-0.1.1/tests/fixtures/search/slack-notify.yaml +26 -0
- recx_cli-0.1.1/tests/fixtures/search/steadyhttp.yaml +30 -0
- recx_cli-0.1.1/tests/fixtures/search/tablecheck.yaml +28 -0
- recx_cli-0.1.1/tests/fixtures/search/thumbsmith.yaml +28 -0
- recx_cli-0.1.1/tests/fixtures/search/tokencheck.yaml +29 -0
- recx_cli-0.1.1/tests/fixtures/search/tollgate.yaml +41 -0
- recx_cli-0.1.1/tests/fixtures/search/yamlguard.yaml +39 -0
- recx_cli-0.1.1/tests/search_cases.yaml +200 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/tests/test_check.py +59 -0
- recx_cli-0.1.1/tests/test_crawler_core.py +497 -0
- recx_cli-0.1.1/tests/test_crawler_github.py +529 -0
- recx_cli-0.1.1/tests/test_crawler_main.py +139 -0
- recx_cli-0.1.1/tests/test_drift.py +851 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/tests/test_hook.py +10 -0
- recx_cli-0.1.1/tests/test_index.py +162 -0
- recx_cli-0.1.1/tests/test_index_cache.py +209 -0
- recx_cli-0.1.1/tests/test_match.py +441 -0
- recx_cli-0.1.1/tests/test_search.py +412 -0
- recx_cli-0.0.4/src/recx_cli/cli.py +0 -111
- recx_cli-0.0.4/src/recx_cli/drift.py +0 -178
- recx_cli-0.0.4/tests/test_drift.py +0 -424
- {recx_cli-0.0.4 → recx_cli-0.1.1}/LICENSE +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/evidence-without-run.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/extension-value-not-scalar.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/http-url.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/license-not-permissive.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/missing-capabilities.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/multiline-summary.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/package-without-purl.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/path-escapes-repo.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/unknown-key.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid/unknown-version.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule1-duplicate-evidence-id.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule1-duplicate-module-id.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule2-covers-unknown-module.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule2-requires-unknown-module.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule5-over-64-kib.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule6-anchor-alias.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule6-duplicate-key.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/invalid-rules/rule6-merge-key.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/valid/full.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/examples/valid/minimal.yaml +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/spec/recx.schema.json +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/__init__.py +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/__main__.py +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/src/recx_cli/evidence.py +0 -0
- {recx_cli-0.0.4 → recx_cli-0.1.1}/tests/test_evidence.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: recx-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Validator for RECX.yaml manifests: the recx check command.
|
|
5
5
|
Project-URL: Homepage, https://github.com/jbmv/recx
|
|
6
6
|
Project-URL: Repository, https://github.com/jbmv/recx
|
|
@@ -38,8 +38,11 @@ than write it again, recording where it came from in its own project's manifest.
|
|
|
38
38
|
|
|
39
39
|
Taking part is meant to cost a repository little. One prompt produces a complete, valid
|
|
40
40
|
manifest, and the Claude Code plugin checks it whenever a session ends, so it stays valid as
|
|
41
|
-
the code changes. No hosted service is involved
|
|
42
|
-
|
|
41
|
+
the code changes. No hosted service is involved. The fixed filename and the GitHub topic `recx`
|
|
42
|
+
serve as the index, and a scheduled workflow in this repository collects the valid manifests it
|
|
43
|
+
finds into a static file each day. In GitHub's web interface, manifests can also be found by
|
|
44
|
+
searching code for `path:/(^|\/)recx\.ya?ml$/i`; GitHub's code search API does not accept that
|
|
45
|
+
regular expression.
|
|
43
46
|
|
|
44
47
|
## The manifest
|
|
45
48
|
|
|
@@ -70,22 +73,59 @@ anything listed can be reused without asking.
|
|
|
70
73
|
- **Any other agent:** paste the prompt in [ADOPT.md](ADOPT.md).
|
|
71
74
|
- **By hand:** start from the example above, then run `uvx --from recx-cli recx check`.
|
|
72
75
|
|
|
76
|
+
Then add the GitHub topic `recx` to the repository, so the daily index finds it promptly.
|
|
77
|
+
|
|
78
|
+
The plugin's hook runs when a session or one of its subagents stops (Claude Code's Stop and
|
|
79
|
+
SubagentStop events). It blocks on an invalid manifest, and it reminds, without blocking, when
|
|
80
|
+
files under a module's `path` changed during the session while RECX.yaml did not. A commit can
|
|
81
|
+
record that module entries were checked against its tree with a trailer such as
|
|
82
|
+
`Recx-Checked: lib, cli`; the reminder then disregards that commit's changes to those modules
|
|
83
|
+
and the changes of the session's commits it descends from. `RECX_DRIFT_REMINDER=off` turns
|
|
84
|
+
the reminder off. The [manifest skill](plugin/skills/manifest/SKILL.md) describes both in full.
|
|
85
|
+
|
|
86
|
+
## Searching
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
recx search "retry an http request with exponential backoff"
|
|
90
|
+
recx search parse rss feeds --language python --json
|
|
91
|
+
recx show OWNER/NAME
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`recx search` downloads the published index (https://jbmv.github.io/recx/v1/index.json),
|
|
95
|
+
caches it for six hours, and ranks entries by keyword overlap with the query, weighting
|
|
96
|
+
capabilities above summaries and descriptions. It returns every entry that shares a term with
|
|
97
|
+
the query, ordered by score, and leaves the judgement of relevance to the agent reading the
|
|
98
|
+
results. `--json` gives the structured form a tool or agent should use, and the same result is
|
|
99
|
+
available from Python as `recx_cli.search.search()`. `recx show` prints one indexed entry in
|
|
100
|
+
full. Neither command needs a GitHub token or runs anything from a repository.
|
|
101
|
+
|
|
102
|
+
Every result is written by the repository's author and has been checked only against the
|
|
103
|
+
schema. The output says so in a fixed `notice`, and the JSON lists the author-written paths in
|
|
104
|
+
`untrusted`. The index never contains a manifest's `setup` or `run` commands. Before reusing
|
|
105
|
+
anything, read the repository's licence file and its current `RECX.yaml`, and run its evidence
|
|
106
|
+
only in a sandbox. [docs/integrating.md](docs/integrating.md) explains how to call search from
|
|
107
|
+
another tool, and [docs/design/search.md](docs/design/search.md) describes the index, the crawler
|
|
108
|
+
and the ranking in full.
|
|
109
|
+
|
|
73
110
|
## What's here
|
|
74
111
|
|
|
75
112
|
| | |
|
|
76
113
|
|---|---|
|
|
77
114
|
| [spec/](spec/) | The spec, its JSON Schema, and valid and invalid example manifests |
|
|
78
|
-
| `recx-cli` on PyPI | `recx check`,
|
|
115
|
+
| `recx-cli` on PyPI | `recx check`, `recx evidence`, `recx search` and `recx show` (`pip install recx-cli`) |
|
|
79
116
|
| `@jbmv/recx` on npm | The schema and examples, for JavaScript tooling |
|
|
80
117
|
| [plugin/](plugin/) | The Claude Code plugin; this repository is its marketplace |
|
|
118
|
+
| [crawler/](crawler/) | The daily crawler that builds the search index, run by a scheduled workflow |
|
|
119
|
+
| [docs/design/](docs/design/) | Design documents |
|
|
81
120
|
| [RECX.yaml](RECX.yaml) | recx's own manifest |
|
|
82
121
|
|
|
83
122
|
## Status
|
|
84
123
|
|
|
85
124
|
Experimental. The spec is a v0.1 draft and may change before 1.0; every manifest states the
|
|
86
125
|
version it was written against. `recx check` enforces the whole spec except rule 4, that the
|
|
87
|
-
license file matches `license
|
|
88
|
-
|
|
126
|
+
license file matches `license`; the search crawler applies it as far as GitHub's licence
|
|
127
|
+
detection allows. Search is in its first version: it ranks by keywords, has no synonym handling,
|
|
128
|
+
and has no MCP server yet.
|
|
89
129
|
|
|
90
130
|
## Kyosei
|
|
91
131
|
|
|
@@ -24,8 +24,11 @@ than write it again, recording where it came from in its own project's manifest.
|
|
|
24
24
|
|
|
25
25
|
Taking part is meant to cost a repository little. One prompt produces a complete, valid
|
|
26
26
|
manifest, and the Claude Code plugin checks it whenever a session ends, so it stays valid as
|
|
27
|
-
the code changes. No hosted service is involved
|
|
28
|
-
|
|
27
|
+
the code changes. No hosted service is involved. The fixed filename and the GitHub topic `recx`
|
|
28
|
+
serve as the index, and a scheduled workflow in this repository collects the valid manifests it
|
|
29
|
+
finds into a static file each day. In GitHub's web interface, manifests can also be found by
|
|
30
|
+
searching code for `path:/(^|\/)recx\.ya?ml$/i`; GitHub's code search API does not accept that
|
|
31
|
+
regular expression.
|
|
29
32
|
|
|
30
33
|
## The manifest
|
|
31
34
|
|
|
@@ -56,22 +59,59 @@ anything listed can be reused without asking.
|
|
|
56
59
|
- **Any other agent:** paste the prompt in [ADOPT.md](ADOPT.md).
|
|
57
60
|
- **By hand:** start from the example above, then run `uvx --from recx-cli recx check`.
|
|
58
61
|
|
|
62
|
+
Then add the GitHub topic `recx` to the repository, so the daily index finds it promptly.
|
|
63
|
+
|
|
64
|
+
The plugin's hook runs when a session or one of its subagents stops (Claude Code's Stop and
|
|
65
|
+
SubagentStop events). It blocks on an invalid manifest, and it reminds, without blocking, when
|
|
66
|
+
files under a module's `path` changed during the session while RECX.yaml did not. A commit can
|
|
67
|
+
record that module entries were checked against its tree with a trailer such as
|
|
68
|
+
`Recx-Checked: lib, cli`; the reminder then disregards that commit's changes to those modules
|
|
69
|
+
and the changes of the session's commits it descends from. `RECX_DRIFT_REMINDER=off` turns
|
|
70
|
+
the reminder off. The [manifest skill](plugin/skills/manifest/SKILL.md) describes both in full.
|
|
71
|
+
|
|
72
|
+
## Searching
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
recx search "retry an http request with exponential backoff"
|
|
76
|
+
recx search parse rss feeds --language python --json
|
|
77
|
+
recx show OWNER/NAME
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`recx search` downloads the published index (https://jbmv.github.io/recx/v1/index.json),
|
|
81
|
+
caches it for six hours, and ranks entries by keyword overlap with the query, weighting
|
|
82
|
+
capabilities above summaries and descriptions. It returns every entry that shares a term with
|
|
83
|
+
the query, ordered by score, and leaves the judgement of relevance to the agent reading the
|
|
84
|
+
results. `--json` gives the structured form a tool or agent should use, and the same result is
|
|
85
|
+
available from Python as `recx_cli.search.search()`. `recx show` prints one indexed entry in
|
|
86
|
+
full. Neither command needs a GitHub token or runs anything from a repository.
|
|
87
|
+
|
|
88
|
+
Every result is written by the repository's author and has been checked only against the
|
|
89
|
+
schema. The output says so in a fixed `notice`, and the JSON lists the author-written paths in
|
|
90
|
+
`untrusted`. The index never contains a manifest's `setup` or `run` commands. Before reusing
|
|
91
|
+
anything, read the repository's licence file and its current `RECX.yaml`, and run its evidence
|
|
92
|
+
only in a sandbox. [docs/integrating.md](docs/integrating.md) explains how to call search from
|
|
93
|
+
another tool, and [docs/design/search.md](docs/design/search.md) describes the index, the crawler
|
|
94
|
+
and the ranking in full.
|
|
95
|
+
|
|
59
96
|
## What's here
|
|
60
97
|
|
|
61
98
|
| | |
|
|
62
99
|
|---|---|
|
|
63
100
|
| [spec/](spec/) | The spec, its JSON Schema, and valid and invalid example manifests |
|
|
64
|
-
| `recx-cli` on PyPI | `recx check`,
|
|
101
|
+
| `recx-cli` on PyPI | `recx check`, `recx evidence`, `recx search` and `recx show` (`pip install recx-cli`) |
|
|
65
102
|
| `@jbmv/recx` on npm | The schema and examples, for JavaScript tooling |
|
|
66
103
|
| [plugin/](plugin/) | The Claude Code plugin; this repository is its marketplace |
|
|
104
|
+
| [crawler/](crawler/) | The daily crawler that builds the search index, run by a scheduled workflow |
|
|
105
|
+
| [docs/design/](docs/design/) | Design documents |
|
|
67
106
|
| [RECX.yaml](RECX.yaml) | recx's own manifest |
|
|
68
107
|
|
|
69
108
|
## Status
|
|
70
109
|
|
|
71
110
|
Experimental. The spec is a v0.1 draft and may change before 1.0; every manifest states the
|
|
72
111
|
version it was written against. `recx check` enforces the whole spec except rule 4, that the
|
|
73
|
-
license file matches `license
|
|
74
|
-
|
|
112
|
+
license file matches `license`; the search crawler applies it as far as GitHub's licence
|
|
113
|
+
detection allows. Search is in its first version: it ranks by keywords, has no synonym handling,
|
|
114
|
+
and has no MCP server yet.
|
|
75
115
|
|
|
76
116
|
## Kyosei
|
|
77
117
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "recx-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Validator for RECX.yaml manifests: the recx check command."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -38,3 +38,4 @@ include = ["/src", "/spec", "/tests", "/README.md", "/LICENSE", "/pyproject.toml
|
|
|
38
38
|
|
|
39
39
|
[tool.pytest.ini_options]
|
|
40
40
|
testpaths = ["tests"]
|
|
41
|
+
pythonpath = ["."] # lets tests import the crawler/ package, which is not in the wheel
|
|
@@ -32,8 +32,14 @@ recx's own validator checks both.
|
|
|
32
32
|
|
|
33
33
|
- The filename is exactly `RECX.yaml`, at the repository root. There is one per repository.
|
|
34
34
|
That fixed name is what makes manifests findable: searching code for the filename returns
|
|
35
|
-
only manifests.
|
|
36
|
-
query also catches misspellings, so keep only root-level
|
|
35
|
+
only manifests. In GitHub's web interface, signed in, search code for
|
|
36
|
+
`path:/(^|\/)recx\.ya?ml$/i`; the query also catches misspellings, so keep only root-level
|
|
37
|
+
files named exactly `RECX.yaml`. GitHub's code search API does not accept regular
|
|
38
|
+
expressions, so a program searches for `filename:RECX.yaml path:/` and applies the same
|
|
39
|
+
filter.
|
|
40
|
+
- A repository with a manifest should also carry the GitHub topic `recx`. Code search indexes
|
|
41
|
+
new and small repositories slowly, and sometimes not at all; repository topics become
|
|
42
|
+
searchable quickly.
|
|
37
43
|
- It is UTF-8 YAML 1.2. JSON is valid YAML, so a tool may write JSON into it.
|
|
38
44
|
- It is at most 64 KiB.
|
|
39
45
|
- It uses no anchors (`&`), aliases (`*`) or merge keys (`<<`), and no mapping repeats a key.
|