sebastienrousseau/agtmls/cross-language-port
Claude Code and agent skill by sebastienrousseau/agtmls
- community
Checking that the SKILL.md file is still in the repository.
Port a module, CLI, or function between Rust, Python, Go, C++, Swift, TypeScript, JavaScript, Ruby, and Bash - preserving logic, adopting target idioms, and proving equivalence with a differential golden-I/O harness. Use for 'port/rewrite this in <lang>'. Not micro-snippets or redesigns.
Install
npx vskill@latest install sebastienrousseau/agtmls/cross-language-portSKILL.md
Skill: cross-language porting
Trigger. The user asks to port this, translate to [Language], rewrite in [Language], convert this to [Language], reimplement X in [Language], or give me the [Language] equivalent.
Reference material (the full cross-language idiom-mapping matrix,per-language porting notes + landmines, the equivalence-harness recipes,and the data-boundary/FFI contracts): seereference.mdin thisdirectory. This file is the doctrine + the execution loop;reference.mdis the lookup and the recipes.
Objective
Port a specific module, script, CLI, or function from a source language to a target language so that:
- Behaviour is preserved exactly — same inputs produce same outputs,
same errors, same side-effect ordering. This is proven, not asserted (see §4).
- The output is idiomatic — it reads as if a senior engineer *native
to the target language* wrote it from the spec, not transliterated line-for-line from the source.
- It lands green — formatted, linted, and tested with the target
language's own toolchain before you call it done.
Supported languages (the fleet)
Every one is a first-class source and target. Anchor per language — full toolchain rows (formatter / linter / test runner / package manager / error model / async model / HTTP / JSON) are in reference.md §R1.
| Language | Idiom anchor | Format · Lint · Test | |
|---|---|---|---|
| Rust | ownership, Result<T,E> + ?, traits over inheritance | rustfmt · clippy -D warnings · cargo test | |
| Python | duck typing, EAFP, type hints + mypy, context managers | ruff format · ruff + mypy · pytest | |
| Go | (T, error) returns, goroutines + channels, small interfaces | gofmt · go vet + golangci-lint · go test | |
| C++ | RAII, std::expected/exceptions, smart pointers, no raw new | clang-format · clang-tidy · GoogleTest/Catch2 | |
| Swift | throws/Result, async/await + actors, value types, Codable | swift-format · SwiftLint · swift-testing/XCTest | |
| TypeScript | discriminated unions, strict mode, async/await, no any | prettier · eslint + tsc --noEmit · vitest | |
| JavaScript | async/await, modules, immutability by default | prettier · eslint · vitest/node:test | |
| Ruby | blocks/enumerables, raise/rescue, duck typing | rubocop -a · rubocop · RSpec/minitest | |
| Bash/Shell | set -euo pipefail, exit codes, pipes, trap | shfmt · shellcheck · bats |
Do not invent a target outside this set without confirming it exists in the fleet (github.com/sebastienrousseau). If the user names one that isn't here, port it anyway but say the target is outside the standard fleet.
Execution plan
Six phases. Do not skip §4 — it is what separates a port from a guess.
- Scope & contract. Read the source in full. Write down, in prose, the
observable contract: inputs (types, ranges, encodings), outputs, error conditions, side effects and their ordering, and any concurrency. This contract — not the source lines — is what you port. If the contract is ambiguous, that ambiguity is the first thing to resolve.
- Source analysis. Identify the core algorithm, external dependencies
(I/O, network, filesystem, env), edge-case handling, and the concurrency model. Flag anything source-language-specific that has no direct target analogue (GIL assumptions, Go's zero values, Rust lifetimes, Ruby monkey-patching, Bash word-splitting) — these are the porting risks.
- Idiom mapping. Map each construct to its idiomatic target
equivalent, not its literal one. Use the matrix in reference.md §R1. The load-bearing axes:
- Error model — source exceptions → target's
Result/error/
throws/exit-code convention. Never smuggle try/except into Rust or if err != nil into Python.
- Concurrency —
asyncio.gather↔Promise.all↔tokio::join!↔
goroutines+WaitGroup↔Swift TaskGroup↔Ruby threads↔std::async↔ Bash &+wait.
- Collections & iteration — comprehensions ↔ iterator combinators ↔
range-for ↔ enumerables ↔ streams. Prefer the target's expression form when it's clearer, not shorter for its own sake.
- Data boundaries — see §3 boundary rules.
- Translate. Write the target code from the contract, in the target's
idiom. Rules:
- Not a 1:1 line translation. Restructure so it reads native.
- Adopt the target error model fully.
- Use vetted standard libraries, named in
reference.md§R1/§R2
(e.g. Python requests→Rust reqwest, C++ std::thread→Go goroutines, JS Promise.all→Python asyncio.gather).
- Respect the target's memory/ownership model — RAII in C++, borrow
discipline in Rust, ARC in Swift; do not paper over it with clones or unsafe/any.
- Prove behavioural equivalence (the load-bearing phase). Build a
golden-I/O corpus from the source — representative inputs paired with the source's actual outputs — then run the port against the same corpus and diff. Any divergence is a port bug until explained. For pure functions, add a property test asserting port(x) == reference(x) over generated inputs. The full differential-harness recipe (per language pair) is in reference.md §R3. "It compiles and looks right" is not equivalence.
- Land it green. Run
harness/port-check.sh <target-lang> <files>—
it formats-checks, lints/typechecks, and compiles/syntax-gates with the target's toolchain, and must print GREEN before you're done. Deliver the ported file(s) + the equivalence tests + the golden corpus.
Data-boundary & interop rules
When the port keeps a foot in both languages (a Python service shelling out to a new Rust binary, a Go caller of a C++ FFI shim, a TS frontend hitting a new Ruby endpoint), enforce a structured contract at the boundary — JSON, Protocol Buffers, or a strict CLI stdout/exit-code contract. Never ad-hoc string-parse across a language boundary. Boundary specifics (serialization parity, integer-width and float-format traps, error propagation across the seam) are in reference.md §R4.
Safety at the port boundary
- Secrets never move into source. If the original read a key from env or
a vault, the port does too — don't inline a value you found in a fixture.
- Re-validate all input in the target. A port is a fresh attack surface;
the source's validation assumptions may not survive the idiom change (Bash word-splitting → argv, Python int bignum → Rust i64 overflow, JS number precision → other languages' integer types).
- No new `unsafe` (Rust) / `any` (TS) / raw `new` (C++) / `eval` to
force a shortcut. If the idiomatic path needs one, that's a design question to surface, not a silent choice.
Worked examples
Runnable, verified ports live in examples/ — each a reference.<ext> (source) + port.<ext> (idiomatic target) + golden corpus/ + verify.sh that proves equivalence. Study the one closest to your port before starting; copy its shape. Roster (examples/README.md indexes them), each teaching a distinct landmine:
- `py-to-rust-iban/` — Python → Rust; integer width (bignum
% 97→
incremental mod, because the value overflows u128).
- `bash-to-python-pathdedupe/` — Bash → Python; word-splitting + glob
expansion of unquoted $var (a /tmp/* segment must stay literal).
- `js-to-ts-configvalidate/` — JavaScript → TypeScript; runtime type
erasure (validate unknown at the boundary; a type cast validates nothing).
- `go-to-rust-fraction/` — Go → Rust;
(T, error)+ zero values →
Result + ?, and matching Go's split semantics exactly.
- `rust-to-swift-op/` — Rust → Swift;
enumassociated values map 1:1,
but Result → throws (adopt the target's error channel).
- `py-to-go-duration/` — Python → Go; exceptions →
if err != nil, no
sum types (control flow inverts from throw/catch to return/check).
- `py-to-cpp-hexcolor/` — Python → C++; exceptions →
std::expected
(C++23) and RAII (no new/delete).
- `ruby-to-python-histogram/` — Ruby → Python; Enumerable/
tally/blocks
→ Counter + comprehensions (watch the codepoint sort order).
Eight directions covering all nine fleet languages. Every verify.sh is a thin wrapper over the shared runner in harness/ (golden-diff.sh + differential property-test templates). Run every proof at once:
When NOT to use this skill
- Micro-porting (a single function of a few lines) — do it inline in the
conversation without invoking this skill.
- Behaviour-changing rewrites — that's a redesign, not a port. Clarify
the intended new behaviour with the user first; the equivalence harness in §5 assumes the contract is preserved.
- Porting *within* a language (2→3, ES5→ESNext, C++17→23) — that's a
migration/modernization, not a cross-language port.
Provenance & maintenance
- Fleet languages are derived from the active repos at
github.com/sebastienrousseau (Rust, Python, Go, C++, Swift, TypeScript, JavaScript, Ruby, Shell). Re-derive with: gh api 'users/sebastienrousseau/repos?per_page=100&type=owner' --jq '.[]|select(.fork==false)|.language' | sort | uniq -c | sort -rn
- Toolchain rows in
reference.md§R1 name current-stable tools; re-verify
a formatter/linter/test-runner exists before scripting it into a port.
- Last reviewed against the fleet: 2026-07-08.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/cross-language-port/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/sebastienrousseau/agtmls/cross-language-port)