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

gestalt-mobile

v0.11.0

Published

Mobile-first web relay for durable Codex development sessions

Downloads

2,047

Readme

Gestalt Mobile

Mobile-first web relay for Gestalt orchestrated development with durable Codex sessions.

Prerequisites

  • Node.js 24 or newer.
  • The codex CLI installed, available on PATH, and authenticated.
  • Optionally, codex-profile and a ~/.codex-gestalt home. When both exist, sessions use codex-profile cli gestalt app-server --stdio; otherwise they fall back automatically to codex app-server --stdio.

Install and run

Run the latest release without a permanent installation:

npx gestalt-mobile --cwd .
npx --yes gestalt-mobile@latest --cwd ~/devel --port 3000

For frequent use, install the executable globally:

npm install --global gestalt-mobile
gestalt-mobile --cwd .

The command prints the loopback URL when it is ready. Open that URL in a browser. Press Ctrl-C, or send SIGINT or SIGTERM, to stop the HTTP server, active Codex subprocesses, and database cleanly.

Skill profiles

Global profiles live in ~/.gestalt/skill-profiles/<name>.yml and use version 1 YAML:

version: 1
name: focused
skills:
  - name: typescript-advanced-types
    path: /absolute/path/to/SKILL.md
    enabled: true

Use gestalt-mobile --skills focused to apply that profile to every Codex child, or gestalt-mobile --skills list to inspect saved profiles and their enabled skill paths without starting the server. Without --skills, a workspace gestalt-skills.yml is used when present; otherwise Codex-native selection is preserved. Explicit profiles take precedence over project defaults, which take precedence over native configuration. Gestalt Mobile never rewrites Codex configuration or skill files.

Command-line options

| Option | Default | Purpose | | -------------------------- | -------------------- | ----------------------------------------------------------------- | | --cwd <path> | Current directory | Root containing selectable workspaces | | --host <address> | 127.0.0.1 | HTTP listen address | | --port <number> | 3000 | HTTP listen port, from 1 through 65535 | | --public-origin <origin> | Loopback Vite origin | Exact browser origin for passkeys; required for non-loopback hosts | | --disable-passkey-auth | Off | Disable passkey access control and serve every client directly | | --data-dir <path> | XDG state directory | Directory containing relay.sqlite | | --skills <profile> | | Apply a saved global profile to every session | | --skills list | | List global profiles without starting the server | | --help | | Print usage without starting the application | | --version | | Print the installed package version |

--cwd may be relative to the directory where the command is invoked. The resolved directory is the selectable root of a recursive workspace tree. Dot directories are omitted, and traversal stops at each directory containing a .git marker, so repositories are terminal nodes. Directory symlinks are included only when their real target stays under the resolved root; repeated real targets and cycles are omitted. Browser requests select nodes by opaque ID, while real filesystem paths remain server-side.

Passkey deployment and operating limits

Gestalt Mobile has built-in passkey authentication, but does not terminate TLS. --public-origin must be the exact origin the browser uses, including its external HTTPS scheme and port. http://localhost is the development-only exception; every other browser origin must be HTTPS. For example, a local developer may use --public-origin http://localhost:3000, while a deployed relay may listen locally on 127.0.0.1:3000 behind https://relay.example.org with --public-origin https://relay.example.org.

