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

tori.host

v0.9.7

Published

Deploy AI-generated apps to tori.host: npx tori.host

Readme

tori.host

Deploy static sites and container services to tori.host. Nothing to install:

npx tori.host

Guides, the quickstart and the generated CLI and API reference are at docs.tori.host. The command list below is the same reference, rendered for npm.

Signing in

There is nothing to set up first. Run the deploy; if this machine has never signed in, a browser opens, you sign in (or sign up — they are the same click, auth here is a magic link), and the deploy carries on:

npx tori.host

What gets saved to ~/.config/tori/config.json is an API token the sign-in mints, named after this machine — CLI · macbook-vaclav. It shows up in the Console under Settings → API tokens, and revoking it there stops this machine deploying, immediately and by itself.

On a machine with no browser

Over SSH, in a container, or anywhere with no DISPLAY, the CLI does not try to open anything. It prints a short code and a URL instead; open the URL on any device you are signed in on, type the code, and the terminal carries on:

$ npx tori.host
→ no browser here (this is an SSH session) — sign in from any other device
  Open: https://my.tori.host/cli-auth
  Code: PQXR-4K7M
⠧ waiting for approval…

--no-browser picks that flow deliberately on a machine that does have a browser. BROWSER=none does the same through the environment.

In CI

There is nobody there to approve anything, so tori deploy does not try: set TORI_TOKEN to a token minted in the Console (Settings → API tokens), and TORI_API_URL if you are not pointing at the default.

Commands

This command list is generated from the same metadata as tori --help and the documentation site. It matches [email protected].

| Command | What it does | | --- | --- | | tori / tori deploy [dir] | Pack a directory, build a service from source, or run a digest-pinned image, and wait until it is live. | | tori deploy --service [dir] | Upload the source tree and have Tori build and run it. A Dockerfile is used if there is one; otherwise the language is detected. | | tori deploy --image <ref> | Deploy a container image the registry already has. <ref> must be digest-pinned. Nothing is built or uploaded. | | tori deploy --image <ref> --restart | Force a new revision when that image and env are already live. | | tori deploy --image <ref> --release "<cmd>" | Run a Job with that command before the new revision takes traffic. | | tori deploy status [id] | Inspect the latest or named deployment | | tori deploy watch <id> | Resume watching a deployment | | tori deploy cancel <id> | Cancel a pending service deployment; keep the live version | | tori deploy build-log [id] | Print the build log of a source deployment | | tori logs [--follow] | Read retained app stdout and stderr | | tori env list / set KEY=VALUE / unset KEY | The environment this app's containers are started with | | tori db create / status / dumps / restore / delete | Manage this service app's Postgres database | | tori domains list / add <hostname> / remove <hostname> / check <hostname> | Connect your own hostname to an app | | tori mcp | Serve Tori tools over MCP stdio | | tori login | Sign in through the browser and save the token | | tori whoami | Show the logged-in account and plan | | tori --version / --help | Print the package version or this command list. tori deploy --help and tori login --help are more specific. |

Example:

$ npx tori.host
→ opening your browser to sign in…
✓ signed in as [email protected]
  Saved as "CLI · macbook-vaclav" — revoke it any time in the console.
→ created app plucky-wren
⠹ uploading 8.4 MB / 30.0 MB  28%  1.1 MB/s  ETA 19s
→ uploaded 30.0 MB in 27s (1.1 MB/s)
✓ live: https://plucky-wren.tori.cloud

Services: building from source

An app is either a static site — files packed out of a directory — or a service, a container the zone runs for you. Which one it is is decided when the app is created and cannot be changed afterwards.

A service is built on Tori from the directory you run the CLI in. With a Dockerfile at the root there is nothing to say: run npx tori.host and the CLI sees the Dockerfile, creates a service, and uploads the tree. Without one, say what you mean with --service, and the build detects the language (Node, Python, Go, PHP, Ruby, Java, Rust, Deno, .NET, Elixir and a few more). Later deploys from the same directory read tori.json and need neither.

$ npx tori.host deploy --service
→ packing . (Dockerfile)
→ packed 23 files, 41.2 kB
→ uploaded 41.2 kB in 0s (312.0 kB/s)
→ queued for build — position 2 in the build queue
→ building — attempt 1
→ built registry.tori.zone/tenant-a_6d9009a4ef/app@sha256:9f2c…
✓ live: https://plucky-wren.tori.cloud

What travels is the directory as it is, minus .git, node_modules and whatever .gitignore matches — every one git itself reads, from the repository root down, so build output, a .env, a target/ stay home exactly as they stay out of the repository. Symlinks and file modes are kept; the build runs the tree you tested. .dockerignore is applied by the build itself, next to the Dockerfile, not by the upload. The plan caps the compressed upload and how long a build may run.

The container that results has to meet the same requirements as one you bring yourself: listen on port 8080 and run as a numeric non-root user. A Railpack-detected build is arranged that way for you; a Dockerfile has to say USER 1000 itself.

A build that fails does not touch what is live. The failure message carries the cause and the last lines of the build log; the whole log is one command away:

$ npx tori.host
…
✗ deploy failed: Dockerfile build failed: exit status 1
  …
  ERROR: process "/bin/sh -c npm ci" did not complete successfully: exit code: 1
  Full build log: tori deploy build-log d_7f3a…
$ npx tori.host deploy build-log d_7f3a… | less

tori deploy cancel <id> stops a build that is queued or running; the build VM is destroyed and the previous version keeps serving.

Services: deploying an image

A service can also run an image you built elsewhere:

$ npx tori.host deploy --image registry.example.com/acme/api@sha256:e3b0c442…
→ deploying registry.example.com/acme/api@sha256:e3b0c442…
⠹ starting… (6s)
✓ live: https://plucky-wren.tori.cloud

