| name | port-project |
| description | Port an entire C project to AmigaOS. Runs the full pipeline — analyze, transform, build, test, package. Use to port a new project from scratch. |
| argument-hint | <path-to-source> |
| allowed-tools | Read, Write, Edit, Bash, Grep, Glob, Agent |
Port Project to Amiga
You are the orchestrator for porting the C project at $ARGUMENTS to AmigaOS 3.x. You run the full pipeline end-to-end.
Environment Pre-flight
Docker: !`docker info --format '{{.ServerVersion}}' 2>/dev/null || echo 'NOT RUNNING — build stage will fail'`
Toolchain: !`docker images --format '{{.Repository}}:{{.Tag}}' 2>/dev/null | grep amiport-toolchain | head -1 || echo 'NOT FOUND — run make setup-toolchain'`
vamos: !`vamos --version 2>&1 | head -1 || echo 'NOT INSTALLED — run pip install amitools'`
lha: !`which lha >/dev/null 2>&1 && echo 'installed' || echo 'NOT INSTALLED — packaging will fail'`
Ports: !`ls -d ports/*/PORT.md 2>/dev/null | wc -l | tr -d ' '` existing
If any tool shows NOT RUNNING/NOT FOUND/NOT INSTALLED, warn the user before starting. Do not proceed to Stage 4 (build) without Docker and the toolchain image.
Output Directory
All ports go into ports/<program-name>/ with this structure:
ports/<name>/
├── original/ # Original POSIX source (copied from input)
├── ported/ # Transformed AmigaOS source
├── Makefile # Build rules (includes ../common.mk)
├── PORT.md # Porting log documenting every transformation
└── <name>.readme # Generated by `make package` for Aminet
Create this structure at the start of the pipeline using the templates in ports/templates/. Read ports/templates/STRUCTURE.md for the directory layout specification.
Pipeline
Stage 0: Research (before any work)
Dispatch an aminet-researcher agent to check whether this tool already exists for AmigaOS 3.x. If a recent, functional port already exists, stop and tell the user — don't duplicate work. If an old or limited version exists, note this in PORT.md and proceed (our port will be the upgrade). This step is mandatory.
GATE: Do NOT dispatch the source-analyzer (Stage 1) until the aminet-researcher has returned. Do not run it in the background and proceed — wait for the result. If the researcher says SKIP, present the finding to the user and let them decide whether to proceed. Proceeding without waiting wastes work if a good port already exists.
Stage 0b: Dependency Audit (conditional)
If the source has external library dependencies (anything beyond libc/libm — detected via #include of non-standard headers, linker flags, pkg-config, or Makefile LDLIBS), dispatch the dependency-auditor agent:
Agent(subagent_type="dependency-auditor", prompt="Audit external dependencies for <path>...")
For single-file CLI tools with only standard C library deps, skip this stage.
GATE: If the auditor classifies any dependency as blocker (not available and not portable to AmigaOS), stop and report to the user. Do not proceed to analysis with known-impossible dependencies.
Stage 1: Analyze — MANDATORY AGENT DISPATCH
YOU MUST dispatch the source-analyzer agent. Do not analyze source manually. The agent runs stub value impact analysis, logic bug pattern detection, and tier classification that manual grep cannot replicate.
Agent(subagent_type="source-analyzer", prompt="Analyze <path> for Amiga portability...")
GATE: Do not proceed to Stage 2 until the source-analyzer agent has returned a portability report with a verdict and tier classification. If the agent returns INFEASIBLE, stop.
The report classifies issues by tier (ADR-008) and port category (ADR-011):
- Tier 1 (green) — automated shim transforms, proceed without user input
- Tier 2 (yellow) — emulation with caveats, present tradeoffs to user before applying
- Tier 3 (red) — redesign required, present pattern options and wait for human decision
Port category determines the pipeline strategy:
- Category 1 (CLI) — standard pipeline, vamos testing
- Category 2 (Scripting) — standard pipeline, may need dlopen stubs, vamos testing
- Category 3 (Console UI) — add console-shim, link with
-lamiport-console, FS-UAE testing
- Category 4 (Network) — add bsdsocket-shim, link with
-lamiport-net, FS-UAE + TCP/IP testing
- Category 5 (GUI) — not yet supported, stop and explain
Stage 2: Set Up Port Directory
Read ports/templates/STRUCTURE.md for the full directory layout specification.
- Create
ports/<name>/original/ and copy the source files there
- Create
ports/<name>/ported/ — this is where transformed source goes
- Copy
ports/templates/Makefile.template to ports/<name>/Makefile and fill in all __PLACEHOLDER__ variables (see template for the full list). Set VERSION to the upstream version and REVISION = 1. DISPLAY_VERSION is auto-computed by common.mk.
- Copy
ports/templates/PORT.md.template to ports/<name>/PORT.md and fill in the Overview table placeholders
- Update
SOURCES in the Makefile to list all ported .c files
All build/test artifacts must stay inside the port directory. Never create files in the project root.
Stage 3: Transform — MANDATORY AGENT DISPATCH
YOU MUST dispatch the code-transformer agent. Do not manually edit ported source files. The agent applies transformation rules consistently, adds /* amiport: */ comments, checks shim availability, and runs stub value impact analysis. A PreToolUse hook (enforce-agents.sh) warns on direct edits to ported/*.c files.
Agent(subagent_type="code-transformer", prompt="Transform <port>/ported/ source files for AmigaOS...")
GATE: Do not proceed to Stage 4 until the code-transformer agent has returned and all ported source files exist in ports/<name>/ported/.
Before dispatching, verify which amiport_* shim functions actually exist by checking headers in lib/posix-shim/include/amiport/. For Tier 2 functions, check lib/posix-emu/include/amiport-emu/. If a needed wrapper is missing, use /extend-shim to add it before dispatching the transformer.
Stage 3b: Hardware Review (conditional — Category 3+ ports)
For Category 3 (Console UI), Category 4 (Network), or any port that does unusual memory allocation (Chip RAM, DMA buffers), dispatch the hardware-expert agent to review hardware assumptions before building:
Agent(subagent_type="hardware-expert", prompt="This is a Category [N] port of [name]. Review the ported source at ports/[name]/ported/ for hardware assumptions — Chip RAM allocation sizes, direct hardware access, DMA-sensitive timing, chipset-specific features.")
Category 1-2 (CLI, scripting) ports skip this stage unless they do unusual memory allocation.
Stage 4: Build — MANDATORY AGENT DISPATCH
YOU MUST dispatch the build-manager agent. Do not run compiler commands directly. A PreToolUse hook (block-direct-gcc.sh) blocks direct m68k-amigaos-gcc calls.
Agent(subagent_type="build-manager", prompt="Build ports/<name> for AmigaOS...")
The build-manager iterates up to 5 times on compile errors. If it can't resolve a linker error for a missing shim function, it will recommend /extend-shim.
GATE: Do not proceed to Stage 5 until a compiled binary exists at ports/<name>/<name>.
Stage 5: Test
5a. vamos testing (quick smoke test):
For Category 1-2 (CLI/scripting): Test with make test TARGET=ports/<name> (vamos) for basic I/O verification using piped stdin.
For Category 3 (Console UI): vamos can run basic smoke tests (start, print version, exit). Interactive testing requires FS-UAE.
For Category 4 (Network): vamos cannot test networking. Build verification only.
5b. Test suite generation (MANDATORY):
Dispatch the test-designer agent to generate a comprehensive test-fsemu-cases.txt:
The test-designer reads the ported source, man pages, and crash-patterns.md to generate a complete test suite meeting docs/test-coverage-standard.md. It produces test-fsemu-cases.txt with 8+ tests (CLI) or 10+ tests (scripting), covering all six required categories: functional, error path, exit code, edge case, Amiga-specific, and real-world/stress.
It runs BEFORE make test-fsemu. The test-designer has the write-arexx skill injected and understands ARexx constraints (ASCII-only files, no $ in CMD lines, ~= not =).
5c. FS-UAE testing (MANDATORY for ALL categories):
Every port MUST have FS-UAE testing with comprehensive coverage per docs/test-coverage-standard.md. Create test-fsemu-cases.txt in the port directory with test cases covering ALL FIVE required categories:
- Functional tests — one test per documented flag/option
- Error path tests — nonexistent files, bad arguments, malformed input (EXPECT_RC: 10)
- Exit code tests — every distinct return code (0, 5, 10) verified with EXPECT_RC:
- Edge case tests — empty files, special characters, long lines, boundary values
- Amiga-specific tests — path handling, T: temp files, epoch (if applicable)
Minimum test counts: CLI tools: 15+, Scripting: 20+, Console UI: 12+, Network: 12+.
Create test input files as test-<name>-*.txt in the port directory (include an empty file for edge case testing). Use EXPECT_RC: on every test case.
Assertion modes: EXPECT: (exact first-line), EXPECT_CONTAINS: (substring), EXPECT_RC: (exit code).
5d. Interactive tests (Category 3+ MANDATORY, ADR-023):
For Category 3 (Console UI) and Category 4 (Network) ports, add ITEST: blocks to test-fsemu-cases.txt for automated keystroke injection via KeyInject:
ITEST: Interactive quit with q key
LAUNCH: WORK:<program> WORK:test-scroll.txt
KEYS: WAIT1500,q
EXPECT_RC: 0
KEYS tokens: named keys (SPACE, RETURN, ESC, UP, DOWN, etc.), single characters (a-z, /, .), delays (WAIT500). The test harness launches the program via Run, injects keys via WORK:KeyInject, and verifies exit code. Minimum 3 interactive tests: basic quit, navigation (scroll/page), and a program-specific action (search, edit, etc.).
5e. Visual verification (ADR-024, MANDATORY for Category 3+):
Generate a separate test-fsemu-visual-cases.txt with SCRAPE tests. Functional and visual tests MUST be separate FS-UAE passes -- never mix them in one suite. Resource exhaustion at ~13 ITESTs is a hard wall.
ITEST: Visual: file content appears on screen
LAUNCH: WORK:mg -n WORK:test-file.txt
KEYS: WAIT2000,CTRL_X,WAIT300,CTRL_C
SCRAPE
EXPECT_AT 1,1,Hello, Amiga world!
EXPECT_RC: 0
Requires the forked FS-UAE (~/Developer/fs-uae/) with ANSI console capture. scripts/verify-screen.py uses pyte to reconstruct the terminal from captured ANSI output. ARexx syntax validated by scripts/check-arexx-syntax.py / make check-arexx.
Current limitation: CMD_WRITE captures static display (file load, help text) but NOT interactive echo (typed characters, cursor movement). Interactive rendering verification deferred to ADR-025.
Run both passes:
make test-fsemu TARGET=ports/<name>
make test-fsemu TARGET=ports/<name> VISUAL=1
GATE: Do not proceed to Stage 6 unless:
- test-fsemu-cases.txt has >= minimum test count for the port category
- At least one test uses EXPECT_RC: 10 (error path tested)
- At least one test uses EXPECT_RC: 5 or EXPECT_RC: 0 (success path tested)
- Category 3+ ports have >= 3 ITEST: blocks
- Category 3+ ports have a separate test-fsemu-visual-cases.txt with >= 3 SCRAPE tests (ADR-024)
- No SCRAPE tests exist in test-fsemu-cases.txt (functional and visual MUST be separate passes)
If FS-UAE tests show a Guru Meditation (crash), automatically dispatch the debug-agent with the Enforcer log and binary. Do not ask the user — the debug agent handles crash diagnosis autonomously. After the debug agent fixes the crash, rebuild and retest.
If FS-UAE is not available (Workbench not fully installed), note this in PORT.md and proceed — the test-fsemu-cases.txt must still be created so testing can run when infrastructure is ready.
If tests fail (wrong output, not crash), analyze the failure and fix. May require going back to the transform stage.
Stage 6: Review and Optimize (mandatory)
6a. Code review: Run /review-amiga on the ported source. This checks for Amiga-specific issues that the transform and build stages don't catch: stack safety, BPTR cleanup on error paths, memory patterns, and AmigaOS conventions.
6b. Memory safety check (mandatory): Dispatch the memory-checker agent. This is mandatory for every port. AmigaOS has no memory protection, no garbage collection, and no process memory cleanup on exit with -noixemul. Every malloc/realloc that isn't explicitly free'd leaks permanently until reboot. The memory-checker finds:
- Memory leaks on all exit paths (including error paths)
- realloc failure patterns that lose the original pointer
- Static buffers that grow but are never freed
- Double-free and use-after-free risks
- File handle and Lock() leaks
Fix all memory safety issues before proceeding.
6c. Performance optimization (MANDATORY): Dispatch the perf-optimizer agent on every port. This is arguably the best agent in the pipeline — it finds critical 68k-specific wins that no other agent catches. On 7MHz hardware, a 3-5x I/O speedup is the difference between usable and unusable. It checks for:
- Hot loop optimization for 68000 (7 MHz, no cache, no pipeline)
- I/O patterns (per-character fgetc vs buffered fgets — 3-5x difference)
- Integer operation costs (multiply/divide avoidance in hot paths)
- Memory access patterns (sequential vs random, alignment)
- Stack-heavy recursion patterns that crash on real hardware but pass on vamos
Apply all CRITICAL and HIGH findings from 6b and 6c immediately. Do not document them for follow-up — implement them now.
If 6b or 6c makes changes, rebuild (Stage 4) and retest (Stage 5), then re-run 6b and 6c on the updated code. Repeat until no CRITICAL or HIGH findings remain. This convergence loop ensures each optimization round doesn't introduce new issues and catches findings that were deprioritized when higher-severity items were present. MEDIUM and LOW findings may be documented in PORT.md without implementation.
6d. Runtime profiling (OPTIONAL): For performance-critical ports, dispatch the profiler agent to empirically measure function timing using ReadEClock. This validates the perf-optimizer's static analysis with real data. The profiler instruments code with AMIPORT_PROFILE_BEGIN/END macros, builds with -DAMIPORT_PROFILE, and runs on vamos or FS-UAE.
6e. Knowledge capture (MANDATORY — do not ask, just do it): Review PORT.md for novel transformation patterns, pitfalls, or workarounds discovered during this port that aren't yet in the canonical references. For each novel finding:
- Check if the pattern exists in
transformation-rules.md, known-pitfalls.md, crash-patterns.md, or posix-tiers.md
- If novel, immediately update the canonical reference — do not ask the user for permission, just add it
- If the finding affects agent behavior (e.g., the code-transformer should catch a new pattern), update the relevant transformation rules too
This step ensures lessons learned flow back into the toolkit for future ports. Novel findings from every port must be captured — this is how the pipeline gets smarter.
GATE: Before proceeding to Stage 7, verify knowledge capture by running:
grep -c '<port-name>' .claude/rules/known-pitfalls.md .claude/skills/transform-source/references/transformation-rules.md docs/references/crash-patterns.md 2>/dev/null
If zero hits AND the port encountered any of these: (a) a new workaround not in known-pitfalls, (b) a shim/libnix behavior difference, (c) a build trick (linker flags, bootstrap steps), (d) a test harness gap — then knowledge capture was skipped. Go back and add the findings. If the port was truly routine with no novel findings, document that explicitly in PORT.md under a "Knowledge Capture: No novel findings" line.
Fix any CRITICAL issues before packaging. WARN issues should be documented in PORT.md.
Stage 7: Package
Before packaging, create the Aminet .readme by copying ports/templates/readme.template to ports/<name>/<name>.readme and filling in placeholders. Replace the usage placeholder with actual examples for this program.
Then package with: make -C ports/<name> TARGET=<name> package
This creates <name>-<version>.lha containing the binary, readme, and PORT.md — ready for Aminet upload.
Stage 8: Documentation & Catalog
- Move candidate to
ported[] in data/catalog.json with measured_binary_kb, test_count, test_pass_rate
- Sync:
cp data/catalog.json site/data/catalog.json
- Add row to
PORTS.md (name, version, description, category, source, test results, status)
- Add row to
README.md ports table (alphabetically sorted in the correct category section)
- Run
python3 scripts/catalog-score.py --score
Do NOT skip README.md. This was missed in multiple batches. The documentation rule (.claude/rules/documentation.md #9) requires it.
Complex Multi-File Ports
For projects with 5+ source files, orchestrate from the main session by dispatching each specialized agent directly (source-analyzer, code-transformer, build-manager, etc.). The main session is the orchestrator — it has full context and can dispatch subagents.
Do NOT use port-coordinator. It cannot dispatch subagents (Claude Code limitation: spawned agents cannot spawn their own agents). It falls back to doing manual transforms that skip the specialized agents' stub value impact analysis, crash pattern detection, and transformation rule enforcement. This was discovered during the less 692 port (2026-03-24).
For multi-file ports, the code-transformer agent handles all source files in a single dispatch — pass it the full list of files to transform. The build-manager iterates on all compile errors across all files.
Orchestration — Mandatory Agent Dispatch
Every stage MUST dispatch its designated agent. There is no "small project" exemption. The agents run stub value impact analysis, crash pattern detection, and transformation rule enforcement that inline work skips.
A PreToolUse hook (enforce-agents.sh) warns on direct edits to ported/*.c files (warn-only — subagents use the same tools). A PreToolUse hook (block-direct-gcc.sh) blocks direct compiler calls.
Sequential pipeline — each stage depends on the previous:
aminet-researcher → check prior art (Stage 0)
dependency-auditor → audit external library deps (Stage 0b, conditional — skip for stdlib-only projects)
source-analyzer → portability analysis with stub value impact analysis (Stage 1)
code-transformer → transformation with ADCD reference lookup (Stage 3)
hardware-expert → hardware assumption review (Stage 3b, conditional — Category 3+ ports only)
build-manager → compilation with error recovery (Stage 4)
test-designer → comprehensive test suite generation (Stage 5b)
test-runner → vamos testing (Stage 5)
memory-checker → mandatory memory safety (Stage 6b)
debug-agent → if crashes detected during FS-UAE testing
Exception: Stage 2 (directory setup) and Stage 7 (packaging) are mechanical and run inline.
Note: port-coordinator is deprecated — it cannot dispatch subagents (Claude Code limitation). Always orchestrate from the main session.
Error Recovery Between Stages
When a stage fails, don't just retry — diagnose which stage needs to be revisited:
| Symptom | Root Cause | Go Back To |
|---|
| Missing header during build | Incomplete transformation | Transform |
Undefined amiport_* function | Shim doesn't have this wrapper | Add to lib/posix-shim/ |
| Type mismatch error | Wrong POSIX→Amiga type mapping | Transform |
| Linker error: undefined symbol | Function not stubbed or shimmed | Transform or extend shim |
| Program crashes in vamos | Logic error in transformation | Debug output, fix transform |
| Wrong output in vamos | Behavioral difference in shim | Fix shim implementation |
| vamos "unknown library" | Program uses unsupported Amiga lib | Stub the library call |
Porting Log
Maintain a PORT.md file in ports/<name>/ using the template from ports/templates/PORT.md.template. Fill in all sections as the pipeline progresses — the Overview table at Stage 2, analysis at Stage 1, transformations at Stage 3, build info at Stage 4, test results at Stage 5, and review score at Stage 6.
Decision Points
At each stage, you may need to make judgment calls:
-
Tier 2 (emulation) features: Present caveats to user before applying. Link against libamiport-emu.a.
-
Tier 3 (redesign) features: Present redesign patterns from redesign-patterns.md. Wait for human decision. Do NOT auto-stub.
-
Unclassified blocking features: Stub with a warning message if non-essential. If core functionality, stop and ask.
-
Multiple source files: Transform all files, build all objects, link together. Update SOURCES in the Makefile to list all .c files.
-
External dependencies: If the project depends on external libraries, check if they've been ported. If not, note this as a limitation.
-
AmigaOS version: Default to 3.x. Only target earlier versions if specifically requested.
Boilerplate
Every ported program gets a version string with today's date:
static const char *verstag = "$VER: progname 1.0 (DD.MM.YYYY)";
Use the actual current date in DD.MM.YYYY format.
Success Criteria
A port is successful when:
- The binary compiles without errors
- Basic functionality works in vamos (Category 1-2) or builds cleanly (Category 3-4)
- Output matches the native version for standard test cases (where testable)
- PORT.md documents the entire process, including port category and test strategy
- The port is in
ports/<name>/ and buildable with make build TARGET=ports/<name>
Capture Learnings (REQUIRED — Final Step)
Before considering the port complete, review the session for any bugs, mistakes, or process failures. If any occurred, invoke /capture-learning to route the fix to the right enforcement mechanism (hook > rule > agent instruction > skill > pitfall > memory).
Check each agent's Learnings section in their reports — they flag pitfalls and process issues discovered during their work.
Listing Ports
After a successful port, make list-ports shows all ports and their status:
=== amiport ports ===
grep BUILT
tree READY
sed ORIGINAL ONLY