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

hop2

v0.11.42

Published

🐰 Hop into your terminal from anywhere. Secure remote shell access with 2FA via Cloudflare Tunnel. Next-gen rewrite with native terminal sharing.

Readme

🐰 hop

Terminal access for humans and agents.

Hop gives you secure browser access to local terminals and a built-in MCP server for creating, driving, and auditing agent sessions over the same runtime.

macOS/Linux β€” Requires cloudflared for tunneling

           (\(\ 
           ( -.-)    "hop into your shell"
           o_(")(")

Why Hop

  • Browser terminal from anywhere β€” Tunnel through Cloudflare with no port forwarding
  • MCP-native terminal control β€” Claude Code, Codex, Gemini, Cursor, and other MCP clients can create terminals, stream output, and send input through Hop
  • One runtime for humans and agents β€” The browser UI, local CLI, and MCP server operate on the same sessions
  • Operationally useful primitives β€” Named sessions, port sessions, auto-attach, and explicit workspace snapshots
  • Auditability built in β€” Per-session logs, isolated agent history, and TUI-aware capture defaults
  • Security when you need it β€” Password + 2FA, custom domains, and multi-user support

πŸš€ Quick Install

Most users only need the npm install. Source install is mainly for development or local hacking.

From npm (easiest)

npm install -g hop2

That installs the nightly β€” a build from the latest green main, which is usually what you want here since almost every commit is a fix. To hold still on a version that was deliberately cut and used:

npm install -g hop2@stable

This installs:

  • hop β€” main CLI / daemon / browser terminal entrypoint
  • hop-mcp β€” MCP server exposing Hop terminals and sessions
  • hop-mcp-setup β€” MCP client auto-config helper

Then:

hop

If you want agent access too:

hop-mcp-setup

From source (one-liner)

git clone https://github.com/jzthree/hop.git ~/.hop && \
cd ~/.hop && npm install && \
sudo ln -sf ~/.hop/hop /usr/local/bin/hop

From source (manual)

# Clone the repo
git clone https://github.com/jzthree/hop.git ~/.hop

# Install dependencies
cd ~/.hop && npm install

# Add to PATH (pick one)
# Option A: Symlink (requires sudo)
sudo ln -sf ~/.hop/hop /usr/local/bin/hop

# Option B: Add to PATH
echo 'export PATH="$HOME/.hop:$PATH"' >> ~/.zshrc
source ~/.zshrc

Quick Start

Browser access

hop

hop is safe to put at the end of your shell rc (~/.zshrc): it only launches for interactive terminals β€” non-interactive shells (ssh host <cmd>, scp/rsync, scripts, cron) and shells already inside a hop session are silently unaffected.

First run:

  1. Optionally set a password with hop password set
  2. Scan the authenticator QR code
  3. Note the URL
  4. Press Enter to start your first local terminal

Then open the URL from another device, sign in, and pick or create a session.

MCP access

hop
hop-mcp-setup
hop agent-skill install

Then restart your MCP client. hop-mcp-setup auto-detects and configures supported clients such as Claude Code, Claude Desktop, Cursor, Gemini CLI, Codex CLI, VS Code / Copilot, and Antigravity. hop agent-skill install installs Hop's bundled orchestration instructions for Claude Code and Codex.

Typical use cases:

  • Launch a dedicated Claude Code / Codex / Gemini terminal and drive it over multiple turns
  • Create isolated agent sessions with per-session history and audit logs
  • Read terminal output incrementally instead of screen-scraping a browser
  • Build higher-level agent workflows on top of stable terminal/session primitives

For full MCP usage, tools, and subagent workflows, see README-MCP.md.

Everyday Workflows

Create and Reuse Sessions

Create multiple independent terminal sessions from the Session Picker (/sessions):

  • Create a new named shell session
  • Join any existing session
  • Share a live session between multiple devices
  • Save selected live terminal sessions into a named workspace when you want to reuse them later

Scratch sessions stay live-only unless you explicitly save them into a workspace. To save reusable definitions from the CLI:

hop session add workspace-shell --cwd ~/src/my-project --workspace dev
hop session add myapp --port 3000 --workspace dev

Use hop workspace save <name> to snapshot selected live terminal sessions, or hop session add ... --workspace <name> when you want to define a reusable terminal or port entry directly.

Inspect or remove saved workspace definitions with:

hop workspace show dev
hop workspace delete dev

Drive a Subagent Over MCP

Use one dedicated terminal per subagent.

  1. Create a terminal with hop_create_terminal and set name / cwd.
  2. Start the agent CLI with hop_write_terminal.
  3. Wait for readiness with hop_wait_terminal(until_prompt=true).
  4. Prefer hopx_agent_turn(mode="auto") or hopx_send_and_wait(...) for one turn at a time.
  5. For long waits, use hopx_agent_turn(async=true, ...) or the lower-level hop_wait_terminal(async=true, ...) + hop_wait_poll(...) (hop_wait_start was removed; use hop_wait_terminal(async=true)).
  6. Interrupt with hop_send_key(key="ctrl_c") and close with hop_close_terminal.

Safety tips:

  • Keep one subagent per terminal.
  • Do not queue a second instruction before reading the first response.
  • For attached user sessions, confirm agentPermitted before sending input (grant it with hop session permit <name>).

Share a Local Web App

Expose a local HTTP or WebSocket service through your Hop tunnel:

hop session add myapp --port 3000 --workspace dev

Result:

  • local service stays on localhost
  • Hop exposes it at https://your-tunnel-url/s/myapp/
  • WebSocket apps work too

Reattach Locally

Attach your local terminal client to an existing terminal session:

hop attach <session>

This is useful when you want a browser, an MCP client, and a local shell to converge on the same named session. Local terminal sessions are persistent by default: they keep running in the Hay host if the local CLI detaches or the Hop daemon restarts. Press Ctrl+Q twice inside the local Hop view to kill a session for everyone; Ctrl+G detaches and leaves it running.

The attached-terminal UI adapts light/dark themes to your terminal and puts the session state at a glance:

Use Hop on Mobile

Native iOS app: hop-ios β€” a SwiftUI client for iPhone with a real terminal (SwiftTerm), optimistic-echo typing, bell notifications with lock-screen reply, Siri/Shortcuts/Spotlight/Handoff integration, and a fixed-height terminal keyboard. It consumes hop's public HTTP + WebSocket API and needs no changes to hop.

Hop’s mobile web UI includes:

  • a terminal-oriented accessory row with Esc, Tab, Ctrl, Alt, and arrows
  • a native keyboard button for dictation, spellcheck, and autocomplete
  • a floating menu for keyboard toggle and session switching; the switcher starts with user sessions and can toggle to agent sessions or all sessions
  • draggable controls designed for one-handed use

Restore Sessions (incl. Claude Code)

A restart kills the underlying processes, but hop can rebuild your sessions and β€” for Claude Code β€” resume each conversation where it left off.

hop claude-hook install   # one-time: lets hop track each session's Claude conversation
hop restore               # recreate saved sessions; claude ones resume their own conversation
hop restore --dry-run     # preview what would be restored

How it works: every hop terminal gets a HOP_SESSION env var; a Claude Code SessionStart hop hook records which conversation is running in each session. On hop restore, each session is reopened in its original directory and claude sessions relaunch with claude --resume <id> β€” so even multiple Claude sessions in the same directory each come back to their own conversation. Plain-shell sessions reopen a shell in their last directory and replay their last screen: on a graceful shutdown hop saves each session's recent output and, on restore, paints it back above a dim ──── session restored ──── separator before the fresh prompt β€” so you keep the context even though the old process is gone. hop status shows how many sessions can be restored.

hop claude-hook install adds a SessionStart entry to ~/.claude/settings.json (backed up first); hop claude-hook remove reverts it. The hook is a no-op outside hop terminals.

Render LaTeX math (hop math)

Glance at a formula without leaving the terminal:

hop math 'e^{i\pi} + 1 = 0'
hop math '\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}'
echo '\sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6}' | hop math

Agents working inside hop terminals can render formulas for the humans watching by invoking the command themselves β€” install the bundled skills with hop agent-skill install so Claude and Codex sessions know to do this (plus ring the bell when blocked, and keep output phone-friendly).

hop math renders a 2D Unicode layout β€” fractions, roots, sums/limits, sub/superscripts, Greek + operators, and accents β€” with no dependencies. Inline-image rendering (Kitty/iTerm) is deferred until graphics support lands in the web client (xterm.js): the real payoff is math that renders inside a shared hop session, which the re-rendering clients can't show yet, so until then it's Unicode everywhere.

Show something a terminal cannot draw (hop view, hop port)

A terminal can only print text, which makes it the wrong surface for the thing you most often want back from a long-running job: a plot, a report, a rendered write-up. hop view publishes a file behind hop's auth and prints a link β€” the web client and the phone app both open it in place, with the session's cookie, so nothing has to be public.

hop view --title "ROC curve: new model vs baseline" results/roc_curve.png
hop view --title "Q3 analysis" report.html analysis.pdf
generate_summary | hop view --name findings.md --title "What the profiler found" -
hop view --list          # what this session published
hop view --rm x.png      # unpublish

HTML, PDF, images, video and markdown all render (markdown is converted at serve time β€” headings, tables, fenced code). --title is what a human sees in the session's Views list, so it is worth writing properly. Published files are grouped by session: a result belongs to the conversation that produced it.

For something live rather than a file, hop port 5173 proxies a local web server through the same auth (WebSocket-safe, so dev-server hot reload works), attached to the current session β€” --standalone makes it a room of its own instead.

Agents do this for you when the bundled skill is installed (hop agent-skill install): the convention is to hand over a titled view rather than describe a result in prose.

Operations

Logging and History

Hop always writes per-session audit logs.

Default behavior:

  • agent-created sessions get isolated shell history files
  • user-created sessions keep normal shell history unless you opt into isolation
  • TUI apps switch to diff-suppressed keyframe capture automatically

Paths:

  • scratch sessions: ~/.hop2/runtime/history/<internal-session>.history
  • scratch audit logs: ~/.hop2/runtime/logs/<internal-session>/audit.ndjson
  • workspace-backed sessions: ~/.hop2/workspaces/<workspace>/history/<internal-session>.history
  • workspace-backed audit logs: ~/.hop2/workspaces/<workspace>/logs/<internal-session>/audit.ndjson

Key tunables:

  • HOP_SESSION_HISTORY_SIZE
  • HOP_AGENT_HISTORY_ISOLATION
  • HOP_USER_HISTORY_ISOLATION
  • HOP_AGENT_POST_START_HISTORY_INIT
  • HOP_POST_START_HISTORY_INIT
  • HOP_SESSION_AUDIT_INLINE_MAX_BYTES
  • HOP_SESSION_TUI_KEYFRAME_INTERVAL_MS
  • HOP_SESSION_TUI_KEYFRAME_TAIL_CHARS
  • HOP_SESSION_TUI_KEYFRAME_MAX_LINES

Users, Domains, and Sharing

Admin flow:

  1. Set a password with hop password set.
  2. Configure a hostname with hop domain hop.yourdomain.com.
  3. Add a user with hop user add alice.
  4. Export credentials with hop user export alice.

User flow:

npm install -g hop2
hop client ./credentials.json

First run prompts for password setup and TOTP enrollment, then the user logs in at their assigned URL such as https://alice.hop.yourdomain.com.

Self-service signup (optional)

Instead of adding every user by hand, the landing host can serve a public signup page. Visitors ask for a subdomain, confirm an email address on a domain you nominate, and wait for you to approve β€” approval runs the same hop user add + hop user export provisioning as the manual flow, then emails them a one-time link to collect their credentials.

hop mail setup                      # SMTP (a Gmail App Password works)
hop registration admin jianzhou     # reserve your own subdomain
hop registration domain uchicago.edu
hop registration enable

Then review requests as they arrive:

hop user pending
hop user approve alice
hop user reject bob "please use your own name"

Notes:

  • Off by default. Enabling it makes the bare hostname public; your own browser keeps working while its session cookie is valid, and https://<landing-host>/signin always reaches the login page.
  • Nothing runs on your machine for them. A registrant gets a Cloudflare tunnel and a DNS record; hop itself runs on their computer, with their own password and TOTP.
  • The tunnel lives in your Cloudflare account and the subdomain is under your domain, so an approved user can serve anything they like at their-name.your-domain. Approve people you would vouch for, and use hop user remove <name> to revoke (delete the DNS record by hand).
  • Registrations live in ~/.hop2/.registrations.json (0600). Verification and claim links are stored only as hashes.

Security

  • Password + TOTP is supported; password is required for custom domains
  • Login cookies are httpOnly, secure, and sameSite=lax
  • Browser sessions persist across hop stop/start by default through a stable session secret
  • The local server binds only to 127.0.0.1
  • Cloudflare Tunnel provides end-to-end TLS

Secrets are stored in ~/.hop2/. Set HOP_PERSIST_SESSION_SECRET=0 if you want login cookies invalidated on every daemon restart.

Runtime and Recovery

Hop uses the external Hay host runtime for PTY hosting and session recovery.

  • active PTYs live in a separate local hay-host process
  • the host survives daemon restarts
  • host state is tracked in ~/.hop2/.hay-host-state
  • startup reconciles already-running Hay sessions before applying workspace state
  • HOP_TERMINAL_BACKEND is accepted only for compatibility and ignored

Reference

Related Docs

Commands

| Command | Description | |---------|-------------| | hop | Start hop daemon/tunnel if needed, then launch a local terminal. Unnamed launches do not reuse a session that already has a local CLI attached. | | hop start | Start the hop daemon and print QR codes | | hop attach [session] | Attach to an existing terminal session | | hop attach all | Attach sequentially to all terminal sessions | | hop local [session] | Start a daemonless local terminal ([session] attaches if it exists) | | hop stop | Stop the hop daemon (terminal sessions keep running) | | hop stop --all | Stop the daemon, the hay-host, and all terminal sessions | | hop status | Show daemon, tunnel, and session status | | hop doctor | Run environment/health checks | | hop logs [-f] | Show daemon logs (-f to follow) | | hop health [--restart] | Check tunnel health (--restart forces a tunnel restart) | | hop url | Print current tunnel URL | | hop qr | Show QR code for current tunnel URL | | hop qr auth | Show QR code for authenticator app setup | | hop config theme [name] | Show or set the session naming theme | | hop domain <hostname> | Set custom domain (named tunnel) | | hop domain-clear | Remove custom domain, use random URLs | | hop password set | Set/change password | | hop password clear | Remove password protection | | hop user list | List users | | hop user add <name> | Add user + subdomain | | hop user remove <name> | Remove user | | hop user export <name> | Export user credentials | | hop session list | List live terminal sessions | | hop session list --all | Include saved definitions from all workspaces alongside live sessions (-a is shorthand) | | hop session add <name> [--cwd P] --workspace W | Save a terminal session definition to a named workspace | | hop session add <name> --port N --workspace W | Save a port session definition to a named workspace | | hop session permit <name> | Allow agent access to a session | | hop session block <name> | Block agent access to a session | | hop workspace list | List workspaces | | hop workspace create <name> | Create an empty workspace | | hop workspace show <name> | Show saved definitions in a workspace | | hop workspace save <name> | Save selected live terminal sessions into a workspace | | hop workspace load <name> | Start sessions defined in a workspace | | hop workspace delete <name> [--yes] | Delete a workspace (asks before deleting a non-empty one) | | hop session rename <old> <new> | Rename a session | | hop session remove <name> | Remove a session | | hop client <credentials> | Run hop with exported credentials | | hop wipe [--all] [--yes] | Remove workspace-defined sessions (--all also kills live sessions after a confirmation; --yes skips it) | | hop wipe --agent | Close all agent-created terminal API sessions |

Local CLI mouse capture is off by default so terminal-native selection and context menus keep working. Use Option+M / Alt+M inside the local Hop view to toggle Hop mouse selection when needed. Use Option+B / Alt+B to toggle the status bar. CLI defaults live under hay-cli in ~/.hop.json.

Development

The Hay source is vendored in ./hay. Hop serves hay/apps/web/dist when present.

npm run build
npm test

This rebuilds Hay and syncs hay/apps/web/dist into hay-web/. npm test runs a basic syntax sanity check on the main hop entrypoint. If ./hay exists and the dist folder is missing, hop auto-builds Hay on startup.

Troubleshooting

  • Authenticator QR again: run hop qr auth
  • Reset TOTP entirely: delete .auth_secret and restart Hop
  • Reset a client install: delete ~/.hop2/clients/<tunnel-id>/ and run hop client again
  • Tunnel not starting: install cloudflared with brew install cloudflared
  • Tunnel returning 502 after a network change: run hop health --restart
  • Stuck tunnel processes:
pkill cloudflared

License

MIT