BiwaScheme runs Scheme in the browser and on Node, minus three R7RS features
Scheme interpreter written in JavaScript
At a glance
- What is it?
- BiwaScheme is a Scheme interpreter written in JavaScript, distributed as a single script file, an npm package with a biwas command, and a bundler friendly module. It implements most of R7RS small but lists syntax-rules, exceptions and the library system as missing, and it inherits two JavaScript limits that will not be fixed.
- Who is it for?
- BiwaScheme suits a teaching project, a browser toy, or a Node script that wants an embeddable Scheme without a native toolchain, and it is a reasonable choice for a page that wants to run user supplied Scheme in the browser. It is the wrong tool for a program needing syntax-rules, exception handling or the R7RS library system, and it is the wrong tool for any code that depends on mutable strings or on integer arithmetic that stays integral.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One interpreter file that runs in a page, on a phone and under Node
BiwaScheme is a Scheme interpreter written in JavaScript. That single sentence covers the whole design: there is no native process, no compiler, and no build step required to use it. The README states that it works with web browsers including mobile devices, and with Node.js.
The distribution is unusually simple for a language implementation. The download link points at the project website, and the README adds that you can just copy the file from the ./release directory. The npm package publishes exactly five files: bin/biwas, release/node_biwascheme.js, release/biwascheme.js, release/biwascheme.mjs and release/biwascheme-min.js. There is no runtime dependency other than optparse, a command line option parser used by the CLI.
That matters for anyone who wants Scheme inside an existing page. You can serve one JavaScript file and evaluate Scheme in the visitor's browser with no server round trip, which is the use case that separates BiwaScheme from a Scheme that compiles to bytecode. The cost of that portability is the set of limitations described further down, since JavaScript's own semantics leak into the language you program against.
The repository also carries a tuplespace/ directory, matching the tuplespace topic on the project, and a website/ directory with the documentation, plus demo/ files including a REPL page.
Scheme source in the page runs from a text/biwascheme script block
The how to use section shows the shortest possible integration, and it is worth reading closely because it uses a non standard script type rather than a function call. The page provides a div with the id bs-console, loads the interpreter with a plain script tag, and then puts Scheme code in a second script tag whose type is text/biwascheme.
<!DOCTYPE html>
<html>
<body>
<div id="bs-console"></div>
<script src="biwascheme.js"></script>
<script type="text/biwascheme">
(display "hello, world!")
</script>
</body>
</html>The console div is what the interpreter renders into, so the page needs a mount point before the interpreter runs. The type attribute is the mechanism: the interpreter finds those blocks and evaluates their contents as Scheme, which is why the demo does not call an eval function by hand.
For a static site this is a complete deployment. There is no build, no bundler and no server component, and the same file works for a phone browser. The trade-off is that the page evaluates whatever Scheme it contains as it loads, so any page that lets users type Scheme needs the interactive path instead of this one.
Two ways to reach it from a terminal: the biwas command or require
Running a Scheme file under Node takes two steps. The interpreter is installed globally with npm, a file is written, and the biwas command runs it:
npm install -g biwascheme
biwas a.scmThe file itself is ordinary Scheme, and the example in the README writes a display call followed by a newline call, so output lands on standard output the way you would expect from a script.
Embedding works through the module entry point instead. The package main field points at ./release/node_biwascheme.js, and the example shows a require call followed by a run invocation:
var BiwaScheme = require("biwascheme");
BiwaScheme.run("(+ 1 2)"); // or BiwaScheme.run_file("a.scm");Two functions cover the common cases. run takes source as a string, and run_file takes a path. There is also a third packaging target for bundlers: the npm package contains biwascheme.mjs, which is what the browser field points at, so a bundler such as rollup can consume it directly.
One packaging caveat is documented. The README notes that biwascheme.mjs does not include jQuery, unlike the biwascheme-x.y.z.js file, and that you need to bundle jQuery manually if you want to use the functions defined in src/library/webscheme_lib.js. The browser specific library is therefore not portable into a bundle without extra work.
Most of R7RS small is implemented, with three named gaps
The conformance section links to the project's own feature list and states that BiwaScheme implements most of the features of R7RS small, including first class continuations and tail call optimization. That is a serious claim for a JavaScript interpreter, because both features are where a naive translation into a host language usually breaks down.
The README then names what is missing. Syntax-rules is absent, which means the hygienic macro system of R7RS is not available and macro expansion has to be written by hand or avoided. Exceptions are absent, so error handling has to use the continuation based mechanisms rather than raise and catch. The library system is absent, so the standard library partitioning that R7RS specifies, with a base library and separate libraries for syntax-case, lists and so on, is not there.
The second missing piece, the library system, is worth separating from the other two in practice. Syntax-rules and exceptions change how you write a program. A missing library system changes what you import and how you configure the interpreter, which for many programs is a smaller adjustment than the first two.
For anyone deciding whether to adopt this, the feature list linked from the README is the document to read, because it is more granular than the three bullet list above. The interpreter has a feature guide of its own at biwascheme.org/doc/features.html, and that page, not the README, is the contract.
Strings are immutable and integers are floats, and neither will be fixed
The README states two limitations that arise from JavaScript, and says plainly that they will not be fixed, because it is technically possible but would be very inefficient.
Strings are immutable. Scheme's string operations that mutate a string in place have no direct equivalent here, so set-string! style code has to be written differently, typically by building a new string. Code that assumes a string can be modified in place will fail rather than merely behave oddly.
Integers are not distinguished from floats. The interpreter does not maintain a separate exact integer type, so numeric results follow the host's number semantics. This affects arithmetic that depends on exact integer behaviour, and it affects the printed form of numbers, since a value that a Scheme programmer expects to see as an integer may appear as a float.
Both limitations are the kind that a careful developer can design around, and both are the kind that surprise people who port code written for another Scheme. They are also permanent, in the sense that the project has decided not to spend effort on them, so any dependency that relies on mutable strings or on exact integer semantics will not be satisfiable here.
This is where the comparison with a native Scheme implementation becomes concrete. A Scheme implemented in C can have exact integers and mutable strings, and pays for it in a runtime that must be installed and compiled. BiwaScheme removes that installation, and the price is paid in the language itself.
Rollup builds the distribution, jest and sirv drive the test loop
Building biwascheme.js needs Node.js, tested with v16.5.0, and npm, tested with v7.20.1, and the build instructions live in doc/dev/build.md. The package scripts show what actually happens. The build script runs rollup -c, and the dev script runs the same with a watch flag, and the prepare script runs the build, so installing from a checkout produces the release files.
Rollup is configured by rollup.config.js and the dev dependencies include @rollup/plugin-replace and @rollup/plugin-terser, which is how the minified biwascheme-min.js is produced from the same sources.
Tests come in several flavours, and the README is specific about each. The main path is npm install followed by npm run serve, which starts a sirv server with the --dev and --port 7001 flags, and then opening http://localhost:7001/test/spec.html in a browser. The spec page can also test the built artefacts directly, at http://localhost:7001/test/spec.html#release for release/biwascheme.js and http://localhost:7001/test/spec.html#min for release/biwascheme-min.js.
Browser specific functions are tested with a separate server started from test/browser_functions, listening on port 7002, and Node specific functions run through npm run node-test, which executes node test/node_functions.js. The jest configuration in jest.config.mjs is used by the test script, which invokes jest with the --experimental-vm-modules flag because the package is an ES module.
The Makefile adds a third activity: the website target builds index.html from the website templates with a version string substituted from package.json, and then runs the Scheme tool bin/biwas over the markdown documentation to generate the site. The documentation is processed by the interpreter it documents.
MIT licensed, last pushed 2026-10-18, with the last release from 2025
The licence is MIT, and the repository ships MIT-LICENSE.txt at the root, so the interpreter can be embedded in a commercial product without copyleft obligations. The logo is credited separately under a Creative Commons Attribution 3.0 licence, which matters if you reuse the branding rather than the code.
Maintenance needs a careful reading. The last push to the repository was on 2026-10-18 and the repository is not archived, so work continues. The release history, however, is much older: v0.8.3 on 2025-09-01, v0.8.0 on 2023-03-31, and v0.7.5 on 2022-03-24. The version in package.json is 0.8.3, so the published npm package and the newest tag agree, and the commits since that tag are development work that has not been released.
That gap is the practical upgrade cost. Anyone pinning biwascheme to 0.8.3 gets a build from September 2025 and will not receive fixes through the npm channel, and the version still below 1.0 signals an API that can change between minor releases.
The CHANGELOG.md and TODO.mkd files at the root are where the project records intent, and the maintenance history of the code shows long stretches between releases: nearly three years between 0.7.5 and 0.8.0. For an interpreter that people embed in a page or a script, that rhythm is fine, but it means version pinning deserves more attention than it would in a fast moving package.
Support runs through the GitHub issue tracker, with English and Japanese mailing lists on Google Groups.
Editorial conclusion
BiwaScheme suits a teaching project, a browser toy, or a Node script that wants an embeddable Scheme without a native toolchain, and it is a reasonable choice for a page that wants to run user supplied Scheme in the browser. It is the wrong tool for a program needing syntax-rules, exception handling or the R7RS library system, and it is the wrong tool for any code that depends on mutable strings or on integer arithmetic that stays integral. Verify three things before committing: that the missing feature list on the project's own conformance page does not block your program, that the language guide for R7RS small covers what you plan to write, and that you are comfortable with strings being immutable and integers being indistinguishable from floats, since the README states both limitations will not be fixed.
Frequently asked questions
How do I run a Scheme script with BiwaScheme on Node.js?
Install the package globally with npm install -g biwascheme, write the script to a file such as a.scm, and run it with biwas a.scm. The npm package exposes a biwas command through its bin entry.
How do I use BiwaScheme inside an HTML page?
Load biwascheme.js with a script tag, provide a div with the id bs-console as the mount point, and put Scheme source in a script tag with type="text/biwascheme". The interpreter evaluates those blocks when the page loads.
Which R7RS small features does BiwaScheme not implement?
The README lists syntax-rules, exceptions and the library system as the major lacking features. It states that most other R7RS small features are implemented, including first class continuations and tail call optimization.
What are the JavaScript related limitations of BiwaScheme?
Strings are immutable, and integers are not distinguished from floats. The README says both arise from JavaScript and that they will not be fixed.
How do I build and test BiwaScheme?
The build runs rollup -c and needs Node.js and npm, and the instructions are in doc/dev/build.md. Tests are served with npm run serve, which starts sirv on port 7001, and you open http://localhost:7001/test/spec.html, with separate paths for the built release and minified files and a node-test script for Node specific functions.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/biwascheme-biwascheme)Was this useful?