Agent skill

Port Node Red Node

by oldrev in oldrev/edgelinkd

Port a Node-RED node into EdgeLinkd the way this repo does it: implement the node in Rust under crates/core/src/runtime/nodes, mirror Node-RED's mocha spec as pytest tests under tests/, register the…

Apache-2.0Auto-check passedTesting & QA

Install Port Node Red Node

skills CLI
$ npx skills add oldrev/edgelinkd --skill port-node-red-node -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install oldrev/edgelinkd port-node-red-node --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/oldrev/edgelinkd.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/port-node-red-node .claude/skills/port-node-red-node && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
port-node-red-node
GitHub stars
121
Token cost
~3k tokens
SKILL.md length
1,241 words
Files
5 (incl. scripts, references)
Skills in repo
1
Repo updated
First seen
Licence
Apache-2.0

At a glance

Port a Node-RED node into EdgeLinkd the way this repo does it: implement the node in Rust under crates/core/src/runtime/nodes, mirror Node-RED's mocha spec as pytest tests under tests/, register the…

  • Works in 7 steps: Read the two upstream files → Implement the Rust node → Rust unit tests (expected for… → …
  • Debug an existing node
  • SKILL.md covers Prerequisites, Step 1 — Read the two upstream…, Step 2 — Implement the Rust node and Step 3 — Rust unit tests…, plus 6 more sections
  • Runs Python scripts from its folder; calls cargo, pytest and python

What it does

Port Node Red Node is an agent skill from oldrev/edgelinkd. Port a Node-RED node into EdgeLinkd the way this repo does it: implement the node in Rust under crates/core/src/runtime/nodes, mirror Node-RED's mocha spec as pytest tests under tests/, register the pair in scripts/specsdiff.json, then prove it with scripts/specsdiff.py. Also use it to finish, extend or debug an existing node, or to report which Node-RED spec tests are still missing.

Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 6 other files, including scripts and reference files (for example `references/python-spec-tests.md`, `references/rust-node-authoring.md` and `references/spec-coverage-audit.md`).

It sits in Testing & QA, covering Unit testing. It works with Rust and pytest. The repository describes itself as: Node-RED Reimplemented in Rust. The licence is Apache-2.0.

When your agent uses it

  • Debug an existing node
  • Report which Node-RED spec tests are still missing

Example prompts

  • “/port-node-red-node”

Requirements

  • Python 3
  • Node.js

Workflow steps

7 steps, taken from the step headings in SKILL.md.

  1. Read the two upstream files
  2. Implement the Rust node
  3. Rust unit tests (expected for non-trivial logic)
  4. Port the spec to pytest
  5. Register the pair in scripts/specs_diff.json
  6. Verify
  7. Commit

What it can do on your machine

Read from SKILL.md and the folder at commit adde082. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships 1 file in scripts/ (Python), which the agent can run.

    Shell commands in SKILL.md call:

    • cargo
    • pytest
    • python
    • git
    • npm
    • pip

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use git, npm and pip, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Port Node Red Node loads about 3k tokens when it runs, and up to ~11k if it reads all its reference files. Until then it costs about 102 tokens; SKILL.md has 1,241 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~102
When it runs · the whole SKILL.md, loaded when a task matches
~3k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~11k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.

SKILL.md

The full file from oldrev/edgelinkd at commit adde082, republished under its Apache-2.0 licence (© oldrev). 1,241 words, ~2,978 tokens.

Download SKILL.mdSave it as .claude/skills/port-node-red-node/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.
name
port-node-red-node
description
Port a Node-RED node into EdgeLinkd the way this repo does it: implement the node in Rust under crates/core/src/runtime/nodes, mirror Node-RED's mocha spec as pytest tests under tests/, register the pair in scripts/specs_diff.json, then prove it with scripts/specs_diff.py. Also use it to finish, extend or debug an existing node, or to report which Node-RED spec tests are still missing.
whenToUse
A task asks to implement, port, complete or debug a Node-RED node in EdgeLinkd; to translate a Node-RED *_spec.js into the pytest suite; or to report and…

Port a Node-RED node into EdgeLinkd

EdgeLinkd re-implements Node-RED nodes in Rust, and mirrors Node-RED's own mocha spec suite as pytest tests. For the behaviour we support, a node is only done when all three artifacts exist and the coverage checker agrees:

#ArtifactLocation
1Rust node implementation (self-registering)crates/core/src/runtime/nodes/<category>/<name>.rs
2Ported spec tests (one pytest test per upstream it(), skipped with a reason when out of scope)tests/nodes/<category>/test_<name>_node.py
3Audit entry mapping the twoscripts/specs_diff.json

EdgeLinkd is embedded-first, so a node may deliberately support only part of its upstream behaviour. Behaviour we support must match Node-RED exactly; out-of-scope behaviour is still ported as a title and marked @pytest.mark.skip(reason=...) (see step 4). Never ship a half-working option that looks supported — see the design philosophy in AGENTS.md.

Verification is the [✓] "<name>" (n/n) line for the node you touched in python scripts/specs_diff.py <absolute path to 3rd-party/node-red>, plus cargo fmt --check, clippy and the Rust tests. (The checker's own exit code is global — the repo still has nodes with unported specs, so it can be non-zero even when your node is complete.)

Prerequisites

bash
git submodule update --init --recursive     # populates 3rd-party/node-red (v4.0.9)
(cd 3rd-party/node-red && npm install)      # mocha, needed by scripts/specs_diff.py
pip install -r ./tests/requirements.txt     # pytest, pytest-asyncio, pytest-it, pytest-json-report, ...
cargo build --all                           # also builds the edgelink_pymod Python extension

The pytest suite does not run the edgelinkd binary: tests/__init__.py loads target/<EDGELINK_BUILD_TARGET>/<EDGELINK_BUILD_PROFILE>/edgelink_pymod.{pyd,dll,so}, so those two env vars must match the way you built:

powershell
$env:EDGELINK_BUILD_TARGET=""; $env:EDGELINK_BUILD_PROFILE="debug"   # default: target/debug
pytest ./tests/nodes/<category>/test_<name>_node.py -v

CI uses cargo build --profile ci --workspace --features full with EDGELINK_BUILD_PROFILE=ci; see .github/workflows/CICD.yml.

Step 1 — Read the two upstream files

For a node whose spec lives in test/nodes/core/<nr_category>/<nn>-<name>_spec.js:

Upstream filePath (relative to 3rd-party/node-red)
JS implementationpackages/node_modules/@node-red/nodes/core/<nr_category>/<nn>-<name>.js
Behaviour + palette HTMLpackages/node_modules/@node-red/nodes/core/<nr_category>/<nn>-<name>.html
mocha spec (the contract)test/nodes/core/<nr_category>/<nn>-<name>_spec.js

Read the spec first: its describe('...') and it('...') titles are the acceptance criteria and their exact text must be reproduced in Python. Then read the JS implementation for the behaviour (defaults, property names, error paths, edge cases).

The <name> part of the filename is usually the flow-JSON "type" you must register in Rust (16-range.js → "type": "range"); check the .js RED.nodes.registerType(...) call when it differs.

Step 2 — Implement the Rust node

Full skeleton, APIs and conventions: references/rust-node-authoring.md.

  1. Add crates/core/src/runtime/nodes/<category>/<name>.rs (use a directory with mod.rs when the node is big, like function/, trigger/, switch/).
  2. Declare it in that category's mod.rs (mod <name>;, wrapped in #[cfg(feature = "...")] if the category is feature-gated). Registration itself is automatic: the #[flow_node] macro inventory::submit!s a MetaNode, and RegistryBuilder::with_builtins() picks it up — there is no central node list.
  3. Reuse the existing helpers instead of hand-rolling: with_uow for the receive→process→fan-out loop, fan_out_one/fan_out_many for output, evaluate_node_property_value for typed properties, json::deser::* for config fields, report_status/report_error for observability.
  4. Add new dependencies behind a Cargo feature in crates/core/Cargo.toml when the node needs one (see nodes_xml, nodes_mqtt, ...).

Step 3 — Rust unit tests (expected for non-trivial logic)

Put them in the same file under #[cfg(test)] mod tests, driven by build_test_engine(json!([...])) + engine.run_once_with_inject(...) / run_once(...). Use #[tokio::test(flavor = "multi_thread", worker_threads = 4)] whenever the flow touches the JS function node or context.* (those paths use block_in_place), plain #[tokio::test] otherwise. Details in the Rust reference.

Rust unit tests are for logic that is awkward to express through flow JSON. The spec port below is what proves Node-RED compatibility — do not skip it.

Step 4 — Port the spec to pytest

Full harness reference: references/python-spec-tests.md.

Create tests/nodes/<category>/test_<name>_node.py:

python
import pytest
from tests import *

@pytest.mark.describe('range Node')                # == the JS describe(...) title
class TestRangeNode:
    @pytest.mark.asyncio
    @pytest.mark.it('ranges numbers up tenfold')   # == the JS it(...) title, character for character
    async def test_0001(self):
        ...

Rules that the coverage checker enforces:

  • @pytest.mark.describe text and @pytest.mark.it text must be identical to the JS ones (mocha fullTitle is describe + " " + it, and specs_diff.py compares those strings, so a typo, a difference in spacing or a smart quote shows up as a gap).
  • One Python test per upstream it(). Keep the upstream order and number the test methods (test_0001, test_0002, ...) as the existing files do.
  • Every upstream it() gets a title, including the ones we do not support. Mark those @pytest.mark.skip(reason="<feature> is out of scope: <why>"). specs_diff.py collects with -p no:skip, so a skipped test still counts as covered — the reason= string is the only written record of the gap, which is why it is mandatory and has to name the unsupported feature. A skip never means "not fixed yet": never skip a spec for behaviour we claim to support.
  • "should be loaded"-style tests are usually ported as a bare pass body.

Drive the node with the helpers from tests/__init__.py (run_single_node_with_msgs_ntimes, run_with_single_node_ntimes, run_flow_with_msgs_ntimes); they build the inject → node → test-once flow for you and return the messages that reached the end of the flow.

Step 5 — Register the pair in scripts/specs_diff.json

Add [<display name>, "nodes/<category>/test_<name>_node.py", "test/nodes/core/<nr_category>/<nn>-<name>_spec.js"] to the matching category (paths are relative to tests/ and to the Node-RED root).

Step 6 — Verify

bash
cargo build --all
pytest ./tests/nodes/<category>/test_<name>_node.py -v

# authoritative coverage check for every registered node; writes the report and
# exits 0 only when the Python suite covers every upstream it().
# Use an ABSOLUTE Node-RED path: the script chdir()s into it before resolving specs.
python scripts/specs_diff.py "$PWD/3rd-party/node-red" -o tests/REDNODES-SPECS-DIFF.md

cargo fmt --check
cargo clippy --all-features --tests --all
cargo test -p edgelink-core           # or: cargo test --workspace --features full

Read the checker's output for your node: [✓] "range" (13/13) means complete, [×] plus - lines list the upstream tests you still owe. Triage rules, the JSON format and the offline fallback script are in references/spec-coverage-audit.md.

Show full SKILL.md (479 more words)Show less

Step 7 — Commit

Follow CONTRIBUTING.md: present tense, imperative, subject ≤ 72 characters, English. Keep the Rust node and its spec port in the same commit, and never commit generated artifacts (tests/REDNODES-SPECS-DIFF.md is regenerated by the script and is tracked — refresh it deliberately only when it is part of the change you intend).

Pitfalls

  • Editing the generated report by hand. tests/REDNODES-SPECS-DIFF.md is produced by specs_diff.py; regenerate, don't patch.
  • Title drift. Moving/renaming an it() in Python breaks coverage silently; the checker only reports a -/+ pair, not a rename.
  • Nested describe blocks. Stack one @pytest.mark.describe per level, outer first, or the fullTitle misses the prefix and the checker reports every test of that block as missing. See references/python-spec-tests.md.
  • The pytest bridge cannot carry Buffers. Variant::Bytes has no JSON representation, so binary-payload spec tests are unportable; skip them with reason="binary payloads cannot cross the pytest bridge". nexpected=0 returns without running the flow, so "should emit nothing" cannot be observed that way.
  • Half-working behaviour that looks supported. An option that is accepted and then ignored, a todo!(), or a fabricated value is worse than an honest gap, because the user cannot tell the difference. When a code path reaches something we do not support, return EdgelinkError::NotSupported (or a node error/status) — and port the corresponding spec as a skip carrying the reason.
  • Never copy an upstream node id into flow JSON. An ElementId is a u64 written in hex (1..16 digits), so a copied id (n1, splitNode1) — and even a hex-encoded long name — is rejected with "failed to parse ElementId". Convert with the harness helper red_id(), which digests the name into 16 digits, together with every reference to it — z, wires, scope, injection targets — or the flow silently splits into disconnected nodes and the test just times out. See references/python-spec-tests.md.
  • nexpected mismatch. The Python helpers wait for exactly nexpected messages and then fail with a timeout; assert on fewer messages by splitting into several tests.
  • Forgetting the mod declaration. The macro self-registers, but the file still has to be compiled in via the category mod.rs; an unreferenced file is silently dead.
  • red_name vs type. The first macro argument is the flows.json "type" and must match Node-RED exactly, otherwise existing flows.json files won't bind to your node.
  • Feature flags. Feature-gated nodes must be added to the [features] list in crates/core/Cargo.toml and reachable from the app's default features, or the node will be missing at runtime while everything still compiles.
  • Blocking in async. Never call blocking/wait helpers inside a node task; the engine runs nodes on a shared tokio runtime (see SyncWaitableFuture for the one sanctioned exception used by the JS context bridge).

Reference map

FileContents
references/rust-node-authoring.mdRust node skeleton, runtime APIs, config/msg handling, error handling, unit tests
references/python-spec-tests.mdpytest harness helpers, markers, title matching, running the suite
references/spec-coverage-audit.mdspecs_diff.json format, running/extracting the audit, triage, offline fallback
scripts/spec-gaps.pyFast offline approximation of the audit (no mocha/pytest needed)

© oldrev, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 4 other files (scripts, references) in .agents/skills/port-node-red-node of oldrev/edgelinkd.

  • SKILL.md
  • references/python-spec-tests.md
  • references/rust-node-authoring.md
  • references/spec-coverage-audit.md
  • scripts/spec-gaps.py

Open the folder on GitHubat commit adde082

Compare with similar skills

Port Node Red Node next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Port Node Red Node compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Port Node Red Node this skilloldrev/edgelinkd121—~3kAutomated safety check: PassApache-2.0
Rust TDD Workflowrtk-ai/rtk83k—~753Automated safety check: NotesApache-2.0
Adk Verify Snippetsgoogle/adk-python22k—~1.4kAutomated safety check: PassApache-2.0
RTK Filter TDD in Rustrtk-ai/rtk83k—~1.9kAutomated safety check: NotesApache-2.0
Hermetic Python Unit TestsdimensionalOS/dimos4.6k—~1.4kAutomated safety check: PassCustom licence
Test GuardamElnagdy/guard-skills1.3k2 repos~2.1kAutomated safety check: PassMIT

Similar skills

  • Enforces red-green-refactor for Rust work, with idiomatic test patterns, a naming convention and a pre-commit gate of cargo fmt, clippy and test.

    83k GitHub stars~753 tokensUpdated today
    Testing & QAAuto-check: notes
  • Adk Verify Snippets

    google/adk-python

    Official

    Checks that every Python code block in a Markdown file actually compiles and runs, by extracting each block to a temporary file, executing it in an isolated subprocess, and writing a pass/fail…

    22k GitHub stars~1.4k tokensUpdated today
    Testing & QAAuto-check passed
  • Enforces red-green-refactor for new RTK output filters in Rust, using real captured fixtures, snapshot tests with insta and token-savings assertions.

    83k GitHub stars~1.9k tokensUpdated today
    Testing & QAAuto-check: notes
  • Hermetic Python Unit Tests

    dimensionalOS/dimos

    Rules for writing, fixing and reviewing pytest unit tests that are hermetic: behavior-focused, deterministic, isolated and cheap to run.

    4.6k GitHub stars~1.4k tokensUpdated today
    Testing & QAAuto-check passed
  • Test Guard

    amElnagdy/guard-skills

    Reviews newly written or edited tests against nine rules that cut test bloat, such as mock-heavy checks and near-duplicate cases, before they are committed.

    1.3k GitHub starsUsed in 2 repos~2.1k tokens
    Testing & QAAuto-check passed
  • Fla Optimization Loop

    fla-org/flash-linear-attention

    Disciplined, reproducible loop for making an FLA kernel faster (Triton, Gluon, TileLang, CuTe) without ever breaking or gaming correctness.

    5.8k GitHub stars~2.6k tokensUpdated yesterday
    Testing & QAAuto-check passed

Works with

Categories

Questions about Port Node Red Node

What does Port Node Red Node do?

Port a Node-RED node into EdgeLinkd the way this repo does it: implement the node in Rust under crates/core/src/runtime/nodes, mirror Node-RED's mocha spec as pytest tests under tests/, register the…. Port Node Red Node is an agent skill from oldrev/edgelinkd.py.

When should I use Port Node Red Node?

Port Node Red Node fits situations like: debug an existing node; report which Node-RED spec tests are still missing.

How do I install Port Node Red Node in Claude Code?

Run `npx skills add oldrev/edgelinkd --skill port-node-red-node -a claude-code`. Or copy the skill folder (.agents/skills/port-node-red-node in oldrev/edgelinkd) into .claude/skills/port-node-red-node in your project. Claude Code loads it when a task matches its description.

How do I install Port Node Red Node in Codex?

Run `npx skills add oldrev/edgelinkd --skill port-node-red-node -a codex`. Or copy the skill folder (.agents/skills/port-node-red-node in oldrev/edgelinkd) into .agents/skills/port-node-red-node in your project. Codex loads it when a task matches its description.

Can I use Port Node Red Node in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add oldrev/edgelinkd --skill port-node-red-node -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/port-node-red-node, .gemini/skills/port-node-red-node, .github/skills/port-node-red-node and .opencode/skills/port-node-red-node in your project.

What does Port Node Red Node need to run?

Going by SKILL.md and its folder, Port Node Red Node needs Python for the scripts in its folder and the command-line tools its instructions call (cargo, pytest, python, git, npm and pip). Our summary lists: Python 3; Node.js.

Does Port Node Red Node access the network?

SKILL.md contains no URLs. Its commands use git, npm and pip, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Port Node Red Node safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.

What licence does Port Node Red Node use?

Port Node Red Node is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Port Node Red Node use?

About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 7.9k tokens, read only when the agent opens those files.

What are the alternatives to Port Node Red Node?

Skills that share tags, products or a category with Port Node Red Node: Rust TDD Workflow (rtk-ai/rtk, 83k stars), Adk Verify Snippets (google/adk-python, 22k stars), RTK Filter TDD in Rust (rtk-ai/rtk, 83k stars) and Hermetic Python Unit Tests (dimensionalOS/dimos, 4.6k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Port Node Red Node?

oldrev (a GitHub user) maintains it in oldrev/edgelinkd, which has 121 GitHub stars. The repository was last updated on October 6, 2026.

Source: oldrev/edgelinkd on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.