This guide explains how to verify that a new agentstrator package installs, runs, and cleans up correctly. Use it when adding a new package or modifying an existing one.
The companion script test-package.sh (in the same directory as this guide) implements the automated checks described below.
./test-package.sh rtkRun ./test-package.sh --help for available options.
The test script (test-package.sh) performs 5 phases:
| Phase | What it checks |
|---|---|
| validate | metadata, install.sh, uninstall.sh, init.sh, Dockerfile structure |
| build | docker build succeeds, file tracking works, smoke test |
| install | install.sh runs, config.json updated, MCP/plugin/instructions registered |
| runtime | generate_dockerfile includes package, runtime build succeeds, binary works |
| uninstall | uninstall.sh runs, cleanup complete, config restored |
# Test a package by name (looks in ~/.agentstrator/packages/ and ./packages/)
./test-package.sh rtk
# Test a specific package directory
./test-package.sh --dir packages/rtk
# Skip slow phases (runtime build)
./test-package.sh --skip runtime rtk
# Always rebuild Docker images
./test-package.sh --rebuild rtk
# Set custom timeout for interactive packages (oh-my-openagent, etc.)
./test-package.sh --timeout 300 oh-my-openagentmetadatafile exists with requiredNAME=fieldinstall.shexists and is executableuninstall.shexists and is executableinit.shis executable (if present)Dockerfileexists and usesagentstrator-coreas base (if present)Dockerfilecontains file-tracking pattern (before-files.txt,after-files.txt,comm -13) (if present)
docker build -t agentstrator-<name>succeeds/new-files.txtexists inside the image and is non-empty/new-symlinks-with-targets.txtexists if symlinks were created- Binary smoke test:
<tool> --helpor<tool> --versionworks inside the image - No system paths in new-files.txt (filters
/tmp/,/root/)
install.shexits with code 0config.jsonmarks the package asinstalled: true- MCP server is registered in opencode.json (if install.sh uses
add_mcp_to_opencode) - Plugin reference is registered (if install.sh uses
add_plugin_to_opencode) - Instruction file exists and is registered (if install.sh uses
add_instructions_to_opencode)
generate_dockerfileoutput includes aCOPY --from=<name>line for this package (if Dockerfile-based)- Runtime image builds successfully with the package included
- Binary is accessible via
which <cmd>in the runtime image
uninstall.shexits with code 0config.jsonmarks the package asinstalled: false- Previously registered MCP/plugin/instructions entries are removed
- Config file is restored to pre-install state (
restore_configis idempotent — safe if called multiple times)
- install.sh does NOT update config.json — the agentstrator framework does this after a successful
agentstrator installrun. The test script handles this by injecting the package entry into config.json after install.sh completes. This means the install phase may pass even if config.json is not updated by the package scripts themselves. - MCP entry key is the package name (2nd arg to
add_mcp_to_opencode), NOT necessarilycommand[0]. For example,agentmemoryregisters with key"agentmemory"butcommand[0]is"npx". The test script checks the entry key via.mcp | has("<name>"). - Timeout: The
--timeoutflag wraps install.sh and uninstall.sh with thetimeoutcommand. Default is 120 seconds. Set to0to disable.
The install and uninstall phases modify config.json and opencode configuration files. The script:
- Backs up
config.jsonbefore install - Backs up
opencode.jsonbefore install - Restores both after uninstall completes (backup vars cleared after restore to prevent double-restore)
This makes it safe to run on a production installation.
| Pattern | Dockerfile | install.sh uses | Phase notes |
|---|---|---|---|
| A (NPM global) | Yes | npm install -g | Build, Install, Runtime, Uninstall |
| B (Python pip) | Yes | pip3 install | Build, Install, Runtime, Uninstall |
| C (binary download) | Yes | curl | sh | Build, Install, Runtime, Uninstall |
| D (git plugin) | No | add_plugin_to_opencode | Install, Uninstall only |
| E (instructions) | No | add_instructions_to_opencode | Install, Uninstall only |
| F (interactive) | No | npm install + docker run | Install, Uninstall only (no automated smoke test) |
Use this in addition to the checklist in adding-packages.md when adding a new package:
-
./test-package.sh <name>passes all 5 phases -
agentstrator install <name>works (single-package install) -
agentstrator remove <name>works (single-package remove, cleanup verified) -
agentstrator rebuildsucceeds without breaking other packages - Runtime image binary:
docker run --rm agentstrator:runtime which <cmd>returns the binary -
init.shexits cleanly (if present) - PATH correctly set for non-standard paths (if
PATH=in metadata)
The following bugs were discovered during testing and should be fixed:
| Package | Issue |
|---|---|
mempalace |
Uninstall removes MCP key "mempalace-mcp" but install creates key "mempalace" — mismatch |
codedna |
init.sh checks $WORKSPACE/bmalph/config.json instead of $WORKSPACE/.codedna — copy-paste from bmalph |
oh-my-openagent |
install.sh prompts 7 interactive questions — requires --timeout or DEBIAN_FRONTEND=noninteractive |
| Symptom | Likely cause |
|---|---|
| Build fails | Dockerfile doesn't use agentstrator-core as base, or package install command fails |
/new-files.txt empty |
File-tracking pattern missing in Dockerfile |
| Smoke test fails | Binary not in PATH or different binary name than expected |
| Install phase fails | install.sh calls add_mcp_to_opencode but node:22-slim image not available |
| Runtime build fails | generate_dockerfile produces invalid Dockerfile or package has conflicting files |
| Install phase hangs | Package has interactive prompts — use --timeout 300 or higher |
| MCP check fails in install but succeeds in uninstall | Package uses different MCP key name than CANONICAL_NAME — check install.sh for add_mcp_to_opencode args |
| config.json check fails | Expected: install.sh doesn't update config.json (framework does). Test injects it automatically. |
If a package introduces a new pattern (not one of the 6 above), add corresponding checks to test-package.sh:
- Add detection logic in the pattern detection section
- Add check functions in the relevant phase
- Update this guide's pattern reference table