For mobile or network use, put a trusted HTTPS reverse proxy or tunnel in front of the relay. It must preserve the external host and origin, cookies, and WebSocket upgrade; do not mount the relay below a rewritten path prefix. Same hostname processes may use different ports and share authorization (for example, two local relay processes behind https://relay.example.org), but an RP-ID/ hostname change is refused once credentials exist because it would strand those credentials. Do not expose --host 0.0.0.0 before that boundary is in place.

An empty authorization store is deliberately bootstrap-open: the first verified passkey becomes the owner. Register a device before exposing the service. The final authorized device cannot be deleted; synced passkeys can represent more than one physical device, and an enrollment QR/link is neither recovery nor proof of physical proximity.

--disable-passkey-auth restores the unprotected serving behavior from before passkey authentication was added. It does not create or consult passkey state, and --public-origin is not required even for a non-loopback listener. This is an explicit unsafe mode: anyone who can reach the HTTP or WebSocket listener has full access to workspaces, Codex sessions, and Git operations. Use it only on a trusted, access-controlled local environment; never expose that mode directly to a shared or public network. Startup prints a warning whenever it is active.

Persistent state

With --data-dir <path>, state is stored in <path>/relay.sqlite; a relative path is resolved from the command's working directory. Without it, state is stored below $XDG_STATE_HOME/gestalt-mobile/<workspace-hash>/relay.sqlite, or ~/.local/state/gestalt-mobile/<workspace-hash>/relay.sqlite when XDG_STATE_HOME is unset. A matching legacy codex-relay database is reused when present.

Authorization is separate shared state at ~/.codex-gestalt/gestalt-mobile/auth.sqlite (under the selected home). Its directory is created owner-only (0700); treat the database as sensitive and keep it accessible only to the local relay user. Back up auth.sqlite with auth.sqlite-wal and auth.sqlite-shm only after all instances are stopped, or use SQLite backup tooling.

Recovery after losing every passkey is deliberately local and manual: stop every instance, make a backup, remove only auth.sqlite and its -wal/-shm sidecars, restart into visibly open bootstrap mode, and immediately enroll a new device before exposing the service. This discards authorization, device, and session state only—not workspace relay databases or history—and is dangerous while the service is exposed. There is intentionally no hosted service, federation, remote administrator, recovery code, credential export, authentication audit analytics, attestation trust policy, or automatic reset.

For the protocol requirements behind these limits, see the official SimpleWebAuthn server guide, SimpleWebAuthn passkey guidance, MDN passkey guide, and W3C WebAuthn RP ID, origin, and challenge requirements.

Sessions

The Sessions tab uses the recursive filesystem tree to choose the base directory for a new session. Expand or collapse folders with the disclosure buttons, or use Left/Right while a tree item is focused. Up/Down, Home, and End move through visible items; Enter or Space selects the focused directory. The selected path remains highlighted when branches are folded or the catalog is refreshed.

At startup, Gestalt Mobile asks the installed Codex app-server for its available models. New sessions use gpt-5.6-terra by default; choose another discovered model from the Session tab before creating the session. The default is defined centrally as DEFAULT_SESSION_MODEL in src/server/features/sessions/application/start-settings.ts so it can be changed in a future configuration surface. The selected model is stored with the relay session and shown in managed session entries.

Use Open to relaunch a released, stopped, or attention-required relay session from the browser.

If an upgrade has removed the Codex rollout for a saved session, Open keeps the relay session and its settings but creates and binds a replacement Codex thread. The client shows that the earlier Codex history is unavailable; other restore failures leave the saved thread unchanged so Open can be retried.

The relay keeps SQLite state under the supplied data directory, or under the root-hashed XDG state directory when --data-dir is omitted. Active durable threads are resumed after a relay restart. A failed child process is retried with bounded backoff before the session is marked as requiring attention.

Mobile recovery

The browser stores the selected session, its replay cursor, and per-session composer drafts. On a dropped connection it replays retained events; if the server has pruned the gap, it reloads canonical Codex thread history.

Git

The Git tab has its own filesystem-tree selection, independent from the base directory selected in Sessions. Selecting a repository shows its branch divergence, dirty counts, recent commits, and repository actions even when no relay session exists. Selecting an ordinary directory makes it the destination for Clone; repositories cannot be clone destinations. After a successful clone, the catalog refreshes and selects the new repository without changing the Sessions selection.

Pull uses git pull --rebase. Push is available only for a branch that has an upstream, is ahead, and is not behind; it never creates an upstream or force-pushes.

Operation results appear as non-modal notifications. Errors are announced assertively, successful operations politely, and each notification can be dismissed with its keyboard-accessible close button.

Versions and upgrades

Inspect the executable and registry versions with:

gestalt-mobile --version
npm view gestalt-mobile version

npx --yes gestalt-mobile@latest fetches the current release according to npm's cache rules. Upgrade a global installation with:

npm install --global gestalt-mobile@latest

If startup reports an incompatible Codex protocol, upgrade Gestalt Mobile or install the Codex CLI version supported by that release. If session startup fails, first confirm codex --version works in the same shell and that Codex is authenticated. Use gestalt-mobile --help to diagnose rejected options without starting the server.

From a source checkout, maintainers can exercise the installed isolated gestalt profile without touching their normal relay data:

npm run test:open-profile-smoke

The opt-in smoke derives the selected profile's CLI version, creates a temporary workspace and relay database, then checks normal Open and missing-rollout replacement. It creates one bounded harmless turn to establish durable history, deletes only the exact smoke-created Codex threads through the app-server afterwards, and always removes its temporary state. It reports SKIP when the isolated profile is unavailable.

Run from source

npm ci
npm run build
npm start -- --cwd <relay-root>

Development

Run npm run check, npm test, npm run lint, and npm run build.

Maintainers should follow the npm release operations guide when configuring GitHub, rotating credentials, or recovering a partial release.

Copyright and license

Copyright (C) 2026 Dyne.org foundation Designed by Denis Roio [email protected]

SPDX-License-Identifier: AGPL-3.0-or-later

Gestalt Mobile is distributed under the GNU Affero General Public License version 3 or, at your option, any later version. See LICENSE.