Drop #636 (2025-04-10): Three Off The Top

🦶🏼 Bare; 🦈 JAWSM; 🎗️ Always Something There

I kind of wish today was Friday, since it has been “a week”. I pulled three resources off the top of my Raindrop.io stack, and got a bit lucky two of them are somewhat-related (so we almost have a theme today).


TL;DR

(This is an LLM/GPT-generated summary of today’s Drop using Ollama + llama 3.2 and a custom prompt.)

  • Bare: A new JavaScript runtime that focuses on embedding and peer-to-peer networking, with minimal features and modular design (https://bare.pears.com/)
  • JAWSM: A project trying to run JavaScript directly in WebAssembly without needing a full JavaScript engine, using WASM garbage collection and exception handling (https://itsallaboutthebit.com/jawsm/)
  • Always Something There: A flexible command-line calendar tool called remind that lets users manage schedules through text files with complex date calculations and recurring events (https://dianne.skoll.ca/projects/remind/)

🦶🏼 Bare

Bare (GH) is new(-ish) simple JavaScript runtime for building modular apps that work across different platforms. It focuses on embedding and peer-to-peer networking. Unlike Node.js (which is best for servers), Bare runs well on desktops, mobile devices, and IoT devices. It works by separating the JavaScript engine (through libjs) from the system that handles input/output operations (libuv), so it performs consistently no matter what device it’s on.

Bare keeps things minimal. It provides only the basic tools for modules, add-ons, and threads, while extra features come as separate modules. For example, if you need file operations, you use the “bare-fs” module; if you need an HTTP server, you use “bare-http1.” This lets us choose exactly what we need without extra bulk. The module system works with both ESM and CommonJS formats, and can translate between them automatically.

A pretty cool/handy feature is how Bare handles add-ons across different JavaScript engines. By using the libjs ABI, add-ons work with multiple engines (V8, QuickJS, JavaScriptCore) without changes. This matters for devices with limited resources — we might use QuickJS on a small device to save memory, but V8 on a desktop for better performance. Mobile support comes through Bare Kit, which lets iOS/Android apps run JavaScript in separate sections that talk to each other.

According to their docs (I have not written any full apps in Bare) Bare works especially well for peer-to-peer and decentralized apps. Its suspension feature handles mobile app events smoothly — when suspended, Bare pauses execution but keeps the state until it resumes. For networking, modules like “bare-tcp” and “bare-dgram” provide basics, while projects like Hypercore offer tools for distributed data.

The build system makes it possible to compile programs/apps for many different processor types, from ARM64 (mobile) to MIPS (routers), with varying levels of support. Bare’s small size makes it good for embedding in larger apps — C interfaces let you start Bare inside existing native apps, while thread features enable parallel JavaScript with shared memory.

The ecosystem follows strict version rules for modules, so you can upgrade without fear of breaking changes. A package can use specific module versions while the main app uses newer versions elsewhere, avoiding dependency conflicts common in Node.js. Package settings can also specify different entry points for different environments, so a single package can work with both Bare and Node.js.

I’m not sure we really need a new JS runtime, but diversity in an ecosystem is generally a good thing.

This is a basic example of a small-but-practical CLI app to hash files:

$ npm install --global bare
$ mkdir file-hash
$ cd file-hash
$ npm install bare-crypto bare-fs bare-os

file-hash.mjs:

#!/usr/bin/env bare
import { createHash } from "bare-crypto";
import { readFile } from "bare-fs/promises";

async function main() {
  
  const args = Bare.argv.slice(1); // Skip script path
  let algorithm = "sha256";
  let file;

  // Parse arguments manually
  for (let i = 1; i < args.length; i++) {
    if (args[i] === "-a" || args[i] === "--algorithm") {
      algorithm = args[++i];
    } else if (!file) {
      file = args[i];
    }
  }

  if (!file) {
    console.error("Usage: file-hash [-a algorithm] <file>");
    Bare.exit(1);
  }

  try {
    const data = await readFile(file);
    const hash = createHash(algorithm).update(data).digest("hex");
    console.log(`${algorithm} hash of ${file}:\n${hash}`);
  } catch (err) {
    console.error(`Error: ${err.message}`);
    Bare.exit(2);
  }
}

main();
$ chmod 755 file-hash.mjs
$ ./file-hash.mjs package.json
sha256 hash of package.json:
6c1d37e2dfa42366638792ba076d3291f7f7b2e6f4346acbbeb58f7450e38be7

🦈 JAWSM

(I have not had cycles to play with this, but I know there are few Drop readers who 💙 WASM.)

JAWSM (GH) is a new project trying to run JavaScript directly in WebAssembly without needing a full JavaScript engine. Created by Piotr Sarnacki, it tackles the problem of running script languages efficiently in WASM, especially for distributed testing in tools like Crows (another project by Piotr).

Traditional methods require packing entire JavaScript engines into WASM, creating YUGE file sizes (i.e., over 10MB). JAWSM takes a different approach by converting JavaScript code directly into WASM instructions, using new features like WASM garbage collection, exception handling, and tail call optimizations.

The compiler recreates JavaScript behaviors using WASM’s type system. JavaScript objects become structs with fields for properties and values, while closures work through linked scope chains. When a function needs to access a variable from a parent scope, JAWSM creates WASM code that searches through these scope structures at runtime. This approach handles complex features like async/await, generators, and try/catch blocks that are usually hard to implement in low-level WASM. Right now, JAWSM supports basic language features like variable declarations, loops, operators, and creating objects and arrays. It doesn’t yet fully support built-in methods, regular expressions, or BigInts, passing about 25% of the standard JavaScript test suite. The project tackles the hardest problems first—like handling closures—before adding simpler features, to prove its core approach works early on.

JAWSM uses Rust for generating code and Node.js/V8 for running it, with polyfills to fill gaps in WASM runtime support. Future work will add more built-in functions, improve type handling, and create better tools as the project grows. If successful, JAWSM could enable lightweight JavaScript running in WASM environments, opening new uses for WebAssembly beyond traditional compiled languages.

I’m looking forward to playing with this, especially since it will reduce the footprint and system requirements for running code on “the edge”. I’m especially eager to try to get some honeypot profiles deployed using this framework.


🎗️ Always Something There

Photo by Pixabay on Pexels.com

recent post, er, reminded (heh), me about the rewind CLI. It’s is a flexible command-line calendar tool that lets us manage schedules through text files. It excels at handling complex date calculations and recurring events, making it popular with us keyboard jockeys who prefer text over graphics.

You can install remind by compiling the source, or use a package manager. Reminders live in a “.reminders” file in your home directory. Each entry starts with “REM” followed by a date and message. For example, “REM May 5 2005 MSG Go to the White House for no malicious reason whatsoever #pinkySwear” creates a one-time reminder, while leaving out the year makes it repeat annually. Features like “+7” give advance notice, and “%b” automatically updates messages to show time remaining.

You can customize recurring events with modifiers — “*30” repeats every 30 days, and “OMIT” skips holidays or weekends. For example, "REM 15 OMIT Sat Sun AFTER MSG Payday” moves payday reminders to weekdays when needed. You can organize reminders in different files (like one for birthdays, another for bills) and include them with “INCLUDE ~/path/to/file” for better organization.

For project use, remind sports some spiffy scripting features. We can create custom functions and logic for countdowns to deadlines or adjust reminders based on ephemeris, such as moon phases. The “SATISFY” keyword enables complex triggers, such as events on the fifth Monday of a month. You can display reminders on your desktop with GeekTool or use “tkremind” for a graphical interface.

remind’s output works as plain text, HTML, or PostScript for sharing or printing. For timed alerts, use the “AT” keyword with “DURATION” to schedule, and “SCHED” to fine-tune notifications. Advanced users can sync reminders across devices or create ICS files using shell scripts.

This CLI harkens back to a much simpler time, and is refreshingly simple to use.


FIN

Remember, you can follow and interact with the full text of The Daily Drop’s free posts on:

  • 🐘 Mastodon via @dailydrop.hrbrmstr.dev@dailydrop.hrbrmstr.dev
  • 🦋 Bluesky via https://bsky.app/profile/dailydrop.hrbrmstr.dev.web.brid.gy

☮️

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.