jcubic/lips

Scheme based powerful lisp interpreter in JavaScript

JavaScript

511

3,408 commits

updated Oct 18, 2026

See the code

See what people are saying

SourceMessageScoreDate

Resumed my work on continuations and tail call optimization in my Scheme interpreter called LIPS. Just released a new beta version: https://lips.js.org/

on Ask HN: What are you working on? (August 2026)

0

Aug 17, 2026

Show HN: Lips Scheme 1.0.0-beta.22 with full call/cc and TCO

20

Aug 17, 2026

LIPS Scheme – Powerful Scheme Based Lisp in JavaScript

1

Jul 31, 2026

>> What other language would people choose in a browser? Lua? Brendan Eich originally wanted to use Scheme. There are some Scheme in Javascript implementations: https://www.biwascheme.org/ https://lips.js.org/ https://www.wescheme.org/ https://web.scheme.org/

on PyScript: An open source platform for Python in the browser

0

Aug 16, 2024

LIPS: Scheme based Lisp interpreter in JavaScript

87

Dec 30, 2023

Sweet, I'll have to give that a go :) Another option in browser land is lips[0], which exclusively targets a js backend. [0] https://lips.js.org

on (learn 'scheme)

0

Oct 30, 2023

and then https://github.com/wisp-lang/wisp/blob/master/doc/language-e... and I'm sure I've seen a time travelling debuggable js-transpiled thing long ago ps: oh and this https://github.com/paulitex/Wisp pps: ok i'm digressing https://lips.js.org/

on Guile Steel: a proposal for a systems Lisp

0

Jul 11, 2022

My side projects are mainly Open Source JavaScript libraries * LIPS: https://lips.js.org/ Powerful Scheme-based Lisp interpreter in JavaScript * jQuery Terminal: https://terminal.jcubic.pl/ for building CLI applications in Browser * Sysend.js: https://github.com/jcubic/sysend.js for sending…

on Ask HN: What is your current side-project?

0

Jun 4, 2021

Lips: Powerful Scheme-based Lisp interpreter in JavaScript

1

May 25, 2021

I've created [jQuery Terminal][0] in about 2010 I think it was first library that allow to create CLI applications in Browser. I've started it because I wanted to have SSH like experience on my shared hosting that didn't provide SSH access. I've build application using my Terminal, called…

on Ask HN: What are some tools / libraries you built yourself?

0

May 22, 2021

README

LIPS - Scheme Based Powerful Lisp Language

X (formerly Twitter) Follow npm 1.0.0 Complete Build and test Coverage Status Join Gitter Chat NPM Download Count JSDelivr Download count Ask DeepWiki

GitHub stars Tweet

LIPS is a powerful Scheme-based, Lisp language written in JavaScript. It is based on the Scheme dialect of lisp and the R5RS/R7RS specifications. It has extensions to make it easier to interact with JavaScript and extend the language. It works both in the browser and with Node.js.

The aim of the project is to support full R7RS specification and be compatible with Scheme programming language.

The name is a recursive acronym which stands for LIPS Is Pretty Simple.

Demo

Web REPL Demo

Features

  • Literal regular expressions.
  • Asynchronous execution (auto resolving of promises).
  • Possibility to add new syntax (similar to vectors and object).
  • Full numerical tower and Big Integer support.
  • Powerful introspection.
  • Great integration with JavaScript.
  • Full continuations and TCO.
  • Code formatting (pretty print).
  • Lisp and hygienic Scheme macros and macroexpand.
  • Builtin help system.

Installation

Node.js

To install you can use npm, which comes with Node.js or any other package manager (e.g.: yarn, bun, or pnpm)

The easiet way to install and use LIPS is via npx command (part of NPM):

npx lips@beta

Or you can install it:

npm install -g lips@beta

You can also install it as part of your Node project.

Browser

You need to include the javascript file in script tag inside your HTML.

You an grag the main file from jsDelivr:

<script src="https://cdn.jsdelivr.net/npm/lips@beta/dist/lips.min.js"></script>

Bookmarklet REPL

You can also run the REPL on any page while you learn Scheme using the bookmarklet:

https://github.com/jcubic/lips/blob/master/lib/js/bookmark.js

Create any link in your bookmarks, edit it and copy-paste the content of that file. After you click on the link it will create the REPL at the bottom of the page. (NOTE: It may not work on every page because of content security policy; e.g. google.com or gihub.com)

If you have trouble with creating the bookmarklet, you can open LISP Scheme home page where you can find a link that you can drag to your bookmarks.

Usage

Browser

The simplest way is to include the lips code in the script tag:

<script type="text/x-scheme" bootstrap>
(let ((what "world")
      (greet "hello"))
   (display (string-append greet " " what)))
</script>

or use the src attribute:

<script type="text/x-scheme" bootstrap src="example.scm"></script>

Node.js

You can use the REPL by typing:

lips

Or create a script using shebang:

#!/usr/bin/env -S lips

(print "Hello, world!")

If you save this into hello.scm and make it executable:

chmod a+x hello.scm

You can execute the script:

./hello.scm

it should print Hello, world!.

Bootstrapping Scheme system

Big part of LIPS is written in LIPS itself, but to use full power of LIPS you need to load those additional Scheme files. The easiest way is to add bootstrap attribute on first script tag with text/x-scheme type. By default, it will use CDN from jsdelivr. To load each file using builtin load function (that will fetch the file using AJAX and evaluate it).

<script src="https://cdn.jsdelivr.net/npm/lips@beta/dist/lips.min.js" bootstrap></script>

You can also specify the path where LIPS should search for standard library.

<script src="https://cdn.jsdelivr.net/npm/lips@beta/dist/lips.min.js"
        bootstrap="https://cdn.jsdelivr.net/npm/lips@beta/dist/std.xcb">
</script>

You can use bootstrap="./std.xcb" if there is std.xcb file in local directory. You can also bootstrap with std.scm or std.min.scm but xcb file is the fastest, because it's already parsed and compiled into binary format.

Running LIPS programmatically

var {exec} = require('lips'); // node
// or
var {exec} = lips; // browser

exec(string).then(function(results) {
     results.forEach(function(result) {
        console.log(result.toString());
     });
});

When running exec you will also need to bootstrap the language and loaded files from /lib/ directory.

Documentation about beta version can be found in Wiki.

Standalone executable

NOTE: Executable don't require bootstrapping lib files.

If you install lips globally with:

npm install -g lips@beta

you can run the interpreter from the terminal:

LIPS: Scheme interactive terminal

You can also run code in a string with:

lips -c '(let ((what "World")) (display (string-append "Hello " what)))'

and you can run a file using:

cat > foo.scm <<EOF
(let ((what "World"))
  (display (string-append "Hello " what))
  (newline))
EOF

lips foo.scm

You can also write executable files that use lips using shebang (SRFI-22)

cat foo.scm
#!/usr/bin/env lips

(let ((what "World"))
  (display (string-append "Hello " what))
  (newline))

chmod a+x foo.scm
./foo.scm

Executables also return a S-Expression according to SRFI-176 use lips --version or lips -V.

FOSDEM'23 Presentation [Video]

FOSDEM 2023 - LIPS Scheme: Powerful introspection and extensibility

Limitations

Performance

Because LIPS is tree walking interpreter, sometimes it may be slow. Especially if you want to process long arrays and use callback function. If the array is quite large each piece of code inside the callback may slow down the processing. For example see:

script reference.scm

That generates reference documentation for all builtin functions and macros. The slow part is (names.sort name-compare) (Array::sort) that take quite time to calculate, because the array with functions and macros is quite large. If you came into performance issue, you can write the part of the code in JavaScript. If you want to do this in LIPS Scheme you can use something like this:

(let ((fn (self.eval "(function(a, b) {
                         /* any complex code in JS */
                         return a.localeCompare(b);
                      })")))
   (arr.sort fn))

Another example of slow performance is using LIPS with React, the more code you put into components the slower the app will become.

Examples:

The issue with performance is tracked in #197.

Supported SRFI

built-in

descriptionspec
Feature-based conditional expansion constructSRFI-0
Homogeneous numeric vector datatypesSRFI-4
Basic String PortsSRFI-6
Running Scheme Scripts on UnixSRFI-22
Error reporting mechanismSRFI-23
Basic Format StringsSRFI-28
Basic Syntax-rules ExtensionsSRFI-46
An interface to access environment variablesSRFI-98
Syntax parametersSRFI-139
Custom macro transformersSRFI-147
Version flagSRFI-176
Command lineSRFI-193
Mixing groups of definitions with expressions within bodiesSRFI-251

require manual loading

You can load the SRFI with special syntax that start with @lips which points to root LIPS directory:

(load "@lips/lib/srfi/<number>.scm")

They should be loaded as R7RS libraries in final 1.0.0 version

descriptionspec
List LibrarySRFI-1
AND-LET*: an AND with local bindings, a guarded LET* special formSRFI-2
receive: Binding to multiple valuesSRFI-8
#, external formSRFI-10
Notation for Specializing Parameters without CurryingSRFI-26
Basic hash tablesSRFI-69
BoxesSRFI-111
Syntactic combiners for binary predicatesSRFI-156
Multiple-value boxesSRFI-195
Pipeline OperatorsSRFI-197
Procedures and Syntax for Multiple ValuesSRFI-210
Evaluating expressions in an unspecified orderSRFI-236
Destructuring ListsSRFI 239
Uninterned SymbolsSRFI 258

in Web (e.g. in Web REPL) you can also use full URL:

(load "https://cdn.jsdelivr.net/npm/lips@beta/lib/srfi/<NUMBER>.scm")

Articles

Press

Roadmap

1.0

  • Full support for R5RS
  • Full support for R7RS
    • R7RS libraries (import/export/define-library).
    • Continuations.
    • Tail Call Optimization (TCO).
    • Fully tested Numerical Tower.
  • Fully working binary compiler (for faster parsing and loading std lib).
  • Finish syntax-rules (ignore limitations of current approach).
    • Vectors.

Future Plans

  • Picture language (possibly inspired by P5.js, see SRFI-203).
  • Stepper/Debugger.
  • Allow to use read/port in syntax extensions (similar to CL reader macros).
  • Proper expansion time for both macro systems.
  • Fully working and tested R7RS hygienic Macros (syntax-rules).
  • All recursive function in JS don't consume stack.

WIP Side projects

  • KISS (Chrome extension REPL).
  • SMILE (Web IDE), need to start over.

How you can help

I'm working on version 1.0. If you find any bugs, you can help by reporting them. If you have some Scheme code that doesn't work (note about the limitations) don't hesitate to report an issue.

You can also propose a feature or improvement to the library, it doesn't always have to be defects.

If you enjoy the library, you can write about it on a blog post and share information about it or write on Social Media. Don't forget to link to the project website (it's good for SEO).

Of course, if you like, you can also contribute with code, but there are way easier ways to help.

I would also love to see if you use the library; I may even share the links of projects that use it.

Acknowledgments

Special thanks:

Thanks to Algolia DocSearch for providing free search on the LIPS website.

License

Released under MIT license
Copyright (c) 2018-2026 Jakub T. Jankiewicz

bookmarklet
hacktoberfest
language
lisp
lisp-interpreter
lisp-language
macros
parser
r5rs
r5rs-scheme
r7rs
r7rs-scheme
repl
scheme
scheme-interpreter
s-expression
support-bigint

Project health

Overall

4.5/10

Maintained

10/10

Code review

1/10
OpenSSF Scorecard

Latest release

0.20.3 · Mar 25, 2021

Releases this year

0
Deprecated

Significant stargazers

Alan Dipert

472 followers · starred Dec 2020

lassik

120 followers · starred Dec 2020

Luan Taraschi

8 followers · starred Aug 2026

Sunny

185 followers · starred Aug 2026

jcubic/lips

Scheme based powerful lisp interpreter in JavaScript

JavaScript

511

3,408 commits

updated Oct 18, 2026

See the code

See what people are saying

SourceMessageScoreDate

Resumed my work on continuations and tail call optimization in my Scheme interpreter called LIPS. Just released a new beta version: https://lips.js.org/

on Ask HN: What are you working on? (August 2026)

0

Aug 17, 2026

Show HN: Lips Scheme 1.0.0-beta.22 with full call/cc and TCO

20

Aug 17, 2026

LIPS Scheme – Powerful Scheme Based Lisp in JavaScript

1

Jul 31, 2026

>> What other language would people choose in a browser? Lua? Brendan Eich originally wanted to use Scheme. There are some Scheme in Javascript implementations: https://www.biwascheme.org/ https://lips.js.org/ https://www.wescheme.org/ https://web.scheme.org/

on PyScript: An open source platform for Python in the browser

0

Aug 16, 2024

LIPS: Scheme based Lisp interpreter in JavaScript

87

Dec 30, 2023

Sweet, I'll have to give that a go :) Another option in browser land is lips[0], which exclusively targets a js backend. [0] https://lips.js.org

on (learn 'scheme)

0

Oct 30, 2023

and then https://github.com/wisp-lang/wisp/blob/master/doc/language-e... and I'm sure I've seen a time travelling debuggable js-transpiled thing long ago ps: oh and this https://github.com/paulitex/Wisp pps: ok i'm digressing https://lips.js.org/

on Guile Steel: a proposal for a systems Lisp

0

Jul 11, 2022

My side projects are mainly Open Source JavaScript libraries * LIPS: https://lips.js.org/ Powerful Scheme-based Lisp interpreter in JavaScript * jQuery Terminal: https://terminal.jcubic.pl/ for building CLI applications in Browser * Sysend.js: https://github.com/jcubic/sysend.js for sending…

on Ask HN: What is your current side-project?

0

Jun 4, 2021

Lips: Powerful Scheme-based Lisp interpreter in JavaScript

1

May 25, 2021

I've created [jQuery Terminal][0] in about 2010 I think it was first library that allow to create CLI applications in Browser. I've started it because I wanted to have SSH like experience on my shared hosting that didn't provide SSH access. I've build application using my Terminal, called…

on Ask HN: What are some tools / libraries you built yourself?

0

May 22, 2021

README

LIPS - Scheme Based Powerful Lisp Language

X (formerly Twitter) Follow npm 1.0.0 Complete Build and test Coverage Status Join Gitter Chat NPM Download Count JSDelivr Download count Ask DeepWiki

GitHub stars Tweet

LIPS is a powerful Scheme-based, Lisp language written in JavaScript. It is based on the Scheme dialect of lisp and the R5RS/R7RS specifications. It has extensions to make it easier to interact with JavaScript and extend the language. It works both in the browser and with Node.js.

The aim of the project is to support full R7RS specification and be compatible with Scheme programming language.

The name is a recursive acronym which stands for LIPS Is Pretty Simple.

Demo

Web REPL Demo

Features

  • Literal regular expressions.
  • Asynchronous execution (auto resolving of promises).
  • Possibility to add new syntax (similar to vectors and object).
  • Full numerical tower and Big Integer support.
  • Powerful introspection.
  • Great integration with JavaScript.
  • Full continuations and TCO.
  • Code formatting (pretty print).
  • Lisp and hygienic Scheme macros and macroexpand.
  • Builtin help system.

Installation

Node.js

To install you can use npm, which comes with Node.js or any other package manager (e.g.: yarn, bun, or pnpm)

The easiet way to install and use LIPS is via npx command (part of NPM):

npx lips@beta

Or you can install it:

npm install -g lips@beta

You can also install it as part of your Node project.

Browser

You need to include the javascript file in script tag inside your HTML.

You an grag the main file from jsDelivr:

<script src="https://cdn.jsdelivr.net/npm/lips@beta/dist/lips.min.js"></script>

Bookmarklet REPL

You can also run the REPL on any page while you learn Scheme using the bookmarklet:

https://github.com/jcubic/lips/blob/master/lib/js/bookmark.js

Create any link in your bookmarks, edit it and copy-paste the content of that file. After you click on the link it will create the REPL at the bottom of the page. (NOTE: It may not work on every page because of content security policy; e.g. google.com or gihub.com)

If you have trouble with creating the bookmarklet, you can open LISP Scheme home page where you can find a link that you can drag to your bookmarks.

Usage

Browser

The simplest way is to include the lips code in the script tag:

<script type="text/x-scheme" bootstrap>
(let ((what "world")
      (greet "hello"))
   (display (string-append greet " " what)))
</script>

or use the src attribute:

<script type="text/x-scheme" bootstrap src="example.scm"></script>

Node.js

You can use the REPL by typing:

lips

Or create a script using shebang:

#!/usr/bin/env -S lips

(print "Hello, world!")

If you save this into hello.scm and make it executable:

chmod a+x hello.scm

You can execute the script:

./hello.scm

it should print Hello, world!.

Bootstrapping Scheme system

Big part of LIPS is written in LIPS itself, but to use full power of LIPS you need to load those additional Scheme files. The easiest way is to add bootstrap attribute on first script tag with text/x-scheme type. By default, it will use CDN from jsdelivr. To load each file using builtin load function (that will fetch the file using AJAX and evaluate it).

<script src="https://cdn.jsdelivr.net/npm/lips@beta/dist/lips.min.js" bootstrap></script>

You can also specify the path where LIPS should search for standard library.

<script src="https://cdn.jsdelivr.net/npm/lips@beta/dist/lips.min.js"
        bootstrap="https://cdn.jsdelivr.net/npm/lips@beta/dist/std.xcb">
</script>

You can use bootstrap="./std.xcb" if there is std.xcb file in local directory. You can also bootstrap with std.scm or std.min.scm but xcb file is the fastest, because it's already parsed and compiled into binary format.

Running LIPS programmatically

var {exec} = require('lips'); // node
// or
var {exec} = lips; // browser

exec(string).then(function(results) {
     results.forEach(function(result) {
        console.log(result.toString());
     });
});

When running exec you will also need to bootstrap the language and loaded files from /lib/ directory.

Documentation about beta version can be found in Wiki.

Standalone executable

NOTE: Executable don't require bootstrapping lib files.

If you install lips globally with:

npm install -g lips@beta

you can run the interpreter from the terminal:

LIPS: Scheme interactive terminal

You can also run code in a string with:

lips -c '(let ((what "World")) (display (string-append "Hello " what)))'

and you can run a file using:

cat > foo.scm <<EOF
(let ((what "World"))
  (display (string-append "Hello " what))
  (newline))
EOF

lips foo.scm

You can also write executable files that use lips using shebang (SRFI-22)

cat foo.scm
#!/usr/bin/env lips

(let ((what "World"))
  (display (string-append "Hello " what))
  (newline))

chmod a+x foo.scm
./foo.scm

Executables also return a S-Expression according to SRFI-176 use lips --version or lips -V.

FOSDEM'23 Presentation [Video]

FOSDEM 2023 - LIPS Scheme: Powerful introspection and extensibility

Limitations

Performance

Because LIPS is tree walking interpreter, sometimes it may be slow. Especially if you want to process long arrays and use callback function. If the array is quite large each piece of code inside the callback may slow down the processing. For example see:

script reference.scm

That generates reference documentation for all builtin functions and macros. The slow part is (names.sort name-compare) (Array::sort) that take quite time to calculate, because the array with functions and macros is quite large. If you came into performance issue, you can write the part of the code in JavaScript. If you want to do this in LIPS Scheme you can use something like this:

(let ((fn (self.eval "(function(a, b) {
                         /* any complex code in JS */
                         return a.localeCompare(b);
                      })")))
   (arr.sort fn))

Another example of slow performance is using LIPS with React, the more code you put into components the slower the app will become.

Examples:

The issue with performance is tracked in #197.

Supported SRFI

built-in

descriptionspec
Feature-based conditional expansion constructSRFI-0
Homogeneous numeric vector datatypesSRFI-4
Basic String PortsSRFI-6
Running Scheme Scripts on UnixSRFI-22
Error reporting mechanismSRFI-23
Basic Format StringsSRFI-28
Basic Syntax-rules ExtensionsSRFI-46
An interface to access environment variablesSRFI-98
Syntax parametersSRFI-139
Custom macro transformersSRFI-147
Version flagSRFI-176
Command lineSRFI-193
Mixing groups of definitions with expressions within bodiesSRFI-251

require manual loading

You can load the SRFI with special syntax that start with @lips which points to root LIPS directory:

(load "@lips/lib/srfi/<number>.scm")

They should be loaded as R7RS libraries in final 1.0.0 version

descriptionspec
List LibrarySRFI-1
AND-LET*: an AND with local bindings, a guarded LET* special formSRFI-2
receive: Binding to multiple valuesSRFI-8
#, external formSRFI-10
Notation for Specializing Parameters without CurryingSRFI-26
Basic hash tablesSRFI-69
BoxesSRFI-111
Syntactic combiners for binary predicatesSRFI-156
Multiple-value boxesSRFI-195
Pipeline OperatorsSRFI-197
Procedures and Syntax for Multiple ValuesSRFI-210
Evaluating expressions in an unspecified orderSRFI-236
Destructuring ListsSRFI 239
Uninterned SymbolsSRFI 258

in Web (e.g. in Web REPL) you can also use full URL:

(load "https://cdn.jsdelivr.net/npm/lips@beta/lib/srfi/<NUMBER>.scm")

Articles

Press

Roadmap

1.0

  • Full support for R5RS
  • Full support for R7RS
    • R7RS libraries (import/export/define-library).
    • Continuations.
    • Tail Call Optimization (TCO).
    • Fully tested Numerical Tower.
  • Fully working binary compiler (for faster parsing and loading std lib).
  • Finish syntax-rules (ignore limitations of current approach).
    • Vectors.

Future Plans

  • Picture language (possibly inspired by P5.js, see SRFI-203).
  • Stepper/Debugger.
  • Allow to use read/port in syntax extensions (similar to CL reader macros).
  • Proper expansion time for both macro systems.
  • Fully working and tested R7RS hygienic Macros (syntax-rules).
  • All recursive function in JS don't consume stack.

WIP Side projects

  • KISS (Chrome extension REPL).
  • SMILE (Web IDE), need to start over.

How you can help

I'm working on version 1.0. If you find any bugs, you can help by reporting them. If you have some Scheme code that doesn't work (note about the limitations) don't hesitate to report an issue.

You can also propose a feature or improvement to the library, it doesn't always have to be defects.

If you enjoy the library, you can write about it on a blog post and share information about it or write on Social Media. Don't forget to link to the project website (it's good for SEO).

Of course, if you like, you can also contribute with code, but there are way easier ways to help.

I would also love to see if you use the library; I may even share the links of projects that use it.

Acknowledgments

Special thanks:

Thanks to Algolia DocSearch for providing free search on the LIPS website.

License

Released under MIT license
Copyright (c) 2018-2026 Jakub T. Jankiewicz

bookmarklet
hacktoberfest
language
lisp
lisp-interpreter
lisp-language
macros
parser
r5rs
r5rs-scheme
r7rs
r7rs-scheme
repl
scheme
scheme-interpreter
s-expression
support-bigint

Project health

Overall

4.5/10

Maintained

10/10

Code review

1/10
OpenSSF Scorecard

Latest release

0.20.3 · Mar 25, 2021

Releases this year

0
Deprecated

Significant stargazers

Alan Dipert

472 followers · starred Dec 2020

lassik

120 followers · starred Dec 2020

Luan Taraschi

8 followers · starred Aug 2026

Sunny

185 followers · starred Aug 2026