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

@lionlang/core

v0.1.1

Published

Lion is a JSON-based Lisp.

Downloads

20

Readme

Lion

Lion is a JSON-based Lisp. Every Lion program is valid JSON, which makes it easy to serialize, store, inspect, and generate from other systems.

Lion evaluates:

  • JSON primitives directly
  • strings as environment references when a binding exists
  • arrays as special forms or function-call expressions
  • objects by recursively evaluating their values

The result is a small homoiconic language that can describe both computation and data interchange without a separate parser.

Packages

packages/
  core/   evaluator, special forms, stdlib
  repl/   interactive web REPL
  agent/  real-world Lion program driving an OpenTUI + AI agent

Basic Usage

import { Effect } from "effect";
import { run } from "@lionlang/core/evaluation/evaluate";
import { stdlib } from "@lionlang/core/modules";

const result = await Effect.runPromise(
	run(["number/add", 1, 2], stdlib)
);

// => 3

Custom Environment

Any string can resolve against the evaluation environment. That includes values, objects, classes, and functions.

import { Effect } from "effect";
import { run } from "@lionlang/core/evaluation/evaluate";
import { stdlib } from "@lionlang/core/modules";

const env = {
	...stdlib,
	price: 100,
	taxRate: 0.08,
	clamp: (min: number, max: number, value: number) =>
		Math.min(max, Math.max(min, value)),
};

await Effect.runPromise(
	run(["number/add", "price", ["number/multiply", "price", "taxRate"]], env)
);
// => 108

await Effect.runPromise(run(["clamp", 0, 100, 150], env));
// => 100

Expression Model

Primitives

Numbers, booleans, and null evaluate to themselves. Strings are treated as references first; if no binding exists, the original string is returned.

42
true
null
"x"

With { "x": 10 } in the environment, "x" evaluates to 10. Otherwise it evaluates to "x".

Arrays

Arrays are always treated as executable expressions:

  1. special forms such as ["define", "x", 1]
  2. function calls when the first element evaluates to a function
["number/add", 1, 2]

Evaluates to 3.

Objects

Objects preserve their keys and evaluate each value.

{
  "sum": ["number/add", 1, 2],
  "ok": true
}

Evaluates to { "sum": 3, "ok": true }.

Special Forms

quote

Returns its argument without evaluating it.

["quote", ["number/add", 1, 2]]

eval

Evaluates its argument, then evaluates the result.

["eval", ["quote", ["number/add", 1, 2]]]

begin

Evaluates expressions in order and returns the last result.

["begin", ["define", "x", 1], ["define", "x", 2], "x"]

define

Evaluates a value, stores it in the global environment, and returns the stored value.

["define", "answer", 42]

lambda

Creates a Lion function with lexical scope.

["lambda", ["x"], ["number/add", "x", 1]]

Lambdas close over surrounding scope, and they observe updated global bindings when invoked later.

cond

Evaluates condition/result pairs in order and returns the first matching result. An else branch is optional.

["cond",
  [["number/greaterThan", "score", 90], "great"],
  [["number/greaterThan", "score", 70], "pass"],
  ["else", "retry"]]

If no branch matches and no else is provided, cond returns null.

match

Pattern matches a value against predicate/function pairs, then applies the first matching branch. The last argument is a fallback function.

["match",
  "value",
  ["value/number?", ["lambda", ["x"], ["number/add", "x", 1]]],
  ["value/string?", ["lambda", ["x"], ["string/concat", "x", "!"]]],
  ["lambda", ["x"], "x"]]

match also supports structural predicates:

["match",
  { "type": "user", "profile": { "name": "Ada" } },
  [
    {
      "type": ["func/partial", "string/equals?", "user"],
      "profile": { "name": "value/string?" }
    },
    "value/identity"
  ],
  ["lambda", ["x"], null]]

Standard Library

The default environment exported as stdlib namespaces entries as <module>/<name>.

