rulereach-delegate 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.
- rulereach_delegate-0.1.1/.github/workflows/ci.yml +28 -0
- rulereach_delegate-0.1.1/.github/workflows/release.yml +58 -0
- rulereach_delegate-0.1.1/.gitignore +7 -0
- rulereach_delegate-0.1.1/.markdownlint-cli2.jsonc +18 -0
- rulereach_delegate-0.1.1/.pre-commit-config.yaml +20 -0
- rulereach_delegate-0.1.1/AGENTS.md +21 -0
- rulereach_delegate-0.1.1/CHANGELOG.md +31 -0
- rulereach_delegate-0.1.1/CLAUDE.md +5 -0
- rulereach_delegate-0.1.1/CONTRIBUTING.md +31 -0
- rulereach_delegate-0.1.1/LICENSE +21 -0
- rulereach_delegate-0.1.1/PKG-INFO +204 -0
- rulereach_delegate-0.1.1/README.md +173 -0
- rulereach_delegate-0.1.1/assets/demo.gif +0 -0
- rulereach_delegate-0.1.1/docs/README.es.md +65 -0
- rulereach_delegate-0.1.1/docs/README.pt-BR.md +64 -0
- rulereach_delegate-0.1.1/docs/README.ru.md +63 -0
- rulereach_delegate-0.1.1/docs/README.zh-CN.md +57 -0
- rulereach_delegate-0.1.1/docs/semantics.md +117 -0
- rulereach_delegate-0.1.1/pyproject.toml +78 -0
- rulereach_delegate-0.1.1/scripts/check.sh +37 -0
- rulereach_delegate-0.1.1/scripts/demo_gif.py +207 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/__init__.py +7 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/__main__.py +8 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/checks.py +447 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/cli.py +149 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/config.py +109 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/discovery.py +262 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/model.py +156 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/report.py +193 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/startup.py +114 -0
- rulereach_delegate-0.1.1/src/rulereach_delegate/tools.py +134 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/.claude/agents/narrowed.md +10 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/.claude/agents/no-description.md +5 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/.claude/agents/unparsable.md +6 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/.claude/agents/zero-tools.md +7 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/.claude/rules/testing.md +5 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/.claude/skills/deep-research/SKILL.md +9 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/.claude/skills/legacy-helper/SKILL.md +8 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/CLAUDE.md +5 -0
- rulereach_delegate-0.1.1/tests/fixtures/broken/docs/style.md +1 -0
- rulereach_delegate-0.1.1/tests/fixtures/clean/.claude/agents/reviewer.md +10 -0
- rulereach_delegate-0.1.1/tests/fixtures/clean/.claude/skills/api-conventions/SKILL.md +6 -0
- rulereach_delegate-0.1.1/tests/fixtures/clean/CLAUDE.md +4 -0
- rulereach_delegate-0.1.1/tests/test_rulereach_delegate.py +228 -0
- rulereach_delegate-0.1.1/uv.lock +1152 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
check:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.10", "3.12"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: astral-sh/setup-uv@v4
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
- run: uv pip install --system -e . pytest ruff==0.16.0 mypy==2.3.0 types-PyYAML
|
|
24
|
+
- run: ruff check .
|
|
25
|
+
- run: ruff format --check .
|
|
26
|
+
- run: mypy
|
|
27
|
+
- run: pytest -q
|
|
28
|
+
- run: rulereach-delegate check . --exclude "tests/fixtures/**"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: astral-sh/setup-uv@v4
|
|
16
|
+
- name: Check tag matches project version
|
|
17
|
+
run: |
|
|
18
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
19
|
+
version="$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2)"
|
|
20
|
+
if [ "$tag" != "$version" ]; then
|
|
21
|
+
echo "tag $tag does not match pyproject version $version"
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
- name: Build sdist and wheel
|
|
25
|
+
run: uv build
|
|
26
|
+
- uses: actions/upload-artifact@v4
|
|
27
|
+
with:
|
|
28
|
+
name: dist
|
|
29
|
+
path: dist/
|
|
30
|
+
|
|
31
|
+
pypi:
|
|
32
|
+
needs: build
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
environment: pypi
|
|
35
|
+
permissions:
|
|
36
|
+
id-token: write
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/download-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
43
|
+
|
|
44
|
+
github-release:
|
|
45
|
+
needs: pypi
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
permissions:
|
|
48
|
+
contents: write
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v4
|
|
51
|
+
- uses: actions/download-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
name: dist
|
|
54
|
+
path: dist/
|
|
55
|
+
- name: Create GitHub release
|
|
56
|
+
env:
|
|
57
|
+
GH_TOKEN: ${{ github.token }}
|
|
58
|
+
run: gh release create "$GITHUB_REF_NAME" dist/* --title "$GITHUB_REF_NAME" --generate-notes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"config": {
|
|
3
|
+
"MD013": false,
|
|
4
|
+
"MD033": false,
|
|
5
|
+
"MD012": false,
|
|
6
|
+
"MD036": false
|
|
7
|
+
},
|
|
8
|
+
// CLAUDE.md starts with an @AGENTS.md import, which is the documented way to keep one
|
|
9
|
+
// canonical instruction file, so MD041 does not apply to it.
|
|
10
|
+
"ignores": [
|
|
11
|
+
".venv/**",
|
|
12
|
+
"tests/fixtures/**",
|
|
13
|
+
"CHANGELOG.md",
|
|
14
|
+
"CLAUDE.md",
|
|
15
|
+
"lychee-*/**",
|
|
16
|
+
"gitleaks*/**"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
default_language_version:
|
|
2
|
+
python: python3.12
|
|
3
|
+
repos:
|
|
4
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
5
|
+
rev: v0.16.0
|
|
6
|
+
hooks:
|
|
7
|
+
- id: ruff-check
|
|
8
|
+
args: [--fix]
|
|
9
|
+
- id: ruff-format
|
|
10
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
11
|
+
rev: v2.3.0
|
|
12
|
+
hooks:
|
|
13
|
+
- id: mypy
|
|
14
|
+
additional_dependencies: [types-PyYAML]
|
|
15
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
16
|
+
rev: v6.0.0
|
|
17
|
+
hooks:
|
|
18
|
+
- id: trailing-whitespace
|
|
19
|
+
- id: end-of-file-fixer
|
|
20
|
+
- id: check-yaml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# rulereach-delegate
|
|
2
|
+
|
|
3
|
+
A CLI that audits what reaches a Claude Code subagent. Python, PyYAML is the only runtime
|
|
4
|
+
dependency.
|
|
5
|
+
|
|
6
|
+
## Commands
|
|
7
|
+
|
|
8
|
+
- `uv sync --extra dev` to set up.
|
|
9
|
+
- `bash scripts/check.sh` is the full gate and must pass before a commit.
|
|
10
|
+
- `uv run python -m pytest -q` for tests alone.
|
|
11
|
+
|
|
12
|
+
## Conventions
|
|
13
|
+
|
|
14
|
+
- Every check cites the documentation sentence that defines the behaviour, recorded in
|
|
15
|
+
`docs/semantics.md` with the date it was read. Never guess a runtime rule.
|
|
16
|
+
- Findings say what a definition loses at delegation, not how the file is written.
|
|
17
|
+
- Fixtures under `tests/fixtures/` are real directory trees; add a case there for every new
|
|
18
|
+
check, and keep `tests/fixtures/clean/` free of findings.
|
|
19
|
+
- A heuristic that fires on prose is a bug. Check new heuristics against large public
|
|
20
|
+
collections of subagents before shipping them.
|
|
21
|
+
- Keep functions small and typed; mypy runs in strict mode.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses
|
|
5
|
+
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.1.1] - 2026-08-26
|
|
8
|
+
|
|
9
|
+
First release published to PyPI. No functional changes: the `0.1.0` tag was built
|
|
10
|
+
before the PyPI trusted publisher existed, so the upload never happened.
|
|
11
|
+
|
|
12
|
+
## [0.1.0] - 2026-08-26
|
|
13
|
+
|
|
14
|
+
First release.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `check`: fourteen checks over `.claude/agents/`, plugin `agents/` directories and forking
|
|
19
|
+
skills, covering files Claude Code skips, the two documented tool filters, preloaded skills
|
|
20
|
+
and `context: fork` targets. Exit code 1 on errors, `--strict` to fail on warnings too.
|
|
21
|
+
- `list`: every subagent and forking skill, with the agent type it runs as, whether it loads
|
|
22
|
+
the `CLAUDE.md` hierarchy, and how many tools survive the filters.
|
|
23
|
+
- `explain`: the documented startup composition of one subagent, split into what reaches it
|
|
24
|
+
and what does not.
|
|
25
|
+
- `--json` on every command, `--exclude` for fixture directories, `--check` to run one check.
|
|
26
|
+
- Configuration through `[tool.rulereach-delegate]` in `pyproject.toml` or
|
|
27
|
+
`.rulereach-delegate.toml`.
|
|
28
|
+
- `docs/semantics.md`: the documentation sentences every check is built on, with the date they
|
|
29
|
+
were read.
|
|
30
|
+
|
|
31
|
+
[0.1.0]: https://github.com/Topicspot/rulereach-delegate/releases/tag/v0.1.0
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time. Small, focused pull requests are the easiest to merge.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync --extra dev
|
|
9
|
+
uv run python -m pytest -q
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`bash scripts/check.sh` runs the full gate: ruff, mypy in strict mode, pytest, vulture,
|
|
13
|
+
pip-audit, markdownlint, the tool on itself, and, when they are installed, gitleaks and
|
|
14
|
+
lychee. CI runs a subset of the same commands, so a green local gate means a green CI.
|
|
15
|
+
|
|
16
|
+
## Adding a check
|
|
17
|
+
|
|
18
|
+
1. Find the sentence in the Claude Code documentation that defines the behaviour, and add it
|
|
19
|
+
to `docs/semantics.md` with the date you read it. A check without a source does not land:
|
|
20
|
+
guessing a runtime rule is how a linter starts lying.
|
|
21
|
+
2. Add a directory tree under `tests/fixtures/broken/` that triggers it, and make sure
|
|
22
|
+
`tests/fixtures/clean/` stays clean.
|
|
23
|
+
3. Write the finding so it says what the definition loses, not how the file is written.
|
|
24
|
+
Message, one-line fix, documentation URL.
|
|
25
|
+
4. Run the tool over a few large public collections of subagents before you open the pull
|
|
26
|
+
request. A check that fires on prose is worse than no check.
|
|
27
|
+
|
|
28
|
+
## Reporting a false positive
|
|
29
|
+
|
|
30
|
+
Open an issue with the smallest agent or skill file that reproduces it and the command you
|
|
31
|
+
ran. False positives are treated as bugs, not as opinions.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Topicspot
|
|
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.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: rulereach-delegate
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Audit what reaches a Claude Code subagent: instructions, skills and tools that delegation drops without an error.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Topicspot/rulereach-delegate
|
|
6
|
+
Project-URL: Repository, https://github.com/Topicspot/rulereach-delegate
|
|
7
|
+
Project-URL: Issues, https://github.com/Topicspot/rulereach-delegate/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Topicspot/rulereach-delegate/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Topicspot
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agent-skills,claude-code,developer-tools,lint,subagents
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: pyyaml>=6.0
|
|
21
|
+
Requires-Dist: tomli>=2.0.1; python_version < '3.11'
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: mypy==2.3.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pillow>=11; extra == 'dev'
|
|
25
|
+
Requires-Dist: pip-audit>=2.7; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=9.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff==0.16.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: types-pyyaml; extra == 'dev'
|
|
29
|
+
Requires-Dist: vulture>=2.16; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# rulereach-delegate
|
|
33
|
+
|
|
34
|
+
**English** · [Русский](docs/README.ru.md) · [简体中文](docs/README.zh-CN.md) · [Español](docs/README.es.md) · [Português](docs/README.pt-BR.md)
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/rulereach-delegate/)
|
|
37
|
+
[](https://pypi.org/project/rulereach-delegate/)
|
|
38
|
+
[](https://github.com/Topicspot/rulereach-delegate/actions/workflows/ci.yml)
|
|
39
|
+
[](https://github.com/Topicspot/rulereach-delegate/blob/main/LICENSE)
|
|
40
|
+
|
|
41
|
+
A subagent definition is a promise about a fresh context window: this prompt, these tools,
|
|
42
|
+
these skills. Claude Code keeps part of that promise and quietly rewrites the rest. A
|
|
43
|
+
background subagent, which is the default, keeps only a fixed list of built-in tools, so
|
|
44
|
+
`BashOutput` in your `tools` list is dropped with no error. A `tools` list that survives
|
|
45
|
+
none of the filters makes the agent fail to launch. A skill named in the prompt but missing
|
|
46
|
+
from the `skills` field is not in the context at startup. A skill that forks into `Explore`
|
|
47
|
+
sees no `CLAUDE.md` at all. An `agent:` that does not resolve falls back to a general-purpose
|
|
48
|
+
agent with a wider tool pool than the one you asked for.
|
|
49
|
+
|
|
50
|
+
`rulereach-delegate` reads `.claude/agents/`, plugin `agents/` directories and every
|
|
51
|
+
`SKILL.md` in a repository, applies the documented startup and tool-filter rules, and reports
|
|
52
|
+
what delegation drops. It runs offline and cites the documentation page behind every finding.
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
```console
|
|
57
|
+
$ rulereach-delegate check
|
|
58
|
+
.claude/agents/narrowed.md
|
|
59
|
+
x skill-unreachable the prompt mentions the 'deep-research' skill, but it is not preloaded and the agent has no Skill tool
|
|
60
|
+
fix: add deep-research to the skills field, or add Skill to tools
|
|
61
|
+
docs: https://code.claude.com/docs/en/sub-agents#preload-skills-into-subagents
|
|
62
|
+
! tools-background-removed BashOutput is dropped for a background subagent, which is the default, and the removal reports no error
|
|
63
|
+
fix: keep the agent in the foreground for this work, or drop the tool from the list so the definition says what the agent really gets
|
|
64
|
+
docs: https://code.claude.com/docs/en/sub-agents#available-tools
|
|
65
|
+
.claude/agents/zero-tools.md
|
|
66
|
+
x tools-zero no entry in tools survives the documented filters, so the agent fails to launch
|
|
67
|
+
fix: list tools the agent can actually keep, such as Artifact, Bash, Edit, EnterWorktree
|
|
68
|
+
docs: https://code.claude.com/docs/en/errors#agent-would-be-spawned-with-zero-tools
|
|
69
|
+
.claude/skills/deep-research/SKILL.md
|
|
70
|
+
! fork-skips-memory agent: Explore skips the CLAUDE.md hierarchy, so 4 instruction line(s) in it, 3 of them prohibitions, do not reach this fork
|
|
71
|
+
fix: restate the rules this task depends on inside the skill, or fork into an agent that loads CLAUDE.md
|
|
72
|
+
docs: https://code.claude.com/docs/en/sub-agents#what-loads-at-startup
|
|
73
|
+
|
|
74
|
+
rulereach-delegate: 5 error(s), 5 warning(s), 2 note(s)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Install
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pipx install rulereach-delegate # or: uv tool install rulereach-delegate
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Nothing is sent anywhere: the tool reads files and exits. No API keys, no network calls.
|
|
84
|
+
|
|
85
|
+
## Use
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
rulereach-delegate check # report what delegation loses, exit 1 on errors
|
|
89
|
+
rulereach-delegate check --strict # exit 1 on warnings and notes too
|
|
90
|
+
rulereach-delegate check --check tools-zero # one check at a time
|
|
91
|
+
rulereach-delegate check --exclude "tests/fixtures/**"
|
|
92
|
+
rulereach-delegate list # every subagent and forking skill
|
|
93
|
+
rulereach-delegate explain code-reviewer # what that agent starts with
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`explain` is the answer to "why did the subagent ignore that":
|
|
97
|
+
|
|
98
|
+
```console
|
|
99
|
+
$ rulereach-delegate explain deep-research
|
|
100
|
+
deep-research (.claude/skills/deep-research/SKILL.md, forking skill)
|
|
101
|
+
|
|
102
|
+
Reaches it at startup:
|
|
103
|
+
- its own system prompt: the skill content, injected as the task
|
|
104
|
+
|
|
105
|
+
Does not reach it:
|
|
106
|
+
- the CLAUDE.md hierarchy: 4 instruction line(s), 3 of them prohibitions, and the git status snapshot
|
|
107
|
+
- the parent conversation history and the files already read
|
|
108
|
+
- skills invoked in the parent session, unless named in the skills field
|
|
109
|
+
- the output style and the parent's auto memory
|
|
110
|
+
|
|
111
|
+
Tools: inherits every tool available to subagents.
|
|
112
|
+
Runs in the background (the default); a background subagent keeps only a fixed set of built-in tools, 19 of them, plus every MCP tool.
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Add `--json` to any command for machine-readable output.
|
|
116
|
+
|
|
117
|
+
## Checks
|
|
118
|
+
|
|
119
|
+
| ID | What it catches |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| `not-loaded` | agent file Claude Code skips: unparsable frontmatter, no `name`, a `name` with a colon or leading hyphen, or a `name` with no `description` |
|
|
122
|
+
| `unknown-field` | frontmatter key that is not a subagent field, such as a skill's `allowed-tools`, so it is ignored |
|
|
123
|
+
| `tools-removed` | tool removed from every subagent even when listed, such as `AskUserQuestion` or `ExitPlanMode` outside plan mode |
|
|
124
|
+
| `tools-background-removed` | built-in tool a background subagent does not keep, dropped without an error |
|
|
125
|
+
| `tools-zero` | no entry in `tools` survives the filters, so the agent fails to launch |
|
|
126
|
+
| `tools-denied-conflict` | tool in both `tools` and `disallowedTools`, so it is denied |
|
|
127
|
+
| `skill-missing` | `skills` names a skill that is not in the repository |
|
|
128
|
+
| `skill-not-preloadable` | `skills` names a skill with `disable-model-invocation: true`, which cannot be preloaded |
|
|
129
|
+
| `skill-unreachable` | prompt names a skill that is neither preloaded nor reachable, because the agent has no `Skill` tool |
|
|
130
|
+
| `skill-not-preloaded` | prompt names a skill the agent must discover itself instead of starting with its content |
|
|
131
|
+
| `fork-agent-unresolved` | `agent:` in a forking skill that resolves to nothing, so the fork runs general-purpose with a wider tool pool |
|
|
132
|
+
| `fork-skips-memory` | fork into `Explore` or `Plan`, which skip the `CLAUDE.md` hierarchy and git status |
|
|
133
|
+
| `fork-background-tools` | tool pre-approved in `allowed-tools` that a background fork does not have |
|
|
134
|
+
| `model-unknown` | `model` that is neither an alias nor a full model ID |
|
|
135
|
+
|
|
136
|
+
Severity is about consequence, not style. An error means the definition cannot do what it
|
|
137
|
+
says: the agent does not load, does not launch, or loses a capability it names. A warning
|
|
138
|
+
means it silently gets less than the file promises. A note is behaviour worth knowing that is
|
|
139
|
+
not a mistake.
|
|
140
|
+
|
|
141
|
+
The documented sentences each check is built on are collected in
|
|
142
|
+
[docs/semantics.md](docs/semantics.md), with the date they were read.
|
|
143
|
+
|
|
144
|
+
## Scope
|
|
145
|
+
|
|
146
|
+
Claude Code only, and only what a repository can carry: `.claude/agents/`, plugin `agents/`
|
|
147
|
+
directories, `.claude/skills/*/SKILL.md`, the `CLAUDE.md` hierarchy with its imports, and
|
|
148
|
+
`.claude/rules/`. Subagents installed at user scope in `~/.claude/agents/` are outside a
|
|
149
|
+
repository, so they are outside a repository check. Runtime behaviour is out of scope too:
|
|
150
|
+
this is a static audit of definitions, not a transcript analyser.
|
|
151
|
+
|
|
152
|
+
## Configuration
|
|
153
|
+
|
|
154
|
+
Optional. Put the flags you would otherwise repeat into `pyproject.toml`:
|
|
155
|
+
|
|
156
|
+
```toml
|
|
157
|
+
[tool.rulereach-delegate]
|
|
158
|
+
exclude = ["tests/fixtures/**"]
|
|
159
|
+
strict = false
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Projects without a `pyproject.toml` can use a `.rulereach-delegate.toml` with the same keys at
|
|
163
|
+
the top level. If both exist, `.rulereach-delegate.toml` wins, and command line flags win over
|
|
164
|
+
both. An unreadable file, an unknown key or a value of the wrong type is reported on stderr
|
|
165
|
+
rather than ignored.
|
|
166
|
+
|
|
167
|
+
## In CI
|
|
168
|
+
|
|
169
|
+
```yaml
|
|
170
|
+
- name: rulereach-delegate
|
|
171
|
+
run: uvx rulereach-delegate check
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`check` exits 1 when there is at least one error, 0 otherwise. Use `--strict` to fail on
|
|
175
|
+
warnings as well.
|
|
176
|
+
|
|
177
|
+
## Alternatives
|
|
178
|
+
|
|
179
|
+
- [skilldoctor](https://github.com/studiomeyer-io/skilldoctor), [skillcheck](https://github.com/erphq/skillcheck),
|
|
180
|
+
[claudelint](https://github.com/pdugan20/claudelint) and
|
|
181
|
+
[claude-plugins-validation](https://github.com/Emasoft/claude-plugins-validation) validate
|
|
182
|
+
the shape of skill, `CLAUDE.md` and subagent files: frontmatter schema, referenced paths,
|
|
183
|
+
security patterns. Some of them check a subagent's frontmatter fields as well. They stop at
|
|
184
|
+
the file; this tool continues into what the runtime does to it, which is where the tool
|
|
185
|
+
filters and the startup composition live.
|
|
186
|
+
- [rule-trace](https://github.com/seanleecoder/rule-trace) answers the same question at
|
|
187
|
+
runtime: it asks the agent to disclose which rules it applied, and counts those disclosures
|
|
188
|
+
over time. That needs your rules migrated into its format and a hook wired up. This tool is
|
|
189
|
+
static and needs nothing but the repository.
|
|
190
|
+
- `claude plugin validate` finds agent files whose frontmatter does not parse. It does not
|
|
191
|
+
flag a file that parses but has no `name`, and it does not model the tool filters.
|
|
192
|
+
|
|
193
|
+
## Related
|
|
194
|
+
|
|
195
|
+
- [rulereach](https://github.com/Topicspot/rulereach) - whether an instruction file reaches
|
|
196
|
+
the main agent at all: Codex, Claude Code, Cursor, Copilot.
|
|
197
|
+
- [skillfrisk](https://github.com/Topicspot/skillfrisk) - scan agent skills and MCP servers
|
|
198
|
+
for prompt injection and unsafe instructions.
|
|
199
|
+
- [ciparity](https://github.com/Topicspot/ciparity) - find drift between pre-commit hooks
|
|
200
|
+
and your CI pipeline.
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
MIT
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# rulereach-delegate
|
|
2
|
+
|
|
3
|
+
**English** · [Русский](docs/README.ru.md) · [简体中文](docs/README.zh-CN.md) · [Español](docs/README.es.md) · [Português](docs/README.pt-BR.md)
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/rulereach-delegate/)
|
|
6
|
+
[](https://pypi.org/project/rulereach-delegate/)
|
|
7
|
+
[](https://github.com/Topicspot/rulereach-delegate/actions/workflows/ci.yml)
|
|
8
|
+
[](https://github.com/Topicspot/rulereach-delegate/blob/main/LICENSE)
|
|
9
|
+
|
|
10
|
+
A subagent definition is a promise about a fresh context window: this prompt, these tools,
|
|
11
|
+
these skills. Claude Code keeps part of that promise and quietly rewrites the rest. A
|
|
12
|
+
background subagent, which is the default, keeps only a fixed list of built-in tools, so
|
|
13
|
+
`BashOutput` in your `tools` list is dropped with no error. A `tools` list that survives
|
|
14
|
+
none of the filters makes the agent fail to launch. A skill named in the prompt but missing
|
|
15
|
+
from the `skills` field is not in the context at startup. A skill that forks into `Explore`
|
|
16
|
+
sees no `CLAUDE.md` at all. An `agent:` that does not resolve falls back to a general-purpose
|
|
17
|
+
agent with a wider tool pool than the one you asked for.
|
|
18
|
+
|
|
19
|
+
`rulereach-delegate` reads `.claude/agents/`, plugin `agents/` directories and every
|
|
20
|
+
`SKILL.md` in a repository, applies the documented startup and tool-filter rules, and reports
|
|
21
|
+
what delegation drops. It runs offline and cites the documentation page behind every finding.
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
```console
|
|
26
|
+
$ rulereach-delegate check
|
|
27
|
+
.claude/agents/narrowed.md
|
|
28
|
+
x skill-unreachable the prompt mentions the 'deep-research' skill, but it is not preloaded and the agent has no Skill tool
|
|
29
|
+
fix: add deep-research to the skills field, or add Skill to tools
|
|
30
|
+
docs: https://code.claude.com/docs/en/sub-agents#preload-skills-into-subagents
|
|
31
|
+
! tools-background-removed BashOutput is dropped for a background subagent, which is the default, and the removal reports no error
|
|
32
|
+
fix: keep the agent in the foreground for this work, or drop the tool from the list so the definition says what the agent really gets
|
|
33
|
+
docs: https://code.claude.com/docs/en/sub-agents#available-tools
|
|
34
|
+
.claude/agents/zero-tools.md
|
|
35
|
+
x tools-zero no entry in tools survives the documented filters, so the agent fails to launch
|
|
36
|
+
fix: list tools the agent can actually keep, such as Artifact, Bash, Edit, EnterWorktree
|
|
37
|
+
docs: https://code.claude.com/docs/en/errors#agent-would-be-spawned-with-zero-tools
|
|
38
|
+
.claude/skills/deep-research/SKILL.md
|
|
39
|
+
! fork-skips-memory agent: Explore skips the CLAUDE.md hierarchy, so 4 instruction line(s) in it, 3 of them prohibitions, do not reach this fork
|
|
40
|
+
fix: restate the rules this task depends on inside the skill, or fork into an agent that loads CLAUDE.md
|
|
41
|
+
docs: https://code.claude.com/docs/en/sub-agents#what-loads-at-startup
|
|
42
|
+
|
|
43
|
+
rulereach-delegate: 5 error(s), 5 warning(s), 2 note(s)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pipx install rulereach-delegate # or: uv tool install rulereach-delegate
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Nothing is sent anywhere: the tool reads files and exits. No API keys, no network calls.
|
|
53
|
+
|
|
54
|
+
## Use
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
rulereach-delegate check # report what delegation loses, exit 1 on errors
|
|
58
|
+
rulereach-delegate check --strict # exit 1 on warnings and notes too
|
|
59
|
+
rulereach-delegate check --check tools-zero # one check at a time
|
|
60
|
+
rulereach-delegate check --exclude "tests/fixtures/**"
|
|
61
|
+
rulereach-delegate list # every subagent and forking skill
|
|
62
|
+
rulereach-delegate explain code-reviewer # what that agent starts with
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`explain` is the answer to "why did the subagent ignore that":
|
|
66
|
+
|
|
67
|
+
```console
|
|
68
|
+
$ rulereach-delegate explain deep-research
|
|
69
|
+
deep-research (.claude/skills/deep-research/SKILL.md, forking skill)
|
|
70
|
+
|
|
71
|
+
Reaches it at startup:
|
|
72
|
+
- its own system prompt: the skill content, injected as the task
|
|
73
|
+
|
|
74
|
+
Does not reach it:
|
|
75
|
+
- the CLAUDE.md hierarchy: 4 instruction line(s), 3 of them prohibitions, and the git status snapshot
|
|
76
|
+
- the parent conversation history and the files already read
|
|
77
|
+
- skills invoked in the parent session, unless named in the skills field
|
|
78
|
+
- the output style and the parent's auto memory
|
|
79
|
+
|
|
80
|
+
Tools: inherits every tool available to subagents.
|
|
81
|
+
Runs in the background (the default); a background subagent keeps only a fixed set of built-in tools, 19 of them, plus every MCP tool.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Add `--json` to any command for machine-readable output.
|
|
85
|
+
|
|
86
|
+
## Checks
|
|
87
|
+
|
|
88
|
+
| ID | What it catches |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `not-loaded` | agent file Claude Code skips: unparsable frontmatter, no `name`, a `name` with a colon or leading hyphen, or a `name` with no `description` |
|
|
91
|
+
| `unknown-field` | frontmatter key that is not a subagent field, such as a skill's `allowed-tools`, so it is ignored |
|
|
92
|
+
| `tools-removed` | tool removed from every subagent even when listed, such as `AskUserQuestion` or `ExitPlanMode` outside plan mode |
|
|
93
|
+
| `tools-background-removed` | built-in tool a background subagent does not keep, dropped without an error |
|
|
94
|
+
| `tools-zero` | no entry in `tools` survives the filters, so the agent fails to launch |
|
|
95
|
+
| `tools-denied-conflict` | tool in both `tools` and `disallowedTools`, so it is denied |
|
|
96
|
+
| `skill-missing` | `skills` names a skill that is not in the repository |
|
|
97
|
+
| `skill-not-preloadable` | `skills` names a skill with `disable-model-invocation: true`, which cannot be preloaded |
|
|
98
|
+
| `skill-unreachable` | prompt names a skill that is neither preloaded nor reachable, because the agent has no `Skill` tool |
|
|
99
|
+
| `skill-not-preloaded` | prompt names a skill the agent must discover itself instead of starting with its content |
|
|
100
|
+
| `fork-agent-unresolved` | `agent:` in a forking skill that resolves to nothing, so the fork runs general-purpose with a wider tool pool |
|
|
101
|
+
| `fork-skips-memory` | fork into `Explore` or `Plan`, which skip the `CLAUDE.md` hierarchy and git status |
|
|
102
|
+
| `fork-background-tools` | tool pre-approved in `allowed-tools` that a background fork does not have |
|
|
103
|
+
| `model-unknown` | `model` that is neither an alias nor a full model ID |
|
|
104
|
+
|
|
105
|
+
Severity is about consequence, not style. An error means the definition cannot do what it
|
|
106
|
+
says: the agent does not load, does not launch, or loses a capability it names. A warning
|
|
107
|
+
means it silently gets less than the file promises. A note is behaviour worth knowing that is
|
|
108
|
+
not a mistake.
|
|
109
|
+
|
|
110
|
+
The documented sentences each check is built on are collected in
|
|
111
|
+
[docs/semantics.md](docs/semantics.md), with the date they were read.
|
|
112
|
+
|
|
113
|
+
## Scope
|
|
114
|
+
|
|
115
|
+
Claude Code only, and only what a repository can carry: `.claude/agents/`, plugin `agents/`
|
|
116
|
+
directories, `.claude/skills/*/SKILL.md`, the `CLAUDE.md` hierarchy with its imports, and
|
|
117
|
+
`.claude/rules/`. Subagents installed at user scope in `~/.claude/agents/` are outside a
|
|
118
|
+
repository, so they are outside a repository check. Runtime behaviour is out of scope too:
|
|
119
|
+
this is a static audit of definitions, not a transcript analyser.
|
|
120
|
+
|
|
121
|
+
## Configuration
|
|
122
|
+
|
|
123
|
+
Optional. Put the flags you would otherwise repeat into `pyproject.toml`:
|
|
124
|
+
|
|
125
|
+
```toml
|
|
126
|
+
[tool.rulereach-delegate]
|
|
127
|
+
exclude = ["tests/fixtures/**"]
|
|
128
|
+
strict = false
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Projects without a `pyproject.toml` can use a `.rulereach-delegate.toml` with the same keys at
|
|
132
|
+
the top level. If both exist, `.rulereach-delegate.toml` wins, and command line flags win over
|
|
133
|
+
both. An unreadable file, an unknown key or a value of the wrong type is reported on stderr
|
|
134
|
+
rather than ignored.
|
|
135
|
+
|
|
136
|
+
## In CI
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
- name: rulereach-delegate
|
|
140
|
+
run: uvx rulereach-delegate check
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`check` exits 1 when there is at least one error, 0 otherwise. Use `--strict` to fail on
|
|
144
|
+
warnings as well.
|
|
145
|
+
|
|
146
|
+
## Alternatives
|
|
147
|
+
|
|
148
|
+
- [skilldoctor](https://github.com/studiomeyer-io/skilldoctor), [skillcheck](https://github.com/erphq/skillcheck),
|
|
149
|
+
[claudelint](https://github.com/pdugan20/claudelint) and
|
|
150
|
+
[claude-plugins-validation](https://github.com/Emasoft/claude-plugins-validation) validate
|
|
151
|
+
the shape of skill, `CLAUDE.md` and subagent files: frontmatter schema, referenced paths,
|
|
152
|
+
security patterns. Some of them check a subagent's frontmatter fields as well. They stop at
|
|
153
|
+
the file; this tool continues into what the runtime does to it, which is where the tool
|
|
154
|
+
filters and the startup composition live.
|
|
155
|
+
- [rule-trace](https://github.com/seanleecoder/rule-trace) answers the same question at
|
|
156
|
+
runtime: it asks the agent to disclose which rules it applied, and counts those disclosures
|
|
157
|
+
over time. That needs your rules migrated into its format and a hook wired up. This tool is
|
|
158
|
+
static and needs nothing but the repository.
|
|
159
|
+
- `claude plugin validate` finds agent files whose frontmatter does not parse. It does not
|
|
160
|
+
flag a file that parses but has no `name`, and it does not model the tool filters.
|
|
161
|
+
|
|
162
|
+
## Related
|
|
163
|
+
|
|
164
|
+
- [rulereach](https://github.com/Topicspot/rulereach) - whether an instruction file reaches
|
|
165
|
+
the main agent at all: Codex, Claude Code, Cursor, Copilot.
|
|
166
|
+
- [skillfrisk](https://github.com/Topicspot/skillfrisk) - scan agent skills and MCP servers
|
|
167
|
+
for prompt injection and unsafe instructions.
|
|
168
|
+
- [ciparity](https://github.com/Topicspot/ciparity) - find drift between pre-commit hooks
|
|
169
|
+
and your CI pipeline.
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
MIT
|
|
Binary file
|