legwork-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. legwork_mcp-0.1.0/.github/workflows/ci.yml +16 -0
  2. legwork_mcp-0.1.0/.github/workflows/publish.yml +49 -0
  3. legwork_mcp-0.1.0/.gitignore +7 -0
  4. legwork_mcp-0.1.0/CLAUDE.md +20 -0
  5. legwork_mcp-0.1.0/LICENSE +21 -0
  6. legwork_mcp-0.1.0/PKG-INFO +189 -0
  7. legwork_mcp-0.1.0/README.md +170 -0
  8. legwork_mcp-0.1.0/docs/designs/legwork-jit-ai-runtime.md +1079 -0
  9. legwork_mcp-0.1.0/docs/designs/legwork-live-runs-2026-09-25.md +89 -0
  10. legwork_mcp-0.1.0/docs/designs/legwork-trending-trial-2026-09-26.md +83 -0
  11. legwork_mcp-0.1.0/docs/designs/legwork-validation-spike-2026-09-22.md +147 -0
  12. legwork_mcp-0.1.0/legwork/__init__.py +1 -0
  13. legwork_mcp-0.1.0/legwork/cache_writer.py +357 -0
  14. legwork_mcp-0.1.0/legwork/cli.py +251 -0
  15. legwork_mcp-0.1.0/legwork/codegen.py +238 -0
  16. legwork_mcp-0.1.0/legwork/llm_client.py +160 -0
  17. legwork_mcp-0.1.0/legwork/local_store.py +88 -0
  18. legwork_mcp-0.1.0/legwork/obfuscation_scanner.py +255 -0
  19. legwork_mcp-0.1.0/legwork/readme_parser.py +272 -0
  20. legwork_mcp-0.1.0/legwork/repo_fetcher.py +188 -0
  21. legwork_mcp-0.1.0/legwork/retry_loop.py +261 -0
  22. legwork_mcp-0.1.0/legwork/sandbox_runner.py +347 -0
  23. legwork_mcp-0.1.0/pyproject.toml +37 -0
  24. legwork_mcp-0.1.0/tests/__init__.py +0 -0
  25. legwork_mcp-0.1.0/tests/fixtures/README.md +25 -0
  26. legwork_mcp-0.1.0/tests/fixtures/ai_data_extractor_payload.py +45 -0
  27. legwork_mcp-0.1.0/tests/fixtures/clean_plugin_loader.py +16 -0
  28. legwork_mcp-0.1.0/tests/mcp_stdio_client.py +77 -0
  29. legwork_mcp-0.1.0/tests/test_cache_writer.py +350 -0
  30. legwork_mcp-0.1.0/tests/test_cli.py +180 -0
  31. legwork_mcp-0.1.0/tests/test_codegen.py +211 -0
  32. legwork_mcp-0.1.0/tests/test_llm_client.py +177 -0
  33. legwork_mcp-0.1.0/tests/test_local_store.py +47 -0
  34. legwork_mcp-0.1.0/tests/test_obfuscation_scanner.py +201 -0
  35. legwork_mcp-0.1.0/tests/test_pipeline_integration.py +56 -0
  36. legwork_mcp-0.1.0/tests/test_readme_parser.py +206 -0
  37. legwork_mcp-0.1.0/tests/test_repo_fetcher.py +160 -0
  38. legwork_mcp-0.1.0/tests/test_retry_loop.py +298 -0
  39. legwork_mcp-0.1.0/tests/test_retry_loop_integration.py +86 -0
  40. legwork_mcp-0.1.0/tests/test_sandbox_runner.py +297 -0
  41. legwork_mcp-0.1.0/tests/test_serve_integration.py +84 -0
  42. legwork_mcp-0.1.0/uv.lock +156 -0
