agt-env 0.0.3__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.
- agt_env-0.0.3/.github/workflows/ci.yml +68 -0
- agt_env-0.0.3/.github/workflows/pypi.yml +63 -0
- agt_env-0.0.3/.github/workflows/release.yml +53 -0
- agt_env-0.0.3/.gitignore +6 -0
- agt_env-0.0.3/AGENTS.md +63 -0
- agt_env-0.0.3/CLAUDE.md +1 -0
- agt_env-0.0.3/LICENSE +21 -0
- agt_env-0.0.3/PKG-INFO +45 -0
- agt_env-0.0.3/README.md +35 -0
- agt_env-0.0.3/docs/PRD.md +294 -0
- agt_env-0.0.3/docs/agents/README.md +63 -0
- agt_env-0.0.3/docs/agents/antigravity.md +119 -0
- agt_env-0.0.3/docs/agents/claude-code.md +139 -0
- agt_env-0.0.3/docs/agents/codex.md +125 -0
- agt_env-0.0.3/docs/agents/opencode.md +152 -0
- agt_env-0.0.3/docs/agents/pi.md +120 -0
- agt_env-0.0.3/pyproject.toml +31 -0
- agt_env-0.0.3/scripts/check_wheel.py +91 -0
- agt_env-0.0.3/src/agt_env/__init__.py +3 -0
- agt_env-0.0.3/src/agt_env/__main__.py +5 -0
- agt_env-0.0.3/src/agt_env/adapters/__init__.py +16 -0
- agt_env-0.0.3/src/agt_env/adapters/antigravity.py +306 -0
- agt_env-0.0.3/src/agt_env/adapters/base.py +266 -0
- agt_env-0.0.3/src/agt_env/adapters/claude_code.py +720 -0
- agt_env-0.0.3/src/agt_env/adapters/codex.py +539 -0
- agt_env-0.0.3/src/agt_env/adapters/opencode.py +598 -0
- agt_env-0.0.3/src/agt_env/adapters/pi.py +537 -0
- agt_env-0.0.3/src/agt_env/cli.py +206 -0
- agt_env-0.0.3/src/agt_env/filters.py +76 -0
- agt_env-0.0.3/src/agt_env/frontmatter.py +51 -0
- agt_env-0.0.3/src/agt_env/hooks.py +97 -0
- agt_env-0.0.3/src/agt_env/jsonc.py +19 -0
- agt_env-0.0.3/src/agt_env/mcp.py +97 -0
- agt_env-0.0.3/src/agt_env/model.py +85 -0
- agt_env-0.0.3/src/agt_env/render_plain.py +156 -0
- agt_env-0.0.3/src/agt_env/render_pretty.py +248 -0
- agt_env-0.0.3/src/agt_env/skills.py +208 -0
- agt_env-0.0.3/tests/conftest.py +150 -0
- agt_env-0.0.3/tests/test_antigravity_oracle.py +256 -0
- agt_env-0.0.3/tests/test_claude_oracle.py +514 -0
- agt_env-0.0.3/tests/test_cli.py +508 -0
- agt_env-0.0.3/tests/test_codex_oracle.py +595 -0
- agt_env-0.0.3/tests/test_detail.py +193 -0
- agt_env-0.0.3/tests/test_filters.py +168 -0
- agt_env-0.0.3/tests/test_findings.py +705 -0
- agt_env-0.0.3/tests/test_frontmatter.py +35 -0
- agt_env-0.0.3/tests/test_hooks_agents_commands.py +636 -0
- agt_env-0.0.3/tests/test_jsonc.py +28 -0
- agt_env-0.0.3/tests/test_mcp_extensions.py +484 -0
- agt_env-0.0.3/tests/test_new_adapters.py +989 -0
- agt_env-0.0.3/tests/test_opencode_oracle.py +511 -0
- agt_env-0.0.3/tests/test_pi_oracle.py +644 -0
- agt_env-0.0.3/tests/test_plugin_skills.py +596 -0
- agt_env-0.0.3/tests/test_render_pretty.py +568 -0
- agt_env-0.0.3/tests/test_safety.py +209 -0
- agt_env-0.0.3/tests/test_speed.py +55 -0
- agt_env-0.0.3/uv.lock +117 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7.0.1
|
|
16
|
+
with:
|
|
17
|
+
persist-credentials: false
|
|
18
|
+
|
|
19
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
20
|
+
|
|
21
|
+
- name: Check formatting
|
|
22
|
+
run: uvx ruff format --check
|
|
23
|
+
|
|
24
|
+
- name: Lint
|
|
25
|
+
run: uvx ruff check
|
|
26
|
+
|
|
27
|
+
- name: Lint workflows
|
|
28
|
+
run: uvx --from actionlint-py actionlint .github/workflows/*.yml
|
|
29
|
+
|
|
30
|
+
# Shared runners vary too much to fail on a time limit: the same code measured 209 ms and
|
|
31
|
+
# under 200 ms on two runs. This only reports the timings.
|
|
32
|
+
speed:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
continue-on-error: true
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v7.0.1
|
|
37
|
+
with:
|
|
38
|
+
persist-credentials: false
|
|
39
|
+
|
|
40
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
41
|
+
|
|
42
|
+
- name: Report speed
|
|
43
|
+
run: uv run pytest -s tests/test_speed.py
|
|
44
|
+
|
|
45
|
+
test:
|
|
46
|
+
strategy:
|
|
47
|
+
fail-fast: false
|
|
48
|
+
matrix:
|
|
49
|
+
os: [ubuntu-latest, macos-latest]
|
|
50
|
+
python: ["3.11", "3.14"]
|
|
51
|
+
runs-on: ${{ matrix.os }}
|
|
52
|
+
env:
|
|
53
|
+
UV_PYTHON: ${{ matrix.python }}
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/checkout@v7.0.1
|
|
56
|
+
with:
|
|
57
|
+
persist-credentials: false
|
|
58
|
+
|
|
59
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
60
|
+
|
|
61
|
+
- name: Run tests
|
|
62
|
+
run: uv run pytest --ignore=tests/test_speed.py
|
|
63
|
+
|
|
64
|
+
- name: Build
|
|
65
|
+
run: uv build
|
|
66
|
+
|
|
67
|
+
- name: Check the built package from a clean environment
|
|
68
|
+
run: uv run --no-project scripts/check_wheel.py dist/*.whl
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Uploads to PyPI when a release tagged v<version> is published by a person, or when
|
|
4
|
+
# release.yml starts this workflow on that tag.
|
|
5
|
+
on:
|
|
6
|
+
release:
|
|
7
|
+
types: [published]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7.0.1
|
|
18
|
+
with:
|
|
19
|
+
persist-credentials: false
|
|
20
|
+
|
|
21
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
22
|
+
|
|
23
|
+
- name: Check the release tag matches the project version
|
|
24
|
+
env:
|
|
25
|
+
TAG: ${{ github.event.release.tag_name || github.ref_name }}
|
|
26
|
+
run: |
|
|
27
|
+
version="$(uv version --short)"
|
|
28
|
+
if [ "$TAG" != "v$version" ]; then
|
|
29
|
+
echo "Release tag $TAG doesn't match project version $version" >&2
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# A slow runner shouldn't stop a release, so the speed test is left out.
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: uv run --python 3.11 pytest --ignore=tests/test_speed.py
|
|
36
|
+
|
|
37
|
+
- name: Build
|
|
38
|
+
run: uv build
|
|
39
|
+
|
|
40
|
+
- name: Check the built package from a clean environment
|
|
41
|
+
run: uv run --no-project scripts/check_wheel.py dist/*.whl
|
|
42
|
+
|
|
43
|
+
- uses: actions/upload-artifact@v7.0.2
|
|
44
|
+
with:
|
|
45
|
+
name: dist
|
|
46
|
+
path: dist/
|
|
47
|
+
if-no-files-found: error
|
|
48
|
+
|
|
49
|
+
publish:
|
|
50
|
+
needs: build
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
environment:
|
|
53
|
+
name: pypi
|
|
54
|
+
url: https://pypi.org/project/agt-env/
|
|
55
|
+
permissions:
|
|
56
|
+
id-token: write # PyPI trusted publishing, so no API token is stored
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/download-artifact@v8.0.2
|
|
59
|
+
with:
|
|
60
|
+
name: dist
|
|
61
|
+
path: dist/
|
|
62
|
+
|
|
63
|
+
- uses: pypa/gh-action-pypi-publish@v1.14.3
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Create release
|
|
2
|
+
|
|
3
|
+
# Pushing a tag v<project version> on a commit in main creates its release, then starts
|
|
4
|
+
# the PyPI workflow. A release made with GITHUB_TOKEN doesn't trigger other workflows,
|
|
5
|
+
# so pypi.yml has to be started explicitly.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
tags: ["v*"]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
release:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
actions: write # start pypi.yml
|
|
18
|
+
contents: write # create the release
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v7.0.1
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0 # needed to check the commit is in main
|
|
23
|
+
persist-credentials: false
|
|
24
|
+
|
|
25
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
26
|
+
|
|
27
|
+
- name: Check the tag matches the project version
|
|
28
|
+
run: |
|
|
29
|
+
version="$(uv version --short)"
|
|
30
|
+
if [ "$GITHUB_REF_NAME" != "v$version" ]; then
|
|
31
|
+
echo "Tag $GITHUB_REF_NAME doesn't match project version $version" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
- name: Check the tagged commit is in main
|
|
36
|
+
run: |
|
|
37
|
+
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
|
|
38
|
+
echo "Tag $GITHUB_REF_NAME points at a commit that isn't in main" >&2
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
- name: Create release and start publishing
|
|
43
|
+
env:
|
|
44
|
+
GH_TOKEN: ${{ github.token }}
|
|
45
|
+
run: |
|
|
46
|
+
# A release published in the browser also pushes its tag, and starts pypi.yml itself.
|
|
47
|
+
if gh release view "$GITHUB_REF_NAME" > /dev/null 2>&1; then
|
|
48
|
+
echo "Release $GITHUB_REF_NAME already exists" >> "$GITHUB_STEP_SUMMARY"
|
|
49
|
+
exit 0
|
|
50
|
+
fi
|
|
51
|
+
gh release create "$GITHUB_REF_NAME" --verify-tag --title "$GITHUB_REF_NAME" --generate-notes
|
|
52
|
+
gh workflow run pypi.yml --ref "$GITHUB_REF_NAME"
|
|
53
|
+
echo "Created $GITHUB_REF_NAME and started pypi.yml" >> "$GITHUB_STEP_SUMMARY"
|
agt_env-0.0.3/.gitignore
ADDED
agt_env-0.0.3/AGENTS.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to coding agents when working with code in this repository. `CLAUDE.md` is a symlink to it.
|
|
4
|
+
|
|
5
|
+
`agt-env` is a read-only CLI that lists the skills, MCP servers, plugins, hooks, subagents, and commands each coding agent can use from the current directory. Requirements are in `docs/PRD.md`.
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
uv run agt-env # run from source
|
|
11
|
+
uv run pytest # all tests; real-agent comparisons are skipped
|
|
12
|
+
uv run pytest tests/test_cli.py::test_filters # one test
|
|
13
|
+
uv run --isolated --python 3.11 --group dev pytest # oldest supported Python
|
|
14
|
+
uvx ruff format # format; configured in pyproject.toml
|
|
15
|
+
uvx ruff check # lint
|
|
16
|
+
uvx --from actionlint-py actionlint .github/workflows/*.yml
|
|
17
|
+
uv build && uv run --no-project scripts/check_wheel.py dist/*.whl # the built wheel, as a new user runs it
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Real-agent comparison tests run only when given a binary, and always use a temporary `HOME`. Pass the real binary, because a version-manager shim may not work in a temporary `HOME` (with mise, use `mise which codex`):
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
AGT_ENV_CLAUDE=... AGT_ENV_CODEX=... AGT_ENV_OPENCODE=... AGT_ENV_PI=... AGT_ENV_AGY=... uv run pytest
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
`cli.py` runs every adapter in `adapters.ADAPTERS` (registry order is display order), marks skills shared between agents by real path, and passes what `filters.py` selects to an output: `render_pretty.py` (Rich) on a color terminal, otherwise `render_plain.py` (plain text, whose exact form scripts can rely on). It hides agents that aren't both installed and configured, unless `--all` or `-a` is used.
|
|
29
|
+
|
|
30
|
+
Each adapter returns an `AgentReport`: install and config state, plus `Item`s (`model.py`). All agent-specific rules live in that adapter. Shared helpers are in `adapters/base.py` (reading config, building items), `skills.py` (scanning, with per-agent options for depth and hidden directories), `mcp.py` (safe server summaries), `hooks.py` (hook entries and safe summaries), `frontmatter.py`, and `jsonc.py`.
|
|
31
|
+
|
|
32
|
+
Adapters are independent of each other. The same directory can be scanned by several adapters, because agents read each other's skill directories.
|
|
33
|
+
|
|
34
|
+
## Rules that span the code
|
|
35
|
+
|
|
36
|
+
- **Default commands only read files.** They never run agent binaries, start MCP servers, or load plugins. `shutil.which` is the only install check.
|
|
37
|
+
- **Secret values must never reach an `Item`.** MCP `details` come from `mcp.py`, which keeps env and header names only, drops arguments, and strips URL credentials and queries. Plugin and package names go through `without_credentials`, and a hook's text goes through `masked`, the one place free text reaches an `Item`. Masking recognizes common forms, not every secret, so add a form there and to the tests when one is missed. Credential stores are never opened, and `skills.py` won't follow a skill file's symlink to a non-Markdown file. `tests/test_safety.py` checks this, and that nothing is written, by auditing what a real run opens; add new credential locations there and to `docs/agents/README.md`.
|
|
38
|
+
- **Inspected text is untrusted.** Everything printed goes through `render_plain.clean()`, and reaches Rich only as a `Text`, because Rich parses plain strings as markup. Files are read with a size limit, and non-regular files aren't opened.
|
|
39
|
+
- **Status needs evidence.** Use `unknown` rather than guessing `enabled`, and `pending` when an item waits on user approval or trust. A `broken` item always has a finding that says why, which every scan in the tests checks. `shadowed` needs a precedence rule with evidence, recorded in the agent's doc page, and adapters call `mark_shadowed` with items in that order. A config file that can't be read gives a warning and `unknown`, and must not affect other agents.
|
|
40
|
+
- **The current directory, or `--project`, is the project root.** Parent directories aren't searched, even for agents that search them.
|
|
41
|
+
|
|
42
|
+
## Changing agent rules
|
|
43
|
+
|
|
44
|
+
Agent docs are often incomplete or wrong, so check behavior against the real agent, in a temporary `HOME`. When rules change, update both the adapter and its `docs/agents/<agent>.md`, which is the single record of each rule and whether it's documented or tested. Adapter header comments only point to that file.
|
|
45
|
+
|
|
46
|
+
To add an agent, write the adapter, a line in `adapters/__init__.py`, a doc page, and tests. The priority order is in the PRD.
|
|
47
|
+
|
|
48
|
+
Tests must stay isolated: the `machine` fixture in `tests/conftest.py` provides a temporary `HOME`, an empty `PATH`, and a redirected `system_root`.
|
|
49
|
+
|
|
50
|
+
OpenCode's comparison tests start a background service, so they give it its own port and stop it afterwards. Don't stop a service running under a real `HOME`.
|
|
51
|
+
|
|
52
|
+
## Docs
|
|
53
|
+
|
|
54
|
+
- Keep `docs/PRD.md` independent of any one machine: no personal paths or installed tools, and no scope or priority decided by them. Use placeholder examples.
|
|
55
|
+
- Don't change the document version in the PRD unless asked.
|
|
56
|
+
|
|
57
|
+
## Releasing
|
|
58
|
+
|
|
59
|
+
Before tagging, run the real-agent comparison tests above, because CI doesn't have the agents.
|
|
60
|
+
|
|
61
|
+
The version is in both `pyproject.toml` and `src/agt_env/__init__.py`, and `uv.lock` must be refreshed with `uv lock`. The workflows only check the tag against `pyproject.toml`.
|
|
62
|
+
|
|
63
|
+
Pushing a tag `v<version>` on a commit in `main` runs `release.yml`, which creates the GitHub release and starts `pypi.yml`. A release created by a workflow can't trigger other workflows, so `release.yml` starts `pypi.yml` explicitly. `pypi.yml` uploads through PyPI trusted publishing, with environment `pypi`.
|
agt_env-0.0.3/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
agt_env-0.0.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xgzeng
|
|
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.
|
agt_env-0.0.3/PKG-INFO
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: agt-env
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: List the skills, MCP servers, and extensions available to each coding agent
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: rich>=14.3
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# agt-env
|
|
12
|
+
|
|
13
|
+
A read-only CLI that shows what each coding agent on your machine can use from the current directory.
|
|
14
|
+
|
|
15
|
+
**Status:** early development. It currently lists **skills**, **MCP servers**, **plugins**, **hooks**, **subagents**, and **commands** for **Claude Code**, **Codex**, **OpenCode**, **Pi**, and **Antigravity CLI**. More agents are planned; see the [product requirements](docs/PRD.md). [Agent discovery rules](docs/agents/README.md) describes how each agent finds these.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
Run it from your project root to include project-level configuration. No install is needed with [uv](https://docs.astral.sh/uv/):
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
uvx agt-env # list everything for active agents
|
|
23
|
+
uvx agt-env --all # also show agents not both installed and configured
|
|
24
|
+
uvx agt-env -a codex -k mcp # filter by agent and kind
|
|
25
|
+
uvx agt-env -n my-skill --detail # filter by name, and add paths and other details
|
|
26
|
+
uvx agt-env "browser test" lint # search all fields: (browser and test) or lint
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`agt-env` only reads files. It never changes your configuration or runs your agents.
|
|
30
|
+
|
|
31
|
+
Output is plain text when piped, or with `--no-color` or `NO_COLOR`.
|
|
32
|
+
|
|
33
|
+
Problems are shown with the items they affect: why an item is `broken`, and when a same-named item is used instead (`shadowed`). Search for them like anything else, as in `uvx agt-env shadowed`.
|
|
34
|
+
|
|
35
|
+
## Development
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
uv run agt-env # run from source
|
|
39
|
+
uv run pytest # run the tests
|
|
40
|
+
|
|
41
|
+
# Also compare results with real agents, in a temporary HOME
|
|
42
|
+
AGT_ENV_CLAUDE=/path/to/claude AGT_ENV_CODEX=/path/to/codex \
|
|
43
|
+
AGT_ENV_OPENCODE=/path/to/opencode AGT_ENV_PI=/path/to/pi AGT_ENV_AGY=/path/to/agy \
|
|
44
|
+
uv run pytest
|
|
45
|
+
```
|
agt_env-0.0.3/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# agt-env
|
|
2
|
+
|
|
3
|
+
A read-only CLI that shows what each coding agent on your machine can use from the current directory.
|
|
4
|
+
|
|
5
|
+
**Status:** early development. It currently lists **skills**, **MCP servers**, **plugins**, **hooks**, **subagents**, and **commands** for **Claude Code**, **Codex**, **OpenCode**, **Pi**, and **Antigravity CLI**. More agents are planned; see the [product requirements](docs/PRD.md). [Agent discovery rules](docs/agents/README.md) describes how each agent finds these.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Run it from your project root to include project-level configuration. No install is needed with [uv](https://docs.astral.sh/uv/):
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
uvx agt-env # list everything for active agents
|
|
13
|
+
uvx agt-env --all # also show agents not both installed and configured
|
|
14
|
+
uvx agt-env -a codex -k mcp # filter by agent and kind
|
|
15
|
+
uvx agt-env -n my-skill --detail # filter by name, and add paths and other details
|
|
16
|
+
uvx agt-env "browser test" lint # search all fields: (browser and test) or lint
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`agt-env` only reads files. It never changes your configuration or runs your agents.
|
|
20
|
+
|
|
21
|
+
Output is plain text when piped, or with `--no-color` or `NO_COLOR`.
|
|
22
|
+
|
|
23
|
+
Problems are shown with the items they affect: why an item is `broken`, and when a same-named item is used instead (`shadowed`). Search for them like anything else, as in `uvx agt-env shadowed`.
|
|
24
|
+
|
|
25
|
+
## Development
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
uv run agt-env # run from source
|
|
29
|
+
uv run pytest # run the tests
|
|
30
|
+
|
|
31
|
+
# Also compare results with real agents, in a temporary HOME
|
|
32
|
+
AGT_ENV_CLAUDE=/path/to/claude AGT_ENV_CODEX=/path/to/codex \
|
|
33
|
+
AGT_ENV_OPENCODE=/path/to/opencode AGT_ENV_PI=/path/to/pi AGT_ENV_AGY=/path/to/agy \
|
|
34
|
+
uv run pytest
|
|
35
|
+
```
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# agt-env: Product Requirements
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
|---|---|
|
|
5
|
+
| **Status** | Draft v0.1 |
|
|
6
|
+
| **Date** | 2026-10-30 |
|
|
7
|
+
| **Name** | `agt-env` (command and package) |
|
|
8
|
+
|
|
9
|
+
## 1. Summary
|
|
10
|
+
|
|
11
|
+
`agt-env` is a read-only CLI that answers one question: **what can each coding agent on my machine use from this directory?** It finds the skills, MCP servers, and plugins configured for each agent, puts them in one model, and shows them in the terminal.
|
|
12
|
+
|
|
13
|
+
## 2. Problem
|
|
14
|
+
|
|
15
|
+
Anyone running several coding agents has capabilities scattered across incompatible locations and formats, and no single place to see them. Common situations make this harder than listing a few directories:
|
|
16
|
+
|
|
17
|
+
| Situation | Why it matters |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Each agent has its own locations, file formats, scopes, and terminology | Checking each one by hand doesn't scale past one or two agents |
|
|
20
|
+
| The same skill can be linked or copied into several agents' directories | A plain listing overstates what exists and hides what is shared |
|
|
21
|
+
| Copies of a skill can change independently | Agents can end up with different versions and no warning |
|
|
22
|
+
| Agents may cache plugins they haven't enabled | Treating a directory's contents as available would mislead |
|
|
23
|
+
| An agent can be installed but unconfigured, or leave config behind after being uninstalled | "Installed" and "configured" are separate states |
|
|
24
|
+
| Some capabilities are built into the agent or attached to a cloud account | Files on disk don't describe everything available at runtime |
|
|
25
|
+
| Agent CLIs can be slow to start, need authentication or network access, or have side effects | Calling each CLI is too slow and unreliable to be the default |
|
|
26
|
+
|
|
27
|
+
## 3. Goals and non-goals
|
|
28
|
+
|
|
29
|
+
### Goals
|
|
30
|
+
|
|
31
|
+
1. List capabilities across all agents in one command, with no setup, including no prior install.
|
|
32
|
+
2. Be accurate about what is known: report status and source, and say "unknown" rather than guess.
|
|
33
|
+
3. Resolve context from the current directory, covering both user and project scope.
|
|
34
|
+
4. Expose shared, duplicated, and shadowed items instead of hiding them.
|
|
35
|
+
5. Make adding a new agent a small, isolated change.
|
|
36
|
+
|
|
37
|
+
### Non-goals (v1)
|
|
38
|
+
|
|
39
|
+
- **Changing anything:** no install, remove, enable, disable, or sync. These may come later, but v1 is strictly read-only.
|
|
40
|
+
- **Machine-readable output:** v1 is for people reading a terminal. JSON or similar output may come later.
|
|
41
|
+
- **Marketplace browsing:** v1 covers what is on the local machine, not what could be installed.
|
|
42
|
+
- **Exact session state:** v1 doesn't report what a particular running session has loaded.
|
|
43
|
+
- **Account-level discovery:** remote connectors that exist only in an agent's cloud account aren't enumerated.
|
|
44
|
+
- **Windows support:** Linux and macOS come first.
|
|
45
|
+
|
|
46
|
+
## 4. Users
|
|
47
|
+
|
|
48
|
+
- **Primary: multi-agent developer.** Switches between agents and wants to know why one of them can't see a skill or MCP server.
|
|
49
|
+
- **Secondary: security-conscious user.** Audits what is configured, especially in an unfamiliar repository.
|
|
50
|
+
|
|
51
|
+
### Core scenarios
|
|
52
|
+
|
|
53
|
+
1. "What do I have across all my agents?" → `agt-env`
|
|
54
|
+
2. "Which MCP servers can Codex use here?" → `agt-env -a codex -k mcp`
|
|
55
|
+
3. "Where does this skill come from, and who else has it?" → `agt-env -n my-skill --detail`
|
|
56
|
+
4. "What does this repo add to my agents?" → `agt-env --scope project`
|
|
57
|
+
|
|
58
|
+
## 5. Functional requirements
|
|
59
|
+
|
|
60
|
+
Priorities: **P0** is required for v1, **P1** follows soon after, and **P2** is later.
|
|
61
|
+
|
|
62
|
+
### 5.1 Commands
|
|
63
|
+
|
|
64
|
+
| Command | Purpose | Priority |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `agt-env [keyword...]` | Agents and their items, filterable | P0 |
|
|
67
|
+
| `agt-env probe` | Opt-in live checks through agent CLIs (see 5.5) | P2 |
|
|
68
|
+
|
|
69
|
+
Agents appear in rank order (see section 6), each with a header showing its state and config location, followed by its items sorted by scope (project, user, system), then kind, then name.
|
|
70
|
+
|
|
71
|
+
**Flags:** `--all`, `--detail`, `-a`/`--agent <agent>` (repeatable), `-n`/`--name <text>` (repeatable), `-k`/`--kind <kind>` (repeatable), `-s`/`--scope project|user|system`, `-p`/`--project <path>`, `--no-color`.
|
|
72
|
+
|
|
73
|
+
**Filters:** different filters narrow each other.
|
|
74
|
+
|
|
75
|
+
- `-a` shows only the named agents, even ones hidden by default. It takes an agent's ID, or `claude` for `claude-code` and `agy` for `antigravity`.
|
|
76
|
+
- `-n` matches a case-insensitive part of the item name. Repeating it widens the results.
|
|
77
|
+
- Keywords match a case-insensitive part of everything shown for an item, including its details and path. Words in one argument narrow and separate arguments widen, so `agt-env "browser test" lint` finds (browser and test) or lint.
|
|
78
|
+
- With `-n` or keywords, agents with no matches are left out. If none are left, the output says so.
|
|
79
|
+
|
|
80
|
+
**Illustrative output:**
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
$ agt-env
|
|
84
|
+
agent-a ~/.agent-a
|
|
85
|
+
SCOPE/KIND NAME STATUS
|
|
86
|
+
P/skill repo-skill enabled
|
|
87
|
+
U/skill my-skill enabled
|
|
88
|
+
U/mcp my-server enabled
|
|
89
|
+
U/plugin my-plugin disabled
|
|
90
|
+
|
|
91
|
+
agent-b /opt/agent-b (set by AGENT_B_HOME)
|
|
92
|
+
SCOPE/KIND NAME STATUS
|
|
93
|
+
U/skill my-skill enabled
|
|
94
|
+
U/plugin other unknown
|
|
95
|
+
|
|
96
|
+
Hidden: agent-c, agent-d. Use --all for details.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`P`, `U`, and `S` stand for the project, user, and system scopes. `--detail` adds lines under each item, starting at the `NAME` column, for everything the columns don't show, and a line of dashes after the table head and between items:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
$ agt-env -a agent-b -n my-skill --detail
|
|
103
|
+
agent-b /opt/agent-b (set by AGENT_B_HOME)
|
|
104
|
+
SCOPE/KIND NAME
|
|
105
|
+
--------------------
|
|
106
|
+
U/skill my-skill
|
|
107
|
+
Status: enabled
|
|
108
|
+
Description: Does a thing
|
|
109
|
+
Path: /opt/agent-b/skills/my-skill (symlink)
|
|
110
|
+
Real path: /opt/shared/my-skill
|
|
111
|
+
Shared with: agent-a
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
What a plugin brings is listed directly below its row, when that row is shown. If a filter hides the plugin, those items take their normal place.
|
|
115
|
+
|
|
116
|
+
Problems are shown with the items they affect, in the same output, with no separate command. Each finding is a row directly below its item, starting where the `DESCRIPTION` column starts, or at `NAME` if a narrow terminal leaves too little room. An agent without any looks as above. With `--detail`, each finding is a `Finding:` line among the item's details.
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
$ agt-env -a agent-a
|
|
120
|
+
agent-a ~/.agent-a
|
|
121
|
+
SCOPE/KIND NAME STATUS
|
|
122
|
+
P/skill my-skill shadowed
|
|
123
|
+
! shadowed by ~/.agent-a/skills/my-skill
|
|
124
|
+
U/skill my-skill enabled
|
|
125
|
+
U/skill old broken
|
|
126
|
+
! symlink target is missing
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Findings can be searched like everything else shown for an item, and they don't change the exit code. A config file that can't be read stays a warning on stderr (FR-17).
|
|
130
|
+
|
|
131
|
+
With `--all`, hidden agents are added with their state:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
agent-c not installed, configured at ~/.agent-c
|
|
135
|
+
agent-d installed, not configured
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 5.2 Capability kinds
|
|
139
|
+
|
|
140
|
+
| Kind | Meaning | Priority |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| `skill` | Skill directory or file, usually `SKILL.md` | P0 |
|
|
143
|
+
| `mcp` | Configured MCP server | P0 |
|
|
144
|
+
| `plugin` | Plugin or extension, with the agent's own term kept in `native_kind` | P0 |
|
|
145
|
+
| `hook` | Lifecycle hook | P1 |
|
|
146
|
+
| `subagent` | Custom agent definition | P1 |
|
|
147
|
+
| `command` | Custom slash command | P1 |
|
|
148
|
+
| `instructions` | Agent instruction and rules files | P2 |
|
|
149
|
+
|
|
150
|
+
### 5.3 Discovery
|
|
151
|
+
|
|
152
|
+
- **FR-1 (P0):** Detect each agent independently through its binary on `PATH` and its config locations, and report the two separately. An agent is configured if it has config at user or project scope. A version-manager shim on `PATH` counts as a binary, but detection must not execute it.
|
|
153
|
+
- **FR-2 (P0):** Discover items at user and project scope. The current directory, or `--project` if given, is assumed to be the project root. Parent directories are not searched, so running from a subdirectory doesn't find the project's items. System-level locations are read where the agent defines them.
|
|
154
|
+
- **FR-3 (P0):** Get all results by reading files on disk. Only `probe` (FR-14) may run other programs, so all other commands must not launch agent CLIs or start MCP servers.
|
|
155
|
+
- **FR-4 (P0):** Determine status from the agent's own configuration. An item in a plugin cache that is not enabled must not be reported as `enabled`.
|
|
156
|
+
- **FR-5 (P0):** Follow symlinks and record both the path found and the resolved path. Report a dangling symlink as `broken`.
|
|
157
|
+
- **FR-6 (P0):** Treat items that resolve to the same real path as shared, naming the other agents under `--detail`, while still listing them under each agent.
|
|
158
|
+
- **FR-8 (P1):** When an agent's precedence rules mean a same-named item is used instead, report the item as `shadowed` and show a finding naming the winner. Only rules with evidence count, so an agent whose rule isn't known is never flagged.
|
|
159
|
+
- **FR-23 (P1):** Show why each `broken` item is broken. The reason is fixed text, never file contents.
|
|
160
|
+
- **FR-24 (P1):** List hooks, custom agents, and custom commands wherever the agent has them, by the same rules as other items: a status from evidence, and the plugin named under `--detail`. A hook is named by its event and matcher unless the agent gives it a name. Its description is what it runs, with anything that looks like a secret masked (FR-12).
|
|
161
|
+
- **FR-9 (P1):** List skills that plugins and packages bring, under the name the agent gives them, such as `my-plugin:my-skill`, and with `--detail` name the plugin. A skill follows its plugin's status, and one whose plugin is off or missing isn't listed.
|
|
162
|
+
- **FR-10 (P0):** Only treat a directory as a skill if it meets the agent's definition. A directory that only groups other skills must be descended into or skipped, not counted.
|
|
163
|
+
- **FR-20 (P0):** Resolve locations from the environment, not fixed paths: honor `HOME`, XDG variables, and each agent's documented config-directory overrides. When an override moves an agent's location away from its default, the output shows the location in use and the variable that set it in the agent's header.
|
|
164
|
+
- **FR-21 (P0):** Work from any starting state. With no agents detected, or an agent's directories missing or unreadable, the tool still succeeds and says what it found. A missing location isn't a warning; an unreadable one is.
|
|
165
|
+
- **FR-22 (P0):** By default, only agents that are both installed and configured are shown, and the output names the agents it hid. `--all` shows every detected agent, and `-a` always shows the agent it names, in each case with its state.
|
|
166
|
+
|
|
167
|
+
### 5.4 Data model
|
|
168
|
+
|
|
169
|
+
Every item has these fields, and adapters must fill them consistently:
|
|
170
|
+
|
|
171
|
+
| Field | Meaning | Example |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| `id` | Unique identity of the item | `agent-a:skill:user:my-skill` |
|
|
174
|
+
| `name` | Display name | `my-skill` |
|
|
175
|
+
| `kind` | Normalized kind (see 5.2) | `plugin` |
|
|
176
|
+
| `native_kind` | The agent's own term | `plugin` |
|
|
177
|
+
| `agent` | Agent ID (see section 6) | `agent-a` |
|
|
178
|
+
| `scope` | `user`, `project`, or `system` | `user` |
|
|
179
|
+
| `status` | `enabled`, `disabled`, `pending` (waiting for the user to approve or trust it), `broken`, `shadowed` (a same-named item is used instead), or `unknown` | `enabled` |
|
|
180
|
+
| `description` | Short description, if the source has one | What the skill does and when to use it. |
|
|
181
|
+
| `source_path` | Where the item was found | `/home/me/.agent-a/skills/my-skill` |
|
|
182
|
+
| `resolved_path` | Real path after following symlinks | `/home/me/shared-skills/my-skill` |
|
|
183
|
+
| `shared_with` | Other agents using the same real path | `agent-b` |
|
|
184
|
+
| `details` | Kind-specific information | See below |
|
|
185
|
+
| `findings` | Problems to show with the item, such as why it's broken | `symlink target is missing` |
|
|
186
|
+
|
|
187
|
+
**MCP `details`** contains transport, command or URL, and the *names* of env vars and headers, never their values.
|
|
188
|
+
|
|
189
|
+
### 5.5 Safety
|
|
190
|
+
|
|
191
|
+
- **FR-11 (P0):** Never modify files in agent config directories or anywhere else.
|
|
192
|
+
- **FR-12 (P0):** Never display secret values in any output. Env values, header values, tokens, and URL credentials are omitted or masked. A hook's command or prompt is free text, so it's shown after masking the forms a secret usually takes, which can't catch a secret that looks like any other word. Agent credential stores are never opened. A skill file that is a symlink to anything but a Markdown file isn't opened, and the skill is reported as `broken`, because a skill's text can become its description and a cloned repository could otherwise display any file.
|
|
193
|
+
- **FR-13 (P0):** Never run code from inspected configuration. Listing an MCP server must not start it, because a repository's project config can name any command.
|
|
194
|
+
- **FR-14 (P2):** `probe` is the only command that may run other programs. It must be explicitly invoked, apply a timeout per agent, and show what it will execute.
|
|
195
|
+
- **FR-15 (P0):** Treat inspected file contents as untrusted. Strip terminal escape sequences from names and descriptions before display.
|
|
196
|
+
|
|
197
|
+
### 5.6 Output and errors
|
|
198
|
+
|
|
199
|
+
- **FR-16 (P0):** On a color terminal, show each agent in a colored panel, with a symbol and a color for each status. The status column has no words, and its heading is `S`. Scopes are written `Prj`, `Usr`, and `Sys` under the heading `SCOPE`, and the description starts with the item's kind, as in `SKILL: Does a thing`. Each kind other than `skill` has its own color on its name. With `--detail` there is no status column, in either output, and the status is one of the details. Use plain aligned text when piped, with `--no-color`, when `NO_COLOR` is set, when `TERM` is `dumb`, or when the output encoding isn't UTF-8. The illustrative output above is the plain form. Without `--detail`, the terminal table also shows the start of each description, cut to the space left in the terminal, and leaves the column out when too little space is left. Other long values wrap on a terminal and are never cut.
|
|
200
|
+
- **FR-17 (P0):** A broken config for one agent must not stop the others. It produces a warning on stderr naming the agent and file, and items from that agent's other sources still appear.
|
|
201
|
+
- **FR-18 (P0):** Exit codes: `0` for success, including partial results with warnings and empty results; `1` for a fatal runtime error; `2` for a usage error.
|
|
202
|
+
- **FR-19 (P0):** Unknown fields in agent configs are ignored without error, so a new agent release doesn't break parsing.
|
|
203
|
+
|
|
204
|
+
## 6. Agent support
|
|
205
|
+
|
|
206
|
+
Each agent is one adapter behind a common interface: detect the agent, then return items and warnings. An adapter must not depend on any other adapter.
|
|
207
|
+
|
|
208
|
+
Adapters are built in rank order. P0 agents are required for v1, and P2 agents are added after v1, when there is demand.
|
|
209
|
+
|
|
210
|
+
| Rank | Agent | ID | Priority |
|
|
211
|
+
|---|---|---|---|
|
|
212
|
+
| 1 | Claude Code | `claude-code` | P0 |
|
|
213
|
+
| 2 | Codex | `codex` | P0 |
|
|
214
|
+
| 3 | OpenCode | `opencode` | P0 |
|
|
215
|
+
| 4 | Pi | `pi` | P0 |
|
|
216
|
+
| 5 | Antigravity CLI | `antigravity` | P0 |
|
|
217
|
+
| 6 | Gemini CLI | `gemini` | P2 |
|
|
218
|
+
| 7 | Cursor | `cursor` | P2 |
|
|
219
|
+
| 8 | GitHub Copilot CLI | `copilot` | P2 |
|
|
220
|
+
| 9 | Amp | `amp` | P2 |
|
|
221
|
+
| 10 | Qwen Code | `qwen` | P2 |
|
|
222
|
+
| 11 | Crush | `crush` | P2 |
|
|
223
|
+
| 12 | Kiro | `kiro` | P2 |
|
|
224
|
+
| 13 | Goose | `goose` | P2 |
|
|
225
|
+
| 14 | Cline | `cline` | P2 |
|
|
226
|
+
| 15 | Windsurf | `windsurf` | P2 |
|
|
227
|
+
|
|
228
|
+
The ranking can change without affecting the architecture.
|
|
229
|
+
|
|
230
|
+
### Adapter rules
|
|
231
|
+
|
|
232
|
+
- Each adapter declares its locations, formats, scopes, and precedence rules, taken from the agent's documentation and a clean install. They live with the adapter rather than in this PRD, because they change with agent releases.
|
|
233
|
+
- Every format claim in an adapter is backed by a fixture and the agent version it was checked against.
|
|
234
|
+
- Tests run against fixtures in an isolated `HOME`, never against a developer's real configuration.
|
|
235
|
+
- Where an agent has a read-only listing command, it is used as a test oracle during development, not at runtime.
|
|
236
|
+
- An adapter attributes a cross-agent shared location to an agent only if that agent is confirmed to read it.
|
|
237
|
+
- Agents without an adapter are ignored: they aren't detected, listed, or mentioned in any output.
|
|
238
|
+
|
|
239
|
+
## 7. Non-functional requirements
|
|
240
|
+
|
|
241
|
+
| Area | Requirement |
|
|
242
|
+
|---|---|
|
|
243
|
+
| **Performance** | The default listing finishes in under 200 ms, in plain and terminal output, on a reference fixture of 5 agents and 500 items, on a typical developer laptop; no subprocesses are spawned. The target excludes the time `uvx` needs to set up its environment |
|
|
244
|
+
| **Distribution** | Published to PyPI and runnable with `uvx agt-env`, with no prior install; `uv tool install` also works. Requires Python 3.11 or later, with as few third-party dependencies as practical; Rich is used for terminal output, and plain output doesn't load it |
|
|
245
|
+
| **Portability** | Linux and macOS, on any home directory layout, shell, or version manager |
|
|
246
|
+
| **Extensibility** | A new adapter touches only its own module, fixtures, and one registry line |
|
|
247
|
+
|
|
248
|
+
**Implementation language:** Python.
|
|
249
|
+
|
|
250
|
+
## 8. Success metrics
|
|
251
|
+
|
|
252
|
+
These are acceptance checks, run against fixtures in CI, except where noted:
|
|
253
|
+
|
|
254
|
+
1. **Accuracy:** for each P0 agent, MCP results match that agent's own listing command on the same fixture, wherever such a command exists. This needs the real agents, and some need a signed-in account, so it runs by hand before each release rather than in CI.
|
|
255
|
+
2. **No false claims:** no item is reported as `enabled` without evidence in that agent's config.
|
|
256
|
+
3. **Secret safety:** a test config with planted secrets produces no secret text in any command's output, planted credential stores are never opened, and no file changes.
|
|
257
|
+
4. **Inertness:** a test project config naming a marker-writing command leaves no marker after any P0 command.
|
|
258
|
+
5. **Resilience:** corrupting any single agent's config still produces full results for the others, with exit code 0 and a warning.
|
|
259
|
+
6. **Clean start:** with an empty `HOME` and no agents on `PATH`, `agt-env` exits 0 with a clear message.
|
|
260
|
+
7. **Speed:** the 200 ms target holds on the reference fixture on a developer machine. CI only reports the timings, because shared runners vary too much for a time limit.
|
|
261
|
+
8. **Zero-install run:** in a clean environment, `uvx` runs the built package and `agt-env` produces correct output.
|
|
262
|
+
|
|
263
|
+
## 9. Risks
|
|
264
|
+
|
|
265
|
+
| Risk | Mitigation |
|
|
266
|
+
|---|---|
|
|
267
|
+
| Agent formats change often and without notice | Tolerant parsing, per-adapter fixtures, and visible warnings instead of crashes |
|
|
268
|
+
| Users read the output as exactly what a session has loaded | Label output as configured state; document the gaps; add `probe` later |
|
|
269
|
+
| Enablement rules are undocumented or complex | Use `unknown` status rather than guessing |
|
|
270
|
+
| Secrets leak through unexpected fields, such as credentials in MCP args | Allowlist the fields to display; mask URL credentials and values following secret-like flags |
|
|
271
|
+
| Terminal injection through a malicious skill description | Sanitize all displayed strings (FR-15) |
|
|
272
|
+
|
|
273
|
+
## 10. Milestones
|
|
274
|
+
|
|
275
|
+
1. **M1, foundation:** data model, adapter interface, skill discovery, Claude Code and Codex adapters, listing, packaging for `uvx`.
|
|
276
|
+
2. **M2, P0 complete:** remaining P0 adapters, MCP and plugins, details and filters, safety tests.
|
|
277
|
+
3. **M3, diagnostics:** findings in the normal output (why items are broken, and shadowing), plugin-bundled skills, hooks, subagents, commands.
|
|
278
|
+
4. **M4, breadth:** `probe`, and P2 adapters in rank order as demand appears.
|
|
279
|
+
|
|
280
|
+
## 11. Decisions and open questions
|
|
281
|
+
|
|
282
|
+
### Decisions made for this draft
|
|
283
|
+
|
|
284
|
+
| Decision | Reasoning |
|
|
285
|
+
|---|---|
|
|
286
|
+
| Read-only in v1 | Keeps the tool safe to run anywhere and the scope small |
|
|
287
|
+
| Static inspection by default | Fast and inert, with no dependence on an agent's startup, authentication, or network |
|
|
288
|
+
| Unified `plugin` kind | "Plugin" and "extension" vary by agent; `native_kind` keeps the original term |
|
|
289
|
+
| Shared items listed under each agent | Each agent really can use them; sharing is shown separately |
|
|
290
|
+
|
|
291
|
+
### Open questions
|
|
292
|
+
|
|
293
|
+
1. **Runtime gap:** should built-in skills and account-level connectors, which aren't in local config, be documented as out of scope permanently, or added through `probe`?
|
|
294
|
+
2. **Shared skill directories:** some skill directories sit outside any one agent's own config and may be read by several agents. Which of these directories exist, and which agents read each one? This decides which agents a skill is listed under: the output could otherwise claim an agent has a skill it never loads, or miss one it does. The answer is needed for each agent when its adapter is built. Until it is confirmed, skills from that directory aren't listed under that agent.
|