Agent skill

Nodetool Custom Node Developer

by nodetool-ai in nodetool-ai/nodetool

Create or update TypeScript NodeTool nodes, decorated properties, process methods, and node packages.

AGPL-3.0Auto-check passedMedia & Creative

Install Nodetool Custom Node Developer

skills CLI
$ npx skills add nodetool-ai/nodetool --skill nodetool-custom-node-developer -a claude-code

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

GitHub CLI
$ gh skill install nodetool-ai/nodetool nodetool-custom-node-developer --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/nodetool-ai/nodetool.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/system-skills/nodetool-custom-node-developer .claude/skills/nodetool-custom-node-developer && 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
nodetool-custom-node-developer
GitHub stars
556
Token cost
~2k tokens
SKILL.md length
387 words
Files
1
Skills in repo
127
Repo updated
First seen
Licence
AGPL-3.0

At a glance

Create or update TypeScript NodeTool nodes, decorated properties, process methods, and node packages.

  • Media & Creative work in your project
  • SKILL.md covers Multi-Output Node, Streaming Node (genProcess), Stateful Collector and Enum Input, plus 3 more sections
  • Calls npm

What it does

Nodetool Custom Node Developer is an agent skill from nodetool-ai/nodetool. Create or update TypeScript NodeTool nodes, decorated properties, process methods, and node packages.

Its SKILL.md is about 2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Media & Creative. It works with TypeScript and npm. The repository describes itself as: Agent-first Creative Workspace. The licence is AGPL-3.0.

When your agent uses it

  • Media & Creative work in your project

Example prompts

  • “/nodetool-custom-node-developer”

Requirements

  • Node.js
  • A credential in MY_API_KEY

What it can do on your machine

Read from SKILL.md and the folder at commit 515bd28. 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

    Shell commands in SKILL.md call:

    • npm

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

  • Network

    No URLs in SKILL.md. Its commands use npm, 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

Nodetool Custom Node Developer loads about 2k tokens when it runs. Until then it costs about 33 tokens; SKILL.md has 387 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~33
When it runs · the whole SKILL.md, loaded when a task matches
~2k

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); files beside SKILL.md are not scanned.

SKILL.md

The full file from nodetool-ai/nodetool at commit 515bd28, republished under its AGPL-3.0 licence (© nodetool-ai). 387 words, ~1,967 tokens.

