Scaffold. Validate. Build. Test.
A zero-dependency AI skill for reliable OpenWrt package development.
Quick start · Install · 简体中文 · Contribute
An AI skill for developing, packaging and testing OpenWrt packages — CLI tools, daemons, kernel modules and LuCI web apps — with as few moving parts as possible.
Give a coding agent this skill and the sentence "write me a LuCI app that shows interface traffic and build it" becomes: correct package tree, correct Makefile, working ACL wiring, a static check that catches the mistakes before a build, and an artifact you can install.
中文文档见 README.zh-CN.md.
Three things routinely break OpenWrt package development, and all three are invisible until a build or a device tells you the hard way:
- The package manager changed. OpenWrt 24.10 and older uses
opkgand produces.ipk. OpenWrt 25.12 and newer usesapkand produces.apk. The same Makefile drives both; picking the wrong target release invalidates the whole effort. - Recipe lines must be indented with a real TAB. Spaces give
missing separatorand, worse, sometimes appear to work. - Windows and macOS cannot compile OpenWrt packages. There is no way around a Linux toolchain — but scaffolding, static validation and artifact inspection need none of it, and the actual compile can run in Docker or in CI.
This skill encodes all of that, plus the licence metadata rules, plus a validator that catches roughly 25 real failure modes before you spend build time.
| Component | Requirement |
|---|---|
| Python | 3.8 or newer, standard library only |
| The skill's own tooling | works on Windows, macOS, Linux — no Docker, no network |
| Compiling packages | any one of: Docker, GitHub Actions, or a native Linux host |
Nothing is installed by this project. There is no pip install step.
Measured on Windows with Python 3.13, where the interpreter startup alone is
~0.32 s: scaffold_package.py takes ~0.31 s, validate_package.py over 20
packages takes ~0.32 s, and the whole 44-test suite takes ~6 s. In other words
runtime is dominated by Python process startup, not by this tooling.
The complete install reference - every platform, verification, update, uninstall and troubleshooting - lives in INSTALL.md. AI agents should read AGENTS.md instead: it has the same commands plus the rules for not inventing facts.
A — skills directory (recommended; the agent picks it up automatically)
git clone https://github.com/cndoin/packwrt.git
cp -r REPO ~/.workbuddy/skills/packwrtOn Windows PowerShell:
git clone https://github.com/cndoin/packwrt.git
Copy-Item -Recurse REPO "$HOME\.workbuddy\skills\packwrt"B — from the packaged zip (unzip into ~/.workbuddy/skills/)
make package # writes dist/packwrt.zipC — clone straight in
git clone https://github.com/cndoin/packwrt.git ~/.workbuddy/skills/packwrtVerify the install:
python ~/.workbuddy/skills/packwrt/scripts/check_env.py# 1. What can this machine actually do?
python scripts/check_env.py
# 2. Generate a package tree (pick a type)
python scripts/scaffold_package.py \
--type luci-app --name luci-app-myapp --title "MyApp" \
--version 1.0.0 --license GPL-2.0-only \
--maintainer "Your Name <you@example.com>" \
--out ./my-feed
# 3. Catch the mistakes before spending build time
python scripts/validate_package.py ./my-feed
# 4. Compile it — Linux/macOS/WSL/Git-Bash
./my-feed/build-in-docker.sh
# or Windows PowerShell
.\my-feed\build-in-docker.ps1
# or, with no Docker at all: push and let the generated CI workflow build it
# 5. Check the artifact without a device
python scripts/inspect_artifact.py my-feed/bin/packages/*/*/*.apkGenerated package types:
--type |
Produces |
|---|---|
luci-app |
LuCI app: JS views, menu.d, acl.d, ucode rpcd backend, uci-defaults, config |
c-binary |
Plain C CLI tool built from bundled source |
c-daemon |
C daemon + procd init script + UCI config + uci-defaults + postinst wiring |
script |
Shell/Python script package (PKGARCH:=all) |
library |
Shared library with Build/InstallDev so other packages can link it |
kernel-module |
kmod package (requires a full buildroot, not the SDK) |
| Script | What it does | Needs Docker? |
|---|---|---|
scripts/check_env.py |
Reports which build route this machine can use | no |
scripts/scaffold_package.py |
Generates the whole package tree from 27 templates | no |
scripts/validate_package.py |
Static analysis; exits non-zero on real problems | no |
scripts/inspect_artifact.py |
Parses a built .ipk/.apk, runs the upstream CI checks |
no |
scripts/fix_exec_bits.py |
Fixes the executable bit on filesystem and git index | no |
Every script is standard-library Python and writes LF-only UTF-8.
| Route | Use when | Cost |
|---|---|---|
| Docker SDK container | Docker available (any OS) | first run pulls 1–2 GB |
| GitHub Actions | no Docker / no Linux host | needs a GitHub repo |
| native Linux buildroot/SDK | repeated builds on Linux | large disk, toolchain build |
scaffold_package.py emits a working example of each: build-in-docker.sh
(Linux/macOS/WSL/Git Bash), build-in-docker.ps1 (Windows), and
.github/workflows/build-package.yml (GitHub Actions, uses openwrt/gh-action-sdk).
These are the things that actually differ between systems, and how the skill handles them:
| Hazard | Handling |
|---|---|
| Console codepage crashes on non-ASCII paths | every script reconfigures stdout/stderr to UTF-8 with errors="replace" |
| CRLF sneaking into generated Makefiles/scripts | all output is written with newline="\n"; .gitattributes normalises the repo; a test asserts the repo has no CRLF |
| Windows has no POSIX mode bits | fix_exec_bits.py sets the bit in the git index (update-index --chmod=+x), which is what travels to GitHub |
LuCI root/ payloads are copied with cp -pR |
a missing exec bit means an init or uci-defaults script silently does not run — hence the check above |
| Windows path separators in reports and mounts | reports print POSIX paths; build-in-docker.sh converts the mount path via cygpath under MSYS/Cygwin |
| macOS/Windows cannot run a Linux toolchain | check_env.py says so explicitly and points at CI instead of failing later |
docker present but the engine not running |
detected specifically, because a bare which docker check passes and every build then fails |
.
├── SKILL.md # the agent-facing skill (five-phase workflow)
├── references/ # loaded on demand
│ ├── makefile-reference.md
│ ├── luci-app-guide.md
│ ├── build-and-test.md
│ ├── licensing.md
│ └── troubleshooting.md
├── scripts/ # standard-library Python tools
├── samples/ # reference packages (luci-app-netmon, netmon-agent)
├── tests/test_skill.py # 44 checks, runs on all three platforms
├── assets/templates/ # 27 templates; the single source of packaging truth
└── .github/workflows/ci.yml # Ubuntu + macOS + Windows, Python 3.10 and 3.13
Contributions must preserve these — CI enforces most of them:
- Standard library only; no
pip install, no network access at runtime. - Templates are pure ASCII and LF-only; they are copied verbatim into packages.
- Makefile recipe lines use TABs.
SKILL.mdstays lean; detail lives inreferences/.- The validator has no false positives on freshly scaffolded output, and every rule has a negative test.
See CONTRIBUTING.md.
- Verified against OpenWrt 24.10 (
opkg/.ipk) and 25.12+ (apk/.apk). - Kernel modules require a full buildroot; the standalone SDK cannot build them.
- The tooling performs static checks and artifact inspection. It does not replace installing the package on a real device — treat a green validator as "worth building", not "proven working".
MIT.
