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

remobi

v1.0.3

Published

Monitor and control your coding agents from your phone. Touch controls for tmux over the web.

Downloads

179

Readme

remobi

CI npm licence

Your terminal. Everywhere.

Your tmux session, on your phone. Same panes, same windows, same bindings — nothing changes on your computer. Swipe between windows, pinch to zoom, tap to send commands. You just get a remote control.

It's a terminal on a 6-inch screen. It won't win design awards. But you can do everything — monitor coding agents, intervene when they're stuck, scroll through output, switch contexts. Full power.

/bin/bash -c "$(curl -fsSL http://remobi.app/install.sh)"

To upgrade stable: npm install -g remobi@latest

To try the experimental channel: npm install -g remobi@dev

Your coding agent handles the rest. It installs remobi, inspects your tmux config, generates a config, and suggests tweaks to make your tmux more mobile-friendly — one conversation. Works with Claude Code and Codex.

Why remobi

  • Zero workflow changes — your existing tmux setup, untouched
  • Swipe between windows — gesture navigation, no prefix key fumbling on a phone screen
  • Pinch to zoom — resize text like every other app on your phone
  • Install to your home screen — standalone PWA, looks and feels native
  • Config-driven — your buttons, your gestures, your layout
  • Self-hosted — local-first by default. Bring your own access layer (Tailscale, Cloudflare, ngrok)

Requirements

Manual setup

# 1. Install
npm install -g remobi

# 2. Enable mouse mode in tmux (required for touch scroll and tap-to-focus)
#    Add to ~/.config/tmux/tmux.conf or ~/.tmux.conf:
#    set -g mouse on

# 3. Start (spawns your command, serves remobi on 127.0.0.1:7681)
remobi serve

Essential tmux settings for mobile — add to your tmux.conf if not already present:

| Setting | Command | Why | |---------|---------|-----| | Mouse mode | set -g mouse on | Enables touch scroll, tap-to-focus, drag resize. The single highest-value setting for mobile use. | | Status position | set -g status-position top | Keeps status bar away from remobi's touch toolbar at the bottom | | Renumber windows | set -g renumber-windows on | Keeps window list tidy after closing windows |

See Mobile-friendly tmux config for responsive status bars, popup sizing, and more.

For local development, see the Development section below.

Open http://localhost:7681 on the same machine to verify it works. For phone access, put a trusted proxy/tunnel in front of it, for example Tailscale Serve. If your proxy mounts remobi under a URL prefix, start remobi with --base-path /that-prefix so the HTML, PWA links, and WebSocket all use the same external path.

Release channels

  • main publishes stable releases to npm latest
  • dev publishes prereleases to npm dev
  • merge dev into main to promote an experimental line to stable

If an experimental change is breaking for consumers, include a BREAKING CHANGE: footer so semantic-release computes the right next version on both channels. ! in the header is optional shorthand only; on its own it does not trigger a major release in this repo.

Set up with AI

The setup skill checks your environment, inspects your tmux config, generates a remobi.config.ts, and suggests tmux mobile optimisations — one conversation. Three ways to use it, from simplest to most manual:

Option 1: One-liner — installs the skill and launches an interactive session with your coding agent:

/bin/bash -c "$(curl -fsSL http://remobi.app/install.sh)"

Option 2: Install the skill — if you prefer to start the conversation yourself:

npx skills add connorads/remobi

Then tell your coding agent: "Use the remobi-setup skill to onboard me."