Download SKILL.mdSave it as .claude/skills/nodetool-custom-node-developer/SKILL.md (or your agent's skills folder).
name
nodetool-custom-node-developer
description
Create or update TypeScript NodeTool nodes, decorated properties, process methods, and node packages.

You are a NodeTool node developer. You create TypeScript nodes that extend BaseNode from @nodetool-ai/node-sdk.

Package Layout

my-nodes/
├── package.json          # depends on @nodetool-ai/node-sdk
├── tsconfig.json         # extends ../../tsconfig.base.json
├── src/
│   ├── index.ts          # exports registration function + ALL_NODES array
│   └── nodes/
│       ├── category-a.ts # node classes
│       └── category-b.ts
└── tests/
    └── nodes.test.ts

Node Template

typescript
import { BaseNode, prop } from "@nodetool-ai/node-sdk";

export class MyNode extends BaseNode {
  // REQUIRED static fields
  static readonly nodeType = "mypack.category.NodeName"; // namespace.category.Name
  static readonly title = "Human-Readable Title";
  static readonly description = "Brief description.\n    search, keywords, here";
  static readonly metadataOutputTypes = { output: "str" }; // declare all outputs

  // Inputs via @prop decorator
  @prop({ type: "str", default: "", title: "Input Text" })
  declare input_text: any;

  @prop({ type: "int", default: 10, min: 1, max: 100, title: "Count" })
  declare count: any;

  // Process method — MUST return all keys from metadataOutputTypes
  async process(): Promise<Record<string, unknown>> {
    const text = String(this.input_text ?? "");
    const count = Number(this.count ?? 10);
    return { output: text.repeat(count) };
  }
}

Input Resolution Pattern

Property values and connected input values are assigned to instance fields before process() is called, so always read inputs from this:

typescript
const value = this.field ?? defaultValue;
  • this.field — resolved value (connection value if connected, else the user-set property, else the @prop default)
  • defaultValue — extra in-code fallback for null/undefined

Do not declare a process(inputs: Record<string, unknown>) parameter — the runtime calls process(context?: ProcessingContext), so an inputs parameter typed that way fails strict type-checking.

@prop Decorator Options

OptionTypeNotes
typestringRequired: "int", "float", "str", "bool", "list[any]", "image", "audio", "video", "document", "dataframe", "enum", "any"
defaultunknownDefault value
titlestringDisplay name in UI
descriptionstringTooltip text
min / maxnumberNumeric bounds
requiredbooleanValidation flag
values(string|number)[]Enum options

Patterns

Multi-Output Node

typescript
static readonly metadataOutputTypes = { text: "str", confidence: "float" };

async process(): Promise<Record<string, unknown>> {
  return { text: "result", confidence: 0.95 }; // ALL keys must be returned
}

Streaming Node (genProcess)

typescript
static readonly isStreamingOutput = true;
static readonly metadataOutputTypes = { output: "str" };

async *genProcess(): AsyncGenerator<Record<string, unknown>> {
  for (const item of items) {
    yield { output: item };
  }
}

Stateful Collector

typescript
static readonly syncMode = "on_any"; // fires on each incoming value

@prop({ type: "any", title: "Item" })
declare item: unknown;

private collected: unknown[] = [];

async initialize(): Promise<void> {
  this.collected = []; // reset per run
}

async process(): Promise<Record<string, unknown>> {
  this.collected.push(this.item);
  return { output: this.collected };
}

Enum Input

typescript
@prop({ type: "enum", values: ["low", "medium", "high"], default: "medium", title: "Quality" })
declare quality: any;

Secrets / API Keys

typescript
static readonly requiredSettings = ["MY_API_KEY"];

async process(): Promise<Record<string, unknown>> {
  // Resolved secrets are available via the `_secrets` getter.
  const apiKey = this._secrets.MY_API_KEY || process.env.MY_API_KEY;
  if (!apiKey) throw new Error("MY_API_KEY not configured");
  // use apiKey...
}

Media Refs (Image/Audio/Video)

typescript
@prop({ type: "image", title: "Input Image" })
declare image: { uri?: string; data?: string } | undefined;

async process(): Promise<Record<string, unknown>> {
  const img = this.image;
  if (!img) throw new Error("No image provided");
  // img.data is base64, img.uri is a URL
  const resultData = await processImage(img);
  return { output: { type: "image", data: resultData } }; // return base64
}

Lifecycle Hooks

typescript
async initialize(): Promise<void> { }   // once at start of run
async preProcess(): Promise<void> { }   // before each process() call
async finalize(): Promise<void> { }     // after all processing

Optional Static Properties

typescript
static readonly isDynamic = true;            // dynamic schema
static readonly supportsDynamicOutputs = true;
static readonly isStreamingInput = true;
static readonly basicFields = ["prompt", "model"]; // shown first in UI

Scaffold a Pack

The fastest start is the scaffolder, which generates a self-contained pack (package.json with the nodetool manifest field, tsconfig, an example node, a test, and a README):

bash
npm run create:pack -- @myorg/my-nodes        # in the nodetool repo
# or directly: node scripts/create-pack.mjs @myorg/my-nodes ./my-nodes
Show full SKILL.md (202 more words)Show less

Registration

typescript
// src/index.ts
import type { NodeClass, NodeRegistry } from "@nodetool-ai/node-sdk";
import { MyNode, OtherNode } from "./nodes/my-nodes.js";

export const ALL_NODES: readonly NodeClass[] = [MyNode, OtherNode];

export function register(registry: NodeRegistry): void {
  for (const nodeClass of ALL_NODES) {
    registry.register(nodeClass);
  }
}

The server auto-loads packs — no need to edit its source. Mark the package as a pack with a nodetool field in package.json, naming the export above:

jsonc
{
  "name": "@myorg/my-nodes",
  "main": "dist/index.js",
  "nodetool": { "apiVersion": 1, "register": "register" }
}

On startup the server scans installed dependencies, imports any package with a nodetool field, and calls the named export with the registry. Install the built pack where the server can resolve it (npm install <pack>, or npm link for local dev) and restart. The export may be sync or async.

Trust model. Custom nodes run in-process as the server user (full filesystem/network/secret access, no sandbox), so loading is gated. In development unlisted packs load automatically; in production (NODETOOL_ENV=production) only packs on the allowlist (NODETOOL_PACKS_ALLOWLIST or ~/.config/nodetool/packs.json) load. Packs also cannot register under reserved namespaces (nodetool., lib., provider names) or shadow an existing node type. Only install packs you trust.

Testing

typescript
import { describe, it, expect } from "vitest";
import { MyNode } from "../src/nodes/my-nodes.js";

describe("MyNode", () => {
  it("processes input", async () => {
    // Constructor assigns properties to instance fields.
    const node = new MyNode({ input_text: "hello", count: 3 });
    const result = await node.process();
    expect(result.output).toBe("hellohellohello");
  });
});

Common Pitfalls

  • Forgetting output keys: Every key in metadataOutputTypes must appear in the return object
  • Wrong input access: Read inputs from this.field (assigned before process()); do not add an inputs parameter to process()
  • nodeType format: Must be namespace.category.Name with dots as separators
  • Mutable state without initialize(): If using instance fields, reset them in initialize()
  • Missing secrets declaration: Add to requiredSettings array for proper UI prompting

© nodetool-ai, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in packages/system-skills/nodetool-custom-node-developer of nodetool-ai/nodetool.

Open the folder on GitHubat commit 515bd28

Compare with similar skills

Nodetool Custom Node Developer 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.

Nodetool Custom Node Developer compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Nodetool Custom Node Developer this skillnodetool-ai/nodetool556—~2kAutomated safety check: PassAGPL-3.0
Add New Packageremotion-dev/remotion62k—~777Automated safety check: NotesCustom licence
MCP Server BuildershareAI-lab/learn-claude-code78k5 repos~1.2kAutomated safety check: PassMIT
Install Anti-Slop Oxlint Rulesdmmulroy/anti-slop5.3k1 repos~2.2kAutomated safety check: PassMIT
Link Workspace Packagesnomcopter/react-mosaic4.8k6 repos~760Automated safety check: PassCustom licence
Logseq Plugin SDKlogseq/logseq45k—~2.3kAutomated safety check: PassAGPL-3.0

Similar skills

  • Add New Package

    remotion-dev/remotion

    Official

    Add a new package to the Remotion monorepo, including package scaffolding, monorepo registration, documentation, build scripts, and release checklist updates.

    62k GitHub stars~777 tokensUpdated today
    Media & CreativeAuto-check: notes
  • MCP Server Builder

    shareAI-lab/learn-claude-code

    Walks through building MCP servers in Python or TypeScript that expose tools, resources and prompts to Claude, with templates, registration and testing.

    78k GitHub starsUsed in 5 repos~1.2k tokens
    Agent WorkflowsAuto-check passed
  • Installs, updates or migrates the vendored anti-slop Oxlint plugin in a repository, keeping local rule changes and the plugin's license and provenance files.

    5.3k GitHub starsUsed in 1 repo~2.2k tokens
    DevelopmentAuto-check passed
  • Link Workspace Packages

    nomcopter/react-mosaic

    Link workspace packages in monorepos (npm, yarn, pnpm, bun).

    4.8k GitHub starsUsed in 6 repos~760 tokens
    DevelopmentAuto-check passed
  • Logseq Plugin SDK

    logseq/logseq

    Build, debug, or review Logseq plugins with the @logseq/libs SDK (TypeScript/JavaScript, iframe/shadow sandboxed).

    45k GitHub stars~2.3k tokensUpdated today
    Knowledge ManagementAuto-check passed
  • Run the tests that cover a change in the pnpm repository, in the Rust workspace (pnpm/, pnpr/) or the TypeScript CLI (pnpm11/), and recognize the cases where a scoped run passes without testing…

    37k GitHub stars~1.1k tokensUpdated today
    DevelopmentAuto-check passed

More from nodetool-ai/nodetool

All 127 skills in this repo
  • Beat Sync Editing

    nodetool-ai/nodetool

    Cut a NodeTool timeline to music and shape its pacing — detect the beat grid, place cuts on phrases, pick a cut type, build speed ramps with time remap, and give the piece an arc.

    556 GitHub stars~2.6k tokensUpdated today
    Auto-check passed
  • Caption Titles

    nodetool-ai/nodetool

    Add and animate a consistent text layer on an existing NodeTool timeline.

    556 GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Color Motion

    nodetool-ai/nodetool

    Choose and animate colour on a NodeTool timeline, including shape and text gradients, colour grades, 3D LUTs, and dither.

    556 GitHub stars~2.3k tokensUpdated today
    Auto-check passed
  • Commercial Beat Sheet

    nodetool-ai/nodetool

    Write a shootable, precisely timed commercial beat sheet and store it as a NodeTool storyboard, with a consistent entity roster behind every shot.

    556 GitHub stars~4.6k tokensUpdated today
    Auto-check passed
  • Elevenlabs Audio Prompting

    nodetool-ai/nodetool

    Direct ElevenLabs speech, dialogue, sound effects and music — the bracketed audio tags v3 acts on and why the voice decides whether a tag lands, stability as the delivery dial, punctuation instead…

    556 GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Frame Composition

    nodetool-ai/nodetool

    Stage the frame on a NodeTool timeline — grids, focal placement, safe areas per aspect ratio, depth layers and parallax, camera moves, and where elements enter and leave.

    556 GitHub stars~3.5k tokensUpdated today
    Auto-check passed

Works with

Questions about Nodetool Custom Node Developer

What does Nodetool Custom Node Developer do?

Create or update TypeScript NodeTool nodes, decorated properties, process methods, and node packages. Nodetool Custom Node Developer is an agent skill from nodetool-ai/nodetool. Create or update TypeScript NodeTool nodes, decorated properties, process methods, and node packages.

When should I use Nodetool Custom Node Developer?

Nodetool Custom Node Developer fits situations like: media & Creative work in your project.

How do I install Nodetool Custom Node Developer in Claude Code?

Run `npx skills add nodetool-ai/nodetool --skill nodetool-custom-node-developer -a claude-code`. Or copy the skill folder (packages/system-skills/nodetool-custom-node-developer in nodetool-ai/nodetool) into .claude/skills/nodetool-custom-node-developer in your project. Claude Code loads it when a task matches its description.

How do I install Nodetool Custom Node Developer in Codex?

Run `npx skills add nodetool-ai/nodetool --skill nodetool-custom-node-developer -a codex`. Or copy the skill folder (packages/system-skills/nodetool-custom-node-developer in nodetool-ai/nodetool) into .agents/skills/nodetool-custom-node-developer in your project. Codex loads it when a task matches its description.

Can I use Nodetool Custom Node Developer 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 nodetool-ai/nodetool --skill nodetool-custom-node-developer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/nodetool-custom-node-developer, .gemini/skills/nodetool-custom-node-developer, .github/skills/nodetool-custom-node-developer and .opencode/skills/nodetool-custom-node-developer in your project.

What does Nodetool Custom Node Developer need to run?

Going by SKILL.md and its folder, Nodetool Custom Node Developer needs the command-line tools its instructions call (npm). Our summary lists: Node.js; A credential in MY_API_KEY.

Does Nodetool Custom Node Developer access the network?

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

Is Nodetool Custom Node Developer 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. Review the folder before installing.

What licence does Nodetool Custom Node Developer use?

Nodetool Custom Node Developer is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Nodetool Custom Node Developer use?

About 2k tokens (SKILL.md is roughly 7.9k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Nodetool Custom Node Developer?

Skills that share tags, products or a category with Nodetool Custom Node Developer: Add New Package (remotion-dev/remotion, 62k stars), MCP Server Builder (shareAI-lab/learn-claude-code, 78k stars), Install Anti-Slop Oxlint Rules (dmmulroy/anti-slop, 5.3k stars) and Link Workspace Packages (nomcopter/react-mosaic, 4.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Nodetool Custom Node Developer?

nodetool-ai (a GitHub organization) maintains it in nodetool-ai/nodetool, which has 556 GitHub stars. The repository holds 127 skills in this directory. The repository was last updated on October 8, 2026.

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