Pass -v or --verbose to also print the created app, deploy ID and recovery command, server progress diagnostics, and phase timing breakdown.

The container must listen on port 8080 and declare a numeric non-root USER, for example USER 1000. The upstream knative/helloworld-go image runs as root and is incompatible. A verified request-echo example is:

TEST_IMAGE='ghcr.io/mendhak/http-https-echo@sha256:1721d9487ee774fd1d37de3014afd9c215df5056c125af941ee17512178129f6'
npx tori.host deploy --image "$TEST_IMAGE"

Keep tori.json to retry the same app. This sample returns request data as JSON; it does not implement the Hello World sample's TARGET variable.

Nothing is built, packed or uploaded on this path: the image is already in a registry, and all that travels is its name. A service app takes either kind of deploy, one at a time: a directory with tori.json naming a service is built from source whenever --image is absent.

The reference must be pinned to a digestregistry/repo@sha256:<64 hex>. A tag is refused locally, before any request:

$ npx tori.host deploy --image nginx:latest
✗ --image must name an image by digest, and nginx:latest names one by tag
  A tag can be moved onto different bytes tomorrow, so it cannot identify a
  deploy — nothing was sent to the API. Resolve it once:
  docker inspect --format "{{index .RepoDigests 0}}" nginx:latest

live here means the revision the zone started is Ready and serving.

Inspecting and stopping an attempt

The CLI prints the deploy ID and the latest observed reason while waiting. Ctrl+C stops watching; the deploy continues on the server. Resume it or explicitly cancel it:

npx tori.host deploy status
npx tori.host deploy watch d_example
npx tori.host deploy cancel d_example

Cancellation applies only to pending service attempts. It prevents that attempt from going live and allows another deploy; resource cleanup follows in the zone. An existing live version remains available. Repeating cancellation is harmless; a deploy that has already gone live cannot be cancelled. Use the ID printed by your deploy, not the placeholder above. If another attempt blocks a deploy, the CLI prints its ID and the watch/cancel commands.

Application logs

From the directory containing tori.json:

npx tori.host logs --since 1h --limit 500
npx tori.host logs --follow

One-shot reads show the latest matching lines in chronological order. --follow polls every three seconds; Ctrl-C stops it. A 30-second replay window catches short ingestion delays. Logs replayed after a longer outage require a historical read. Missing storage and an empty time range produce different messages. Log availability depends on the zone's logging rollout and configured retention.

MCP server

The published CLI also carries Tori's MCP server. For Claude Code:

claude mcp add tori -- npx -y tori.host mcp

Other MCP hosts should launch npx with -y, tori.host, and mcp as its arguments using the stdio transport. Run npx tori.host login once first, or set TORI_TOKEN in the MCP host's environment. The server reads the same saved credential and TORI_API_URL as the CLI.

tori_deploy accepts either an already-built static directory containing index.html or a digest-pinned service image; building from source is a CLI path today (issue 315). tori_logs returns a bounded, chronological page and labels application output as untrusted. Database tools are not advertised until the database API and credential path exist.

Environment variables

$ npx tori.host env set DATABASE_URL=postgres://…
✓ set DATABASE_URL = pos•••••••• on plucky-wren
  Applies on the next deploy — a running revision keeps the environment it started with.

$ npx tori.host env list
DATABASE_URL  pos••••••••
PORT          ••••

Three things worth knowing:

  • Only a service has an environment. A static site is files served from object storage: nothing runs, so nothing reads a variable, and every static deploy is stored with no environment at all. env set and env unset are refused on a static site rather than accepted and quietly ignored. env list still works, and says the values are inert — variables set before this check existed are still there.
  • A change applies on the next deploy, not immediately. Each deploy takes a snapshot of the environment, so a revision that is already running keeps the one it started with. Run tori deploy for the change to take effect.
  • Values never come back. The API returns them masked and there is no endpoint that does otherwise, so env list can show that a variable is set and not what it is set to.

The listing goes to stdout and the commentary to stderr, so piping it somewhere gets the variables and not the paragraph about them.

Uploads

The server holds the request open for the whole upload and only answers once the last byte has arrived, so on a slow uplink tori deploy can legitimately run for several minutes — a 100 MB artifact over 1 Mbit/s is about fourteen. The progress line is there so that wait is distinguishable from a hang; when stderr is a pipe (CI), progress is printed as periodic lines instead.

Limits and timeouts, all matched to the server rather than guessed:

| | | | --- | --- | | Largest artifact | 100 MB compressed (refused locally before the upload starts); a source upload is further capped by the plan | | Upload deadline | 20 minutes, the same as the API ingress and the server's build watchdog | | Stall detection | 2 minutes without the socket accepting a byte | | Wait for the build | 20 minutes; timing out here abandons the wait, it does not cancel the deploy |

Environment overrides, mainly for tests: TORI_UPLOAD_TIMEOUT_MS, TORI_UPLOAD_STALL_MS, TORI_DEPLOY_TIMEOUT_MS, TORI_LOGIN_TIMEOUT_MS.

Known ceiling, server-side: the API today closes any single request after five minutes (Node's server.requestTimeout default, not overridden), so an upload slower than roughly 2.8 Mbit/s at the 100 MB cap will be cut off with HTTP 408 no matter what the client does — issue 48. The CLI reports that as what it is rather than as a connection error, but it cannot work around it.

Tests

npm test -w packages/cli

The suite drives the real binary as a child process against a mock control plane on a real socket. Two tests reproduce the five-minute ceiling at real speed and take five and a half minutes each, so they are opt-in:

TORI_SLOW_TESTS=1 npm test -w packages/cli