number

["number/add", 1, 2]
["number/subtract", 10, 3]
["number/multiply", 5, 4]
["number/divide", 20, 4]
["number/equals?", 5, 5]
["number/lessThan", 3, 5]
["number/greaterThan", 5, 3]
["number/lessThanOrEqualTo", 3, 5]
["number/greaterThanOrEqualTo", 5, 5]

boolean

["boolean/not", true]
["boolean/and", true, false]
["boolean/or", false, true]
["boolean/xor", true, false]
["boolean/nand", true, true]
["boolean/nor", false, false]
["boolean/equals?", true, true]

array

["array/make", 1, 2, 3]
["array/head", ["array/make", 1, 2, 3]]
["array/tail", ["array/make", 1, 2, 3]]
["array/length", ["array/make", 1, 2, 3]]
["array/concat", ["array/make", 1, 2], ["array/make", 3, 4]]
["array/includes?", ["array/make", 1, 2, 3], 2]
["array/map", ["array/make", 1, 2, 3], ["lambda", ["x"], ["number/add", "x", 1]]]
["array/flat-map", ["array/make", 1, 2], ["lambda", ["x"], ["array/make", "x", "x"]]]
["array/reduce", ["array/make", 1, 2, 3], 0, ["lambda", ["acc", "x"], ["number/add", "acc", "x"]]]

string

["string/equals?", "a", "a"]
["string/length", "lion"]
["string/concat", "lion", "ized"]
["string/startsWith", "lion", "li"]
["string/endsWith", "lion", "on"]
["string/includes", "lion", "io"]
["string/indexOf", "lion", "o"]

object

["object/get", {"a": 1}, "a"]
["object/get-path", {"a": {"b": {"c": 42}}}, "a.b.c"]
["object/keys", {"a": 1, "b": 2}]
["object/values", {"a": 1, "b": 2}]
["object/json-stringify", {"a": 1}, null, 2]
["object/get-method", "obj", "methodName"]
["object/call-method", "obj", "methodName", 1, 2]
["object/get-method-path", "obj", "nested.methodName"]
["object/call-method-path", "obj", "nested.methodName", 1, 2]
["object/new", "SomeClass", "arg1", "arg2"]

object/get-path understands dot paths and numeric array segments such as "users.1.name".

func

["func/bind", "fn", "obj"]
["func/apply", "fn", "obj", 1, 2]
["func/callback", ["lambda", ["x"], ["number/add", "x", 1]]]
["func/partial", "fn", 1, 2]

func/callback is especially useful for turning Lion lambdas into JavaScript callbacks while preserving access to the Lion environment.

value

["value/function?", "x"]
["value/number?", 1]
["value/string?", "lion"]
["value/boolean?", true]
["value/object?", {"a": 1}]
["value/array?", ["array/make", 1, 2]]
["value/null?", null]
["value/identity", 42]

value/undefined? and value/symbol? are mainly useful when Lion is evaluating host values supplied through the environment.

console

["console/log", "hello"]
["console/log-json", {"hello": "world"}]

Host Interop

Lion works well as a configuration and orchestration layer over ordinary JavaScript objects and functions.

The packages/agent package is the clearest example. It injects:

  • OpenTUI classes and enums
  • AI SDK helpers
  • a model instance
  • Node fs
  • Zod constructors
  • a renderer instance

Then Lion code in packages/agent/src/agent.json uses:

  • object/get-path to traverse host APIs
  • object/new to construct classes
  • object/call-method via aliases such as "()"
  • func/callback to hand Lion lambdas to promise and event APIs
  • match, cond, begin, and define to orchestrate application flow

That lets Lion drive a non-trivial terminal UI agent entirely from JSON.

Development

From the repo root:

bun install
bun run prepare
bun test
bun run build

To work on a specific package:

turbo test --filter=@lionlang/core
turbo dev --filter=@lionlang/repl