.agents/skills/node-best-practices/SKILL.md
Provides domain-specific best practices for Node.js development with TypeScript, covering type stripping, async patterns, error handling, streams, modules, testing, performance, caching, logging, and more. Use when setting up Node.js projects with native TypeScript support, configuring type stripping (--experimental-strip-types), writing Node 22+ TypeScript without a build step, or when the user mentions 'native TypeScript in Node', 'strip types', 'Node 22 TypeScript', '.ts files without compilation', 'ts-node alternative', or needs guidance on error handling, graceful shutdown, flaky tests, profiling, or environment configuration in Node.js. Helps configure tsconfig.json for type stripping, set up package.json scripts, handle module resolution and import extensions, and apply robust patterns across the full Node.js stack.
npx skillsauth add shandin17/paperclaw node-best-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill whenever you are dealing with Node.js code to obtain domain-specific knowledge for building robust, performant, and maintainable Node.js applications.
When writing TypeScript for Node.js, use type stripping (Node.js 22.6+) instead of build tools like ts-node or tsx. Type stripping runs TypeScript directly by removing type annotations at runtime without transpilation.
Key requirements for type stripping compatibility:
import type for type-only imports.ts extensions in importsMinimal example — a valid type-stripped TypeScript file:
// greet.ts
import type { IncomingMessage } from 'node:http';
const greet = (name: string): string => `Hello, ${name}!`;
console.log(greet('world'));
Run directly with:
node greet.ts
See rules/typescript.md for complete configuration and examples.
For multi-step processes, follow these high-level sequences before consulting the relevant rule file:
Graceful shutdown: Register signal handlers (SIGTERM/SIGINT) → stop accepting new work → drain in-flight requests → close external connections (DB, cache) → exit with appropriate code. See rules/graceful-shutdown.md.
Error handling: Define a shared error base class → classify errors (operational vs programmer) → add async boundary handlers (process.on('unhandledRejection')) → propagate typed errors through the call stack → log with context before responding or crashing. See rules/error-handling.md.
Diagnosing flaky tests: Isolate the test with --test-only → check for shared state or timer dependencies → inspect async teardown order → add retry logic as a temporary diagnostic step → fix root cause. See rules/flaky-tests.md.
Profiling a slow path: Reproduce under realistic load → capture a CPU profile with --cpu-prof → identify hot functions → check for stream backpressure or unnecessary serialisation → validate improvement with a benchmark. See rules/profiling.md and rules/performance.md.
Read individual rule files for detailed explanations and code examples:
tools
# Searcher Agent You find and retrieve documents from the user's archive. You have access to `qdrant` (semantic search) and `paperless` (full-text search and document fetch) tools. ## Mode behaviour - **document**: Return a list of matching documents. Include `fileToSend` with the best match so the user gets the original file. - **data**: Extract structured data from the best matching document(s). Return key-value pairs. Do NOT include `fileToSend`. - **both**: List documents AND extract data
tools
# Indexer Agent You store and classify documents. You have access to `paperless` tools and can invoke the `embedder` agent. ## Workflow 1. Use `paperless_upload` with `filePath: <fileUrl from input>` to upload the file. This returns `{ documentId, content }`. 2. Read the `content` field (OCR text) from the upload result. 3. Classify the document type (e.g. `passport`, `contract`, `invoice`, `medical`, `receipt`, `id_card`, `bank_statement`, `other`). 4. Generate a short descriptive title (e.g
documentation
# Form-Filler Agent You analyze forms and fill them using data from the user's stored documents. ## Workflow 1. The form file is passed to you as a base64 image in the user message. Analyze it visually. 2. Identify all fields in the form (name, date of birth, passport number, address, INN, etc.). 3. For each field, invoke `searcher` to find the relevant data: `invoke("searcher", { query: "<field description>", mode: "data" })`. 4. Map retrieved data to form fields. Record the source document
documentation
# Embedder Agent Custom runner — does not use an LLM. Chunks the input text, generates embeddings via OpenAI text-embedding-3-small, and upserts all vectors into Qdrant with document metadata.