npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@robinpath/core

v0.36.1

Published

RobinPath - A lightweight, fast, and easy-to-use scripting language for automation and data processing.

Downloads

1,238

Readme

@robinpath/core

The core runtime for RobinPath — a lightweight scripting language for automation and data processing.

Installation

npm i @robinpath/core

Integration

Basic Usage

import { RobinPath } from '@robinpath/core';

const rp = new RobinPath();

const result = await rp.executeScript(`
  $items = ["apples", "bananas", "cherries"]
  for $item in $items
    log "Item: " + $item
  endfor
`);

REPL Mode (Persistent State)

Use executeLine() for REPL-like behavior where state persists between calls:

const rp = new RobinPath();

await rp.executeLine('$result = math.add 10 20');
console.log(rp.getLastValue()); // 30

await rp.executeLine('math.multiply $result 2');
console.log(rp.getLastValue()); // 60

Working with Variables

const rp = new RobinPath();

rp.setVariable('name', 'Alice');
rp.setVariable('age', 25);

await rp.executeScript(`
  log "Hello" $name
  log "Age:" $age
`);

const name = rp.getVariable('name'); // "Alice"

Threads (Isolated Execution Contexts)

const rp = new RobinPath({ threadControl: true });

const thread1 = rp.createThread('user-123');
await thread1.executeScript('$count = 10');

const thread2 = rp.createThread('user-456');
await thread2.executeScript('$count = 20');

console.log(thread1.getVariable('count')); // 10
console.log(thread2.getVariable('count')); // 20

Registering Custom Functions

const rp = new RobinPath();

rp.registerBuiltin('greet', (args) => {
  return `Hello, ${String(args[0] ?? 'World')}!`;
});

await rp.executeScript('greet "Alice"');
console.log(rp.getLastValue()); // "Hello, Alice!"

Registering Custom Modules

const rp = new RobinPath();

rp.registerModule('myapp', {
  process: (args) => {
    const data = args[0];
    return processedData;
  },
  validate: (args) => {
    return isValid(args[0]);
  }
});

rp.registerModuleFunctionMeta('myapp', 'process', {
  description: 'Processes input data',
  parameters: [
    { name: 'data', dataType: 'object', description: 'Data to process', formInputType: 'json', required: true }
  ],
  returnType: 'object',
  returnDescription: 'Processed data'
});

rp.registerModuleInfo('myapp', {
  description: 'Custom application module',
  methods: ['process', 'validate']
});

await rp.executeScript(`
  myapp.process $data
`);

Getting Available Commands

const rp = new RobinPath();

const commands = rp.getAvailableCommands();
console.log(commands.native);          // Native commands (if, def, etc.)
console.log(commands.builtin);         // Root-level builtins
console.log(commands.modules);         // Available modules
console.log(commands.moduleFunctions); // Module.function names
console.log(commands.userFunctions);   // User-defined functions

AST with Execution State

const rp = new RobinPath({ threadControl: true });
const thread = rp.createThread('debug');

const astResult = await thread.getASTWithState(`
  math.add 5 5
  $result = $
  if $result > 5
    math.multiply $result 2
  endif
`);

console.log(astResult.ast);
console.log(astResult.variables);
console.log(astResult.lastValue);

Checking for Incomplete Blocks

const rp = new RobinPath();

const check1 = rp.needsMoreInput('if $x > 5');
// { needsMore: true, waitingFor: 'endif' }

const check2 = rp.needsMoreInput('if $x > 5\n  log "yes"\nendif');
// { needsMore: false }

Error Handling

const rp = new RobinPath();

try {
  await rp.executeScript('unknown_function 123');
} catch (error) {
  console.error('Script error:', error.message);
}

CLI

The RobinPath CLI is available as a separate package:

npm i -g @robinpath/cli

Then run robinpath to start the AI-powered terminal.

Language Reference

Variables

$name = "Alice"
$age = 25
log $name $age

Last Value ($)

math.add 10 20
math.multiply $ 2   # Uses 30 (result of add)
log $                # Prints 60

Into Syntax

math.add 10 20 into $sum
log $sum  # 30

do into $blockResult
  math.add 5 5
  math.multiply $ 2
enddo
# $blockResult is 20

Conditionals

if $score >= 90
  log "Grade: A"
elseif $score >= 80
  log "Grade: B"
else
  log "Grade: F"
endif

Loops

for $i from 1 to 5
  log "Iteration:" $i
endfor

$numbers = [10, 11, 12]
for $num in $numbers
  log $num
endfor

repeat 5 with
  log "Iteration:" $1
endwith

Functions

def greet $name
  log "Hello, " + $name + "!"
  return "greeted"
enddef

greet "Alice"

Do Blocks (Scopes)

Regular do blocks share variables with the parent scope:

do
  $name = "Alice"
  $items = ["apples", "bananas"]
enddo
log $name   # "Alice" — accessible outside the block
for $item in $items
  log $item # works
endfor

Parameterized do blocks create isolated scopes:

$outer = 100
do $a $b
  # $outer is NOT accessible here
  # only $a and $b are available
enddo

Events

on "user_login"
  log "User logged in:" $1
endon

trigger "user_login" "Alice"

Parallel Execution

together
  do into $result1
    math.add 10 20
  enddo
  do into $result2
    math.multiply 5 6
  enddo
endtogether

Subexpressions

log "Result:" $(math.add 10 20)

$val = $(
  math.add 5 5
  math.multiply $ 2
)

Built-in Modules

  • math: add, subtract, multiply, divide, modulo, power, sqrt, abs, round, floor, ceil, min, max
  • string: length, substring, toUpperCase, toLowerCase, trim, replace, split, startsWith, endsWith, contains, indexOf
  • json: parse, stringify, isValid
  • object: keys, values, entries, merge, clone
  • time: now, timestamp, format, addDays, diffDays
  • random: int, float, uuid, choice
  • array: create, length, get, slice, push, concat, join
  • test: assertEqual, isEqual, isBigger, isSmaller, assertTrue, assertFalse, assertNull, assertContains

200+ additional modules available via npm install @robinpath/<module> — see robinpath.com/modules.

License

MIT