@@ -0,0 +1,16 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ # The sandbox is macOS sandbox-exec, so the real tests need macOS.
11
+ runs-on: macos-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v6
15
+ - run: uv sync
16
+ - run: uv run pytest -q
@@ -0,0 +1,49 @@
1
+ name: publish
2
+
3
+ # Push a tag like v0.1.0 to publish that version to PyPI. Uses PyPI trusted
4
+ # publishing: no API token exists anywhere. The PyPI project must list this
5
+ # repo, this workflow file and the `pypi` environment as a trusted publisher.
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: macos-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: astral-sh/setup-uv@v6
16
+ - run: uv sync
17
+ - run: uv run pytest -q
18
+
19
+ build:
20
+ needs: test
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: astral-sh/setup-uv@v6
25
+ - name: Tag must match the package version
26
+ run: |
27
+ version=$(uv version --short)
28
+ if [ "v$version" != "$GITHUB_REF_NAME" ]; then
29
+ echo "Tag $GITHUB_REF_NAME doesn't match pyproject version $version" >&2
30
+ exit 1
31
+ fi
32
+ - run: uv build
33
+ - uses: actions/upload-artifact@v4
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+
38
+ pypi:
39
+ needs: build
40
+ runs-on: ubuntu-latest
41
+ environment: pypi
42
+ permissions:
43
+ id-token: write
44
+ steps:
45
+ - uses: actions/download-artifact@v4
46
+ with:
47
+ name: dist
48
+ path: dist/
49
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .pytest_cache/
4
+ *.egg-info/
5
+ .venv/
6
+ dist/
7
+ .ruff_cache/
@@ -0,0 +1,20 @@
1
+ # AwesomeAI
2
+
3
+ ## Skill routing
4
+
5
+ When the user's request matches an available skill, invoke it via the Skill tool. When in doubt, invoke the skill.
6
+
7
+ Key routing rules:
8
+ - Product ideas/brainstorming → invoke /office-hours
9
+ - Strategy/scope → invoke /plan-ceo-review
10
+ - Architecture → invoke /plan-eng-review
11
+ - Design system/plan review → invoke /design-consultation or /plan-design-review
12
+ - Full review pipeline → invoke /autoplan
13
+ - Bugs/errors → invoke /investigate
14
+ - QA/testing site behavior → invoke /qa or /qa-only
15
+ - Code review/diff check → invoke /review
16
+ - Visual polish → invoke /design-review
17
+ - Ship/deploy/PR → invoke /ship or /land-and-deploy
18
+ - Save progress → invoke /context-save
19
+ - Resume context → invoke /context-restore
20
+ - Author a backlog-ready spec/issue → invoke /spec
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kumar Ganduri and Legwork contributors
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,189 @@
1
+ Metadata-Version: 2.5
2
+ Name: legwork-mcp
3
+ Version: 0.1.0
4
+ Summary: Point it at a GitHub repo, get a working MCP tool back.
5
+ Project-URL: Homepage, https://github.com/kumarganduri/legwork
6
+ Project-URL: Repository, https://github.com/kumarganduri/legwork
7
+ Project-URL: Issues, https://github.com/kumarganduri/legwork/issues
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,codegen,llm,mcp,model-context-protocol,sandbox
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Software Development :: Code Generators
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Legwork
21
+
22
+ **Point it at a GitHub repo, get a working MCP tool back.**
23
+
24
+ Legwork reads a repo's README, has your LLM write an
25
+ [MCP](https://modelcontextprotocol.io) wrapper for it, installs it in a
26
+ sandbox, and proves it runs before handing it to Claude Code, Cursor or any
27
+ other MCP client. If a repo can't be wrapped, it says why instead of
28
+ producing something broken.
29
+
30
+ ```sh
31
+ uvx legwork-mcp owner/repo
32
+ ```
33
+
34
+ ## Proof, not a pitch
35
+
36
+ On 2026-09-26 we ran Legwork against **this week's 10 most-starred new AI
37
+ repos on GitHub**, taken exactly as search ranked them, with nothing skipped
38
+ for being hard:
39
+
40
+ | Outcome | Repos |
41
+ |---|---|
42
+ | ✅ Built a working MCP server | **3** — an npm CLI, a Python library, a Go binary |
43
+ | ↩️ Refused, with the right reason | **5** — two Android/macOS apps, a desktop app, a repo with no usage docs, a tool that needs its own API keys |
44
+ | 🛑 Blocked as malware | **2** |
45
+
46
+ Two of the week's top-10 "AI tools", about 700 stars each and three days
47
+ old, carried the same byte-identical obfuscated dropper under different
48
+ file names. Legwork's pre-install scan refused both in about a second.
49
+ Nothing from them was installed or run. Stars are not a trust signal.
50
+
51
+ Full write-up, including what failed along the way and what we fixed:
52
+ [docs/designs/legwork-trending-trial-2026-09-26.md](docs/designs/legwork-trending-trial-2026-09-26.md).
53
+
54
+ ## Quick start
55
+
56
+ You need **macOS**, [uv](https://docs.astral.sh/uv/), and any
57
+ OpenAI-compatible chat-completions endpoint. Legwork itself is free; the
58
+ only cost is your own model usage, which is 1–3 calls per build.
59
+
60
+ ```sh
61
+ export LEGWORK_LLM_ENDPOINT=https://api.openai.com/v1
62
+ export LEGWORK_LLM_API_KEY=... # your own key; never a CLI flag
63
+ export LEGWORK_LLM_MODEL=gpt-5
64
+
65
+ uvx legwork-mcp 2akouwu/reverify
66
+ ```
67
+
68
+ A build takes 1–3 minutes and ends with the line to connect it:
69
+
70
+ ```
71
+ Built an MCP wrapper for 2akouwu/reverify on attempt 2 of 3.
72
+ What it wraps: Verify claims about binaries using Reverify's deterministic tools (wraps `reverify verify --json`)
73
+
74
+ Connect it to Claude Code:
75
+ claude mcp add reverify -- ~/.local/bin/uvx legwork-mcp serve 2akouwu/reverify
76
+ ```
77
+
78
+ It also prints an `mcpServers` block for Claude Desktop, Cursor and other
79
+ clients. For a permanent `legwork` command: `uv tool install legwork-mcp`.
80
+
81
+ ## How it works
82
+
83
+ 1. **Fetch.** Checks the repo is public and reachable, then shallow-clones it.
84
+ 2. **Scan.** Statically scans every Python file for obfuscated payloads
85
+ (XOR-decoded byte arrays, computed imports and attribute lookups,
86
+ unreadable identifiers). A hit stops everything before install.
87
+ 3. **Read.** The README, plus setup docs it links to (`install.md`,
88
+ `docs/getting-started.md`, …), capped at 50KB with install and usage
89
+ sections kept first.
90
+ 4. **Write.** Your model writes the install command and a Python MCP
91
+ wrapper with a self-test, or refuses with a specific reason: no
92
+ programmatic entrypoint, needs hardware, needs its own credentials,
93
+ needs a toolchain the sandbox doesn't have, and so on.
94
+ 5. **Install**, sandboxed, network on.
95
+ 6. **Self-test**, sandboxed, network off. A failure goes back to the model
96
+ and it tries again, up to 3 attempts and 10 minutes.
97
+ 7. **Serve.** `legwork serve owner/repo` runs the wrapper as an MCP server
98
+ over stdio, sandboxed, network off.
99
+
100
+ ## What "built" means
101
+
102
+ The self-test calls the **simplest** documented command and checks the
103
+ shape of its result. So "built" means the wrapper starts and its simplest
104
+ tool works. It does not mean every tool works. In the trial:
105
+
106
+ - golive-skill's wrapper exposes its read-only commands, not its deploy
107
+ flow, which needs accounts.
108
+ - AnyJev's decision tool needs a running vLLM server, which the self-test
109
+ didn't have.
110
+
111
+ Tools that must reach the network at run time won't work under `serve`,
112
+ because the network is off.
113
+
114
+ ## Risks, stated plainly
115
+
116
+ Legwork runs code you didn't write: the target repo's install steps and a
117
+ wrapper an LLM wrote from a README a stranger wrote. What contains it:
118
+
119
+ - **Install time is the biggest risk.** Package installs and `install.sh`
120
+ scripts run with network on, because they have to. The sandbox limits
121
+ them to their own working folder: no access to your home directory (SSH
122
+ keys, cloud credentials, dotfiles), no writes outside the folder, and an
123
+ environment with none of your variables (including your model key). A
124
+ malicious package can still misbehave inside that folder and reach the
125
+ network during install.
126
+ - **The scan covers the repo's source, not what installers download.**
127
+ magpie, for example, installs with the vendor's `curl … | sh`. For
128
+ downloaded code, the sandbox is the protection.
129
+ - **Prompt injection is not mitigated.** A README can steer the model into
130
+ writing a wrapper that does something other than what you asked for. The
131
+ wrapper still runs sandboxed with network off, which bounds the damage;
132
+ it doesn't prevent a wrong or misleading tool.
133
+ - **The scanner is heuristic.** It catches the obfuscation patterns seen in
134
+ real payloads so far, and a determined author can get past it.
135
+
136
+ The sandbox is macOS `sandbox-exec`. If it isn't available, Legwork refuses
137
+ to run. It never falls back to running unsandboxed.
138
+
139
+ ## Commands
140
+
141
+ | Command | What it does |
142
+ |---|---|
143
+ | `legwork owner/repo` | Build a wrapper (also `legwork build`). Accepts `owner/repo` or a github.com URL |
144
+ | `legwork serve owner/repo` | Run the built wrapper as an MCP server over stdio. Needs no model key |
145
+ | `legwork contribute owner/repo [--out DIR]` | Write the build as a public-cache entry, ready for a PR (below) |
146
+
147
+ Builds live in `~/.legwork` (override with `LEGWORK_HOME`). A failed build
148
+ saves its full error output to `attempts.log` in its build folder.
149
+
150
+ ## Contributing a wrapper
151
+
152
+ `legwork contribute owner/repo` writes `cache/<owner>__<repo>/` containing
153
+ `wrapper.py` and `manifest.json`, and prints a PR description. Before
154
+ writing anything, it:
155
+
156
+ - blocks the entry if the wrapper copies 50+ words in a row from the source repo
157
+ - re-runs the self-test in the sandbox
158
+ - blocks the write if any output contains something shaped like an API key,
159
+ including your own configured key
160
+
161
+ A GPL, AGPL, missing or unrecognized source license is flagged in the
162
+ manifest and the PR description, but not blocked. If the repo has commits
163
+ newer than the build or the existing entry, you get a warning. Open the PR
164
+ yourself; a bad entry is removed with a plain `git revert`.
165
+
166
+ ## Status
167
+
168
+ Early. What's next:
169
+
170
+ - **Linux sandbox.** Legwork is macOS-only today.
171
+ - **Reuse from the cache**, so a repo someone already wrapped doesn't cost
172
+ you a build.
173
+ - Better multi-tool verification than a single simplest-command self-test.
174
+
175
+ ## Development
176
+
177
+ ```sh
178
+ uv sync
179
+ uv run pytest # the sandbox and integration tests need macOS
180
+ ```
181
+
182
+ `tests/fixtures/ai_data_extractor_payload.py` is a real malicious file with
183
+ its payload destroyed (every encoded byte randomized, code shape kept), so
184
+ the scanner is tested against a real technique. Tests only parse it with
185
+ `ast`; see `tests/fixtures/README.md`.
186
+
187
+ ## License
188
+
189
+ MIT
@@ -0,0 +1,170 @@
1
+ # Legwork
2
+
3
+ **Point it at a GitHub repo, get a working MCP tool back.**
4
+
5
+ Legwork reads a repo's README, has your LLM write an
6
+ [MCP](https://modelcontextprotocol.io) wrapper for it, installs it in a
7
+ sandbox, and proves it runs before handing it to Claude Code, Cursor or any
8
+ other MCP client. If a repo can't be wrapped, it says why instead of
9
+ producing something broken.
10
+
11
+ ```sh
12
+ uvx legwork-mcp owner/repo
13
+ ```
14
+
15
+ ## Proof, not a pitch
16
+
17
+ On 2026-09-26 we ran Legwork against **this week's 10 most-starred new AI
18
+ repos on GitHub**, taken exactly as search ranked them, with nothing skipped
19
+ for being hard:
20
+
21
+ | Outcome | Repos |
22
+ |---|---|
23
+ | ✅ Built a working MCP server | **3** — an npm CLI, a Python library, a Go binary |
24
+ | ↩️ Refused, with the right reason | **5** — two Android/macOS apps, a desktop app, a repo with no usage docs, a tool that needs its own API keys |
25
+ | 🛑 Blocked as malware | **2** |
26
+
27
+ Two of the week's top-10 "AI tools", about 700 stars each and three days
28
+ old, carried the same byte-identical obfuscated dropper under different
29
+ file names. Legwork's pre-install scan refused both in about a second.
30
+ Nothing from them was installed or run. Stars are not a trust signal.
31
+
32
+ Full write-up, including what failed along the way and what we fixed:
33
+ [docs/designs/legwork-trending-trial-2026-09-26.md](docs/designs/legwork-trending-trial-2026-09-26.md).
34
+
35
+ ## Quick start
36
+
37
+ You need **macOS**, [uv](https://docs.astral.sh/uv/), and any
38
+ OpenAI-compatible chat-completions endpoint. Legwork itself is free; the
39
+ only cost is your own model usage, which is 1–3 calls per build.
40
+
41
+ ```sh
42
+ export LEGWORK_LLM_ENDPOINT=https://api.openai.com/v1
43
+ export LEGWORK_LLM_API_KEY=... # your own key; never a CLI flag
44
+ export LEGWORK_LLM_MODEL=gpt-5
45
+
46
+ uvx legwork-mcp 2akouwu/reverify
47
+ ```
48
+
49
+ A build takes 1–3 minutes and ends with the line to connect it:
50
+
51
+ ```
52
+ Built an MCP wrapper for 2akouwu/reverify on attempt 2 of 3.
53
+ What it wraps: Verify claims about binaries using Reverify's deterministic tools (wraps `reverify verify --json`)
54
+
55
+ Connect it to Claude Code:
56
+ claude mcp add reverify -- ~/.local/bin/uvx legwork-mcp serve 2akouwu/reverify
57
+ ```
58
+
59
+ It also prints an `mcpServers` block for Claude Desktop, Cursor and other
60
+ clients. For a permanent `legwork` command: `uv tool install legwork-mcp`.
61
+
62
+ ## How it works
63
+
64
+ 1. **Fetch.** Checks the repo is public and reachable, then shallow-clones it.
65
+ 2. **Scan.** Statically scans every Python file for obfuscated payloads
66
+ (XOR-decoded byte arrays, computed imports and attribute lookups,
67
+ unreadable identifiers). A hit stops everything before install.
68
+ 3. **Read.** The README, plus setup docs it links to (`install.md`,
69
+ `docs/getting-started.md`, …), capped at 50KB with install and usage
70
+ sections kept first.
71
+ 4. **Write.** Your model writes the install command and a Python MCP
72
+ wrapper with a self-test, or refuses with a specific reason: no
73
+ programmatic entrypoint, needs hardware, needs its own credentials,
74
+ needs a toolchain the sandbox doesn't have, and so on.
75
+ 5. **Install**, sandboxed, network on.
76
+ 6. **Self-test**, sandboxed, network off. A failure goes back to the model
77
+ and it tries again, up to 3 attempts and 10 minutes.
78
+ 7. **Serve.** `legwork serve owner/repo` runs the wrapper as an MCP server
79
+ over stdio, sandboxed, network off.
80
+
81
+ ## What "built" means
82
+
83
+ The self-test calls the **simplest** documented command and checks the
84
+ shape of its result. So "built" means the wrapper starts and its simplest
85
+ tool works. It does not mean every tool works. In the trial:
86
+
87
+ - golive-skill's wrapper exposes its read-only commands, not its deploy
88
+ flow, which needs accounts.
89
+ - AnyJev's decision tool needs a running vLLM server, which the self-test
90
+ didn't have.
91
+
92
+ Tools that must reach the network at run time won't work under `serve`,
93
+ because the network is off.
94
+
95
+ ## Risks, stated plainly
96
+
97
+ Legwork runs code you didn't write: the target repo's install steps and a
98
+ wrapper an LLM wrote from a README a stranger wrote. What contains it:
99
+
100
+ - **Install time is the biggest risk.** Package installs and `install.sh`
101
+ scripts run with network on, because they have to. The sandbox limits
102
+ them to their own working folder: no access to your home directory (SSH
103
+ keys, cloud credentials, dotfiles), no writes outside the folder, and an
104
+ environment with none of your variables (including your model key). A
105
+ malicious package can still misbehave inside that folder and reach the
106
+ network during install.
107
+ - **The scan covers the repo's source, not what installers download.**
108
+ magpie, for example, installs with the vendor's `curl … | sh`. For
109
+ downloaded code, the sandbox is the protection.
110
+ - **Prompt injection is not mitigated.** A README can steer the model into
111
+ writing a wrapper that does something other than what you asked for. The
112
+ wrapper still runs sandboxed with network off, which bounds the damage;
113
+ it doesn't prevent a wrong or misleading tool.
114
+ - **The scanner is heuristic.** It catches the obfuscation patterns seen in
115
+ real payloads so far, and a determined author can get past it.
116
+
117
+ The sandbox is macOS `sandbox-exec`. If it isn't available, Legwork refuses
118
+ to run. It never falls back to running unsandboxed.
119
+
120
+ ## Commands
121
+
122
+ | Command | What it does |
123
+ |---|---|
124
+ | `legwork owner/repo` | Build a wrapper (also `legwork build`). Accepts `owner/repo` or a github.com URL |
125
+ | `legwork serve owner/repo` | Run the built wrapper as an MCP server over stdio. Needs no model key |
126
+ | `legwork contribute owner/repo [--out DIR]` | Write the build as a public-cache entry, ready for a PR (below) |
127
+
128
+ Builds live in `~/.legwork` (override with `LEGWORK_HOME`). A failed build
129
+ saves its full error output to `attempts.log` in its build folder.
130
+
131
+ ## Contributing a wrapper
132
+
133
+ `legwork contribute owner/repo` writes `cache/<owner>__<repo>/` containing
134
+ `wrapper.py` and `manifest.json`, and prints a PR description. Before
135
+ writing anything, it:
136
+
137
+ - blocks the entry if the wrapper copies 50+ words in a row from the source repo
138
+ - re-runs the self-test in the sandbox
139
+ - blocks the write if any output contains something shaped like an API key,
140
+ including your own configured key
141
+
142
+ A GPL, AGPL, missing or unrecognized source license is flagged in the
143
+ manifest and the PR description, but not blocked. If the repo has commits
144
+ newer than the build or the existing entry, you get a warning. Open the PR
145
+ yourself; a bad entry is removed with a plain `git revert`.
146
+
147
+ ## Status
148
+
149
+ Early. What's next:
150
+
151
+ - **Linux sandbox.** Legwork is macOS-only today.
152
+ - **Reuse from the cache**, so a repo someone already wrapped doesn't cost
153
+ you a build.
154
+ - Better multi-tool verification than a single simplest-command self-test.
155
+
156
+ ## Development
157
+
158
+ ```sh
159
+ uv sync
160
+ uv run pytest # the sandbox and integration tests need macOS
161
+ ```
162
+
163
+ `tests/fixtures/ai_data_extractor_payload.py` is a real malicious file with
164
+ its payload destroyed (every encoded byte randomized, code shape kept), so
165
+ the scanner is tested against a real technique. Tests only parse it with
166
+ `ast`; see `tests/fixtures/README.md`.
167
+
168
+ ## License
169
+
170
+ MIT