Option 3: Already in a session? — if an agent is already looking at this repo (or you don't want to install a skill), tell it:

Read .agents/skills/remobi-setup/SKILL.md in this repo and follow it to onboard me.

The skill file contains the full setup workflow. The agent can read it directly — no installation needed.

Security model

remobi is a remote-control surface for your terminal. Anyone who can reach it can drive the tmux session with your user privileges.

  • remobi serve binds to 127.0.0.1 by default.
  • The inner PTY-backed terminal session stays local to the remobi process.
  • There is no built-in login, password, or ACL in remobi itself.
  • Safe default: keep it on localhost and publish it through a trusted layer like Tailscale Serve.
  • If you use remobi serve --host 0.0.0.0, you are exposing terminal control to your LAN/whatever can route to that port. Do that only if you intentionally want direct network exposure and have separate network controls in place.

To report a vulnerability, see SECURITY.md.

CLI reference

remobi serve [--config <path>] [--port <n>] [--host <addr>] [--base-path <path>] [-- <command...>]
  Start remobi with its built-in web terminal and PWA support.
  Default host: 127.0.0.1. Default port: 7681. Default command: tmux new-session -A -s main
  Example: remobi serve --host 0.0.0.0 --port 8080
  Example: remobi serve --base-path /random-token
  Example: remobi serve --port 8080 -- tmux new -As dev

remobi build [--config <path>] [--output <path>] [--dry-run]
  Deprecated. remobi no longer patches ttyd HTML.

remobi inject [--config <path>] [--dry-run]
  Deprecated. remobi no longer patches ttyd HTML.

remobi init
  Scaffold a remobi.config.ts with commented defaults.

remobi --version
remobi --help

Short flags: -c (--config), -p (--port). Legacy deprecated flags: -o (--output), -n (--dry-run).

Config resolution

When --config is not specified, remobi searches:

  1. remobi.config.ts / .js in the current directory
  2. ~/.config/remobi/remobi.config.ts / .js (XDG fallback)

Configuration

Create remobi.config.ts (or run remobi init):

export default {
  font: {
    family: 'JetBrainsMono NFM, monospace',
    mobileSizeDefault: 16,
    sizeRange: [8, 32],
  },
  toolbar: {
    row1: [
      { id: 'esc', label: 'Esc', description: 'Send Escape key', action: { type: 'send', data: '\x1b' } },
      { id: 'tmux-prefix', label: 'Prefix', description: 'Send tmux prefix key (Ctrl-B)', action: { type: 'send', data: '\x02' } },
      // ...
    ],
    row2: [
      { id: 'alt-enter', label: 'M-↵', description: 'Send Alt+Enter (ESC + Enter)', action: { type: 'send', data: '\x1b\r' } },
      { id: 'drawer-toggle', label: '☰ More', description: 'Open command drawer', action: { type: 'drawer-toggle' } },
      { id: 'paste', label: 'Paste', description: 'Paste from clipboard', action: { type: 'paste' } },
      { id: 'backspace', label: '⌫', description: 'Send Backspace key', action: { type: 'send', data: '\x7f' } },
      // ...
    ],
  },
  drawer: {
    buttons: [
      { id: 'tmux-new-window', label: '+ Win', description: 'Create tmux window', action: { type: 'send', data: '\x02c' } },
      { id: 'tmux-split-vertical', label: 'Split |', description: 'Split pane vertically', action: { type: 'send', data: '\x02%' } },
      { id: 'combo-picker', label: 'Combo', description: 'Open combo sender (Ctrl/Alt + key)', action: { type: 'combo-picker' } },
      // ...
    ],
  },
  gestures: {
    swipe: {
      enabled: true,
      left: '\x02n',         // data sent on swipe left (default: next tmux window)
      right: '\x02p',        // data sent on swipe right (default: prev tmux window)
      leftLabel: 'Next tmux window',    // shown in help overlay
      rightLabel: 'Previous tmux window',
    },
    scroll: {
      enabled: true,
      strategy: 'wheel',
      sensitivity: 40,
      wheelIntervalMs: 24,
    },
    pinch: { enabled: true },
  },
  mobile: {
    initData: '\x02z',     // send on mobile load when viewport < widthThreshold
    widthThreshold: 768,   // px — default matches common phone/tablet breakpoint
  },
  floatingButtons: [
    {
      position: 'top-left',
      buttons: [
        { id: 'zoom', label: 'Zoom', description: 'Toggle pane zoom', action: { type: 'send', data: '\x02z' } },
      ],
    },
  ],
}

All fields are optional — the CLI fills in defaults internally when it loads the config.

Shipped tmux drawer defaults stick to stock tmux bindings (c, %, ", s, w, [, ?, x, z) rather than personal popup workflows.

Replace the drawer entirely with a plain array when you want a fully custom setup:

import { defineConfig } from 'remobi/config'

export default defineConfig({
  drawer: {
    buttons: [
      { id: 'sessions', label: 'Sessions', description: 'Choose tmux session', action: { type: 'send', data: '\x02s' } },
      { id: 'git', label: 'Git', description: 'Open my tmux git popup', action: { type: 'send', data: '\x02g' } },
    ],
  },
})

At runtime, remobi validates the config object shape and rejects unknown keys with clear path-based errors.

gestures.scroll.strategy controls touch scroll behaviour:

  • wheel (default): sends SGR mouse wheel events with touch-mapped terminal coordinates.
  • keys: sends PageUp / PageDown for app-level paging when preferred.

Programmatic API

import { defineConfig, serialiseThemeForTtyd } from 'remobi/config'
import type { RemobiConfig, ControlButton } from 'remobi/types'
import { init } from 'remobi'

Advanced consumers can use hook registry primitives to observe lifecycle and terminal-send events:

import { createHookRegistry, init } from 'remobi'

const hooks = createHookRegistry()
hooks.on('beforeSendData', (ctx) => {
  if (ctx.data.includes('rm -rf /')) return { block: true }
})

init(undefined, hooks)

Guides

Architecture docs

Architecture

Pure TypeScript + DOM API — no framework. The build bundles the browser client via esbuild, serves it from Node, and bridges browser input/output to a local PTY via node-pty. xterm.js handles terminal rendering in the browser; remobi layers the mobile controls on top. The docs above walk through the current runtime in more detail, including diagrams for the server, browser, and WebSocket flow.

Key modules:

| Module | Purpose | |--------|---------| | src/toolbar/ | Two-row touch toolbar | | src/drawer/ | Command drawer with grid layout | | src/gestures/ | Swipe, pinch, scroll detection | | src/controls/ | Font size, help overlay, scroll buttons | | src/theme/ | Catppuccin Mocha + theme application | | src/viewport/ | Height management, landscape detection | | src/util/ | DOM helpers, terminal, keyboard, haptics |

Public API and semver

remobi follows semantic versioning. The public API is defined by the following import paths:

| Import path | Contents | Stability | |---|---|---| | remobi | init, defineConfig, createHookRegistry, RemobiConfig, ControlButton, ButtonAction, ButtonArrayPatch, ButtonArrayInput, RemobiConfigOverrides, HookRegistry | Public — breaking changes are semver-major | | remobi/config | defineConfig, mergeConfig, defaultConfig, serialiseThemeForTtyd | Public | | remobi/types | All types in src/types.ts | Public |

Internal modules (not part of the public API — may change without a major version bump): src/toolbar/, src/drawer/, src/gestures/, src/controls/, src/theme/, src/viewport/, src/util/, src/serve.ts, src/cli/, build.ts

Semver policy:

  • Major: removing or renaming a public export, changing a public function signature incompatibly, removing a config field
  • Minor: adding new public exports, new optional config fields, new ButtonArrayInput operations
  • Patch: bug fixes, internal refactors, documentation updates

Development

git clone https://github.com/connorads/remobi.git && cd remobi
pnpm install
git config core.hooksPath .hk-hooks   # enable commit hooks (conventional commits, biome)

Running locally

From source (bundles the browser client on the fly via esbuild — no build step needed):

tsx cli.ts serve              # localhost:7681, default tmux session

Or build first, then run from dist/:

pnpm run build:dist          # transpile TS → JS + bundle browser client
node dist/cli.mjs serve      # run locally-built version on localhost:7681

No watch mode — re-run the build or use tsx for automatic source bundling.

Checks

pnpm test            # vitest (unit + integration)
pnpm run test:pw     # playwright e2e (needs: pnpm exec playwright install chromium webkit --with-deps)
pnpm run check       # biome lint + format

FAQ

Is this secure? remobi doesn't handle auth — it's a UI overlay. Use a tunnel or VPN you trust. We recommend Tailscale (deployment guide included) — your session never leaves your tailnet. Cloudflare Tunnel and ngrok also work. Security is your responsibility.

Why not Termux / Termius / SSH apps? They work. But you're managing SSH keys, losing your tmux setup, and fighting a UI that wasn't built for touch. remobi keeps your exact workflow — same panes, same windows, same bindings — and adds touch controls on top.

Why not Happy / Claude resume / chat-based mobile apps? Those tools change your workflow. Chat relays route through third-party servers. Claude's resume has limitations. remobi gives you the raw terminal — full power, self-hosted, works with every agent because it works with tmux.

Why Node? remobi migrated from Bun to Node.js + pnpm for broader compatibility. It transpiles to JS via tsdown for npm distribution and uses esbuild for the browser client bundle.

Is this production-ready? It's v0.1. The author uses it daily. It works. It's also early — feedback welcome, forks encouraged.

Acknowledgements

remobi owns the full web terminal path now: a local PTY on the server, xterm.js in the browser, and the mobile touch controls on top.

Earlier versions were built on top of ttyd. It helped remobi launch quickly, prove the workflow, and shape the product before the runtime moved in-house.

Licence

MIT