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

geniejars

v0.2.13

Published

Linux geniejars sandboxing — library and CLI for running processes as isolated system users

Readme

GenieJars

Run sandboxed processes as isolated Linux users — without ever needing runtime sudo.

Inspired by Docker, but lightweight and aimed at running AI agents (like Claude Code) in a confined environment where they can operate freely without being able to touch anything outside their own home directory.

How it works

Each geniejars is a real Linux user with its own home directory. A shell server manages agent lifecycle on demand. The manager communicates with agents over Unix sockets to build environments and run processes — no sudo required at runtime.

manager (you)
    │
    ├─ shell server ────────────────► agents (one per geniejars, started on demand)
    │
    ├─ COPY files ──────────────────► geniejars home (via group write access)
    │
    └─ socket ──────────────────────► agent (running as geniejars)
                                           │
                                           ├─ RUN (setup commands)
                                           └─ start main process

Isolation guarantees

  • Geniejars can only write inside their own home directory
  • Geniejars have no sudo access
  • Geniejars cannot connect to each other's agent sockets
  • The manager can read and write into any geniejars's home (via group membership)

Requirements

  • Linux
  • Node.js >= 18.17
  • setfacl (acl package)

Installation

npm install geniejars        # library + CLI
npx geniejars preconfig      # create geniejars.config.json from template
# edit geniejars.config.json
sudo npx geniejars setup     # one-time system setup (requires root)
su - $USER                 # new login to pick up group membership
geniejars sys up             # start the shell server

To remove everything:

sudo geniejars uninstall

Quick start

geniejars example install    # install helloworld + libcall examples

# run helloworld manually
geniejars alloc -s           # allocate and select a geniejars
geniejars build ./geniejars-example/helloworld
geniejars app up             # starts the webserver (Ctrl+C to stop)

# or run the library demo
node geniejars-example/libcall.mjs

CLI reference

System

geniejars preconfig          # create geniejars.config.json in current directory
geniejars setup              # one-time system setup (run as root)
geniejars uninstall          # remove all geniejars and system config (run as root)
geniejars sys up             # start shell server
geniejars sys down           # stop shell server and all agents
geniejars sys status         # show running agents

Pool management

geniejars alloc              # allocate a free geniejars
geniejars alloc -s           # allocate and select
geniejars alloc --tag myapp  # allocate with a tag
geniejars free               # deallocate selected geniejars
geniejars free sub002        # deallocate by name
geniejars status             # show pool status table
geniejars status --json      # full state as JSON

Selection

geniejars select sub001      # select geniejars for subsequent commands
geniejars unselect           # clear selection

Most commands use the selected geniejars when no name is given. Selection is stored in .geniejars-selected in the current directory, or via the GENIEJARS environment variable.

Building

geniejars build ./myapp          # build from folder (loads JFile inside)
geniejars build ./myapp/JFile  # build from explicit file
geniejars build sub002 ./myapp   # build into specific geniejars

Running

geniejars app up             # start CMD (waits, streams output)
geniejars app up -n          # start CMD detached (returns immediately)
geniejars app down           # stop CMD
geniejars exec ls -la        # run one-off command (direct args)
geniejars exec "ls | grep x" # run one-off shell command (single string → sh -c)

Other

geniejars normalize          # fix file permissions via ACLs
geniejars mount ./link       # symlink geniejars home to ./link
geniejars mount -C ./common  # symlink commonDir to ./common
geniejars unmount ./link     # remove symlink

JFile

The JFile format mirrors Dockerfile. Supported directives:

| Directive | Description | |---|---| | TAG name | Label this build (used for alias generation) | | ENV KEY=VALUE | Set environment variable | | WORKDIR path | Set working directory (relative to geniejars home) | | COPY src dest | Copy files from manager into geniejars environment | | RUN command | Execute setup command as the geniejars | | CMD ["cmd", "arg"] | Define the main process | | DEPEND path | Fail build if path does not exist on the manager | | ADDPATH path | Prepend path to PATH at runtime | | IMPORT KEY | Copy env var from manager environment at build time |

Port placeholders ${PORT(1)}, ${PORT(2)} etc. are substituted with the geniejars's pre-assigned ports at build time. ${COMMON} expands to commonDir.

See JFILE.md for full documentation.

Library usage

import * as geniejars from 'geniejars'

const config = await geniejars.loadConfig()

const name = await geniejars.allocate(config, { tag: 'myapp' })
const prepared = await geniejars.prepare(config, name, './JFile')
await geniejars.ensureAgent(config, name)

const [cmd, ...args] = prepared.cmd
await geniejars.startAs(config, name, cmd, args, { cwd: prepared.workdir })

await geniejars.stopProcess(config, name)
await geniejars.deallocate(config, name)

loadConfig() reads geniejars.config.json from $GENIEJARS_HOME or the current directory.

See geniejars-example/libcall.mjs (installed via geniejars example install) for a full working example.

Configuration

geniejars.config.json:

| Key | Description | |---|---| | poolPrefix | Geniejars name prefix (default sub) | | poolSize | Number of geniejars in the pool | | poolPadding | Zero-padding for geniejars numbers | | homeBase | Parent directory for geniejars homes (default /home) | | managerUser | The Linux user running the manager | | managerGroup | Group granting manager access | | portBase | First port in the allocated range | | portCount | Total ports in the pool | | portsPerGeniejars | Ports assigned per geniejars | | socketDir | Directory for Unix sockets | | stateFile | Path to pool state JSON | | lockFile | Path to state lock file | | logDir | Directory for app log files | | commonDir | Shared read-only directory accessible to all geniejars | | commonUser | Linux user owning the common directory | | backupDir | Directory for home directory backups | | agentIdleTimeout | Seconds before an idle agent self-terminates (0 to disable) | | shutdownGraceMs | Milliseconds to wait for busy agents during sys down | | nodePath | Path to node binary (defaults to current node executable) |

Project structure

src/
  agent.mjs       agent process — runs as geniejars, handles socket requests
  server.mjs      shell server — manages agent lifecycle on demand
  pool.mjs        state file, locking, config
  allocate.mjs    allocate/deallocate geniejars and ports
  prepare.mjs     JFile parser and executor
  run.mjs         socket client (talks to agents and shell server)
  normalize.mjs   fix file permissions via ACLs
  index.mjs       public API

script/
  geniejars.mjs            unified CLI entry point
  setup-geniejars.mjs     one-time system setup (run as root)
  uninstall-geniejars.mjs remove all geniejars and system config (run as root)

Common Issues

See COMMON-ISSUES.md for solving common issues.

Links and contact

Github Contact me on my Twitter/X account

License

MIT — see LICENSE.md