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

terminal-commands

v0.3.0

Published

A cross-platform, approval-gated terminal companion for ChatGPT, Claude, Codex, and any MCP-compatible AI client.

Readme

Terminal Commands companion

A companion that connects your Windows, macOS, or Linux machine to ChatGPT, Codex, Claude, or another MCP-compatible AI client. Browse approved folders, read text files, and approve commands and file writes on your own machine.

The companion runs on the machine you want to access. Your AI client connects to the hosted MCP server, which routes requests to machines paired with your Terminal Commands account. The companion makes an outbound connection; the hosted setup needs no public port, port forwarding, tunnel, or self-hosted server.

Quick start from npm

You need Node.js 20 or later, npm, and an existing folder to share. The npm package includes native helpers for Windows, macOS, and Linux on x64 and arm64; you do not need Go or a compiler.

1. Install and sign in

Run these commands on the machine you want to connect:

npm install --global terminal-commands@latest
terminal-commands login

Open the URL printed in your terminal and approve the one-time code. Use the same Terminal Commands account when connecting your AI client and signing in to the dashboard. The hosted service's OAuth settings are built in; you do not need an OpenAI API key or to copy access tokens.

Prefer running without a global install? Use npx --yes terminal-commands@latest login and npx --yes terminal-commands@latest connect with the same options shown below.

2. Connect a folder

Open a terminal in the project folder you want to share, then run:

terminal-commands connect --root . --allow-destructive

--root . approves the current folder. --allow-destructive enables an interactive approval prompt for each command or file write. Review the requested executable, arguments, and working directory before approving. Omit that flag for read-only access; commands and file writes will be refused.

You can also use an existing absolute path. For example, on macOS or Linux:

terminal-commands connect --root "$HOME/projects" --name "My laptop" --allow-destructive

Or in Windows PowerShell:

terminal-commands connect --root "$HOME\projects" --name "My PC" --allow-destructive

Replace the example path with your own folder. Repeat --root to approve more folders. Keep the terminal open while using the connection. It shows connection activity, approval requests, command stdout/stderr, exit status, and errors. Ctrl+C stops the companion connection. Disconnecting is not a guarantee that an already-started program has stopped; check the machine if a task's outcome is unknown.

3. Connect your AI client

Choose either the directory plugin or a manual MCP connection below. Both use the same hosted service and paired machines; installing the npm package alone does not add a plugin to your AI client.

Use the published plugin

When Terminal Commands is available in your ChatGPT or Codex Plugins directory:

  1. Open Plugins, search for Terminal Commands, and install it.
  2. Connect your account when prompted, using the same Terminal Commands account as terminal-commands login.
  3. Start a new chat, type @, and select Terminal Commands.
  4. Ask it to list your connected machines and approved folders.

Directory availability depends on publication, review, and workspace policies. If you cannot find the listing, add the hosted MCP server manually using the next section.

Add the MCP server manually

ChatGPT

  1. Open Plugins in ChatGPT.
  2. Select the plus button, then Add custom MCP server.
  3. Enter Terminal Commands as the name and a description such as “Access my paired machines with local command approval.”
  4. Choose a public server connection and enter the full server URL: https://mcp.terminalcommands.fr/mcp.
  5. Choose OAuth authentication. Review the warning, select I understand and want to continue, then Create as a plugin.
  6. Complete the sign-in using the same Terminal Commands account as the companion, review the discovered tools, and install the resulting plugin.
  7. Start a new Work chat, type @, and select your plugin.

Custom MCP connections are subject to your account and workspace policies. See OpenAI's connection instructions for the current interface and metadata refresh steps.

Other MCP clients

In a client that supports remote MCP over Streamable HTTP and OAuth, add:

  • Name: Terminal Commands
  • Server URL: https://mcp.terminalcommands.fr/mcp
  • Transport: Streamable HTTP
  • Authentication: OAuth; sign in with the companion's Terminal Commands account

Use your client's remote-server setup instructions. Clients that only support stdio cannot connect directly to the hosted HTTPS endpoint.

The dashboard URL (https://mcp.terminalcommands.fr/) is a web page. Use the URL ending in /mcp for MCP clients. The local http://127.0.0.1:3333/mcp service belongs to the companion and is not the hosted endpoint to paste into ChatGPT.

Website and dashboard

Visit terminalcommands.fr for the product overview and setup guide. Open your dashboard and select Sign in to your workspace with the same account used by the companion.

The dashboard provides:

  • Overview: a summary of your devices and command sessions.
  • Devices: paired machines and their connection status, including offline devices.
  • Sessions: command history, task status, approval details, errors, and exit codes.
  • Live terminal: follow a selected session's bounded stdout/stderr and copy its output.

You can request cancellation of an active task from its session details. The companion's local approval policy still applies; cancellation is confirmed only when the machine reports that the process stopped. Device revocation is available with the required owner permission and fresh authentication.

The dashboard displays your account's activity; it does not replace the running companion or its local approval prompts. Output is bounded and retained for seven days by default. See the hosted service's privacy policy and terms.

Try your first request

With the companion running and the plugin selected, try:

List my connected machines and their approved folders.

Then, if Git is installed and you enabled command approval:

Run git status in my approved project folder. Show stdout, stderr, and the exit code.

Approve the request in the companion terminal. Commands return a task ID first; the AI client uses wait_process_task or get_process_task with that same ID to retrieve progress and results. If you only see a task ID, ask it to wait for that task and show the output. You can also follow the session in the dashboard. Do not submit the command again just because it is still running or its outcome is unknown.

Troubleshooting

  • No machine appears, or it is offline: keep terminal-commands connect running and check its connection messages. Confirm that the companion, dashboard, and MCP connection use the same account. Run terminal-commands status in another terminal to inspect local sign-in state and settings; it is not a live connection check.
  • Commands or writes are refused: restart with --allow-destructive in an interactive terminal and approve the request there. Without that flag the connection is read-only. A rejected approval or security error is reported in the task result.
  • A folder or program is blocked: choose an existing folder within an approved --root, and check any --allowed-program restriction. Shells, sudo, and su are blocked by default. Ask for the executable and its arguments directly.
  • No output is visible yet: check the companion terminal and dashboard, then ask the AI client to wait for the existing task ID. A program may buffer output or simply produce none. Check the task status and exit code as well as stdout/stderr.
  • Sign-in expired or authentication failed: stop the companion, run terminal-commands login, and reconnect with your chosen roots and options. Reconnect the plugin's OAuth account if the client reports an authentication error.
  • The local service cannot start: check the printed error and whether port 3333 is already in use. Choose another port with connect --port 3334 and your usual roots and approval options.
  • The directory listing is unavailable: use the manual hosted MCP setup above. A missing listing does not require hosting your own server.

To update, stop the companion, run npm install --global terminal-commands@latest, then start connect again with your chosen roots and options. If you use npx, run npx --yes terminal-commands@latest connect with those options instead.

For more help, visit Support. Include your OS, Node.js version, error text, and task ID when relevant. Keep credentials and sensitive command output private.

Security model

  • Binds to 127.0.0.1 by default and refuses public interfaces unless explicitly enabled.
  • The hosted connection uses OAuth and routes requests only to the authenticated user's paired machines.
  • Marks command execution and file writes as destructive and also requires approval in the companion terminal.
  • Runs programs without a shell. Shells, sudo, and su are blocked by default.
  • Passes only a small environment allowlist to child processes, excluding API keys and other secrets.
  • Restricts dedicated filesystem tools to the approved roots.

File reads, bounded directory listings and writes use a bundled native helper with Go's handle-based os.Root API. Approved roots are pinned and checked against their original file identities; a concurrent parent-directory or root symlink swap cannot redirect an operation into another directory. File writes truncate only an already safely opened regular file. The helper is required: missing, crashed or unsupported helpers refuse file IO, with no path-string fallback. Relative paths and the originally configured root aliases remain supported. Roots should be ordinary directories on a trusted local filesystem; this boundary does not prevent privileged mount changes or hard-link aliases.

Process working directories use the same checked root identities and native directory handles during startup. Unix wrappers use fchdir followed by exec, preserving the supervised PID/process group. Windows holds canonical ancestors against rename through process creation; existing taskkill /T supervision includes the wrapper's child. An approved executable still has the user's ordinary OS permissions; the directory boundary is not a process sandbox.

See Go's traversal-resistant APIs for the native filesystem boundary and its mount/hard-link limitations.

Command-line programs still execute with your operating-system user permissions. A program can access more than the dedicated filesystem tools, so review every command approval carefully.

The local MCP server exposes the low-level process supervisor (start_process, read_process_output, list_processes, and terminate_process) only to the local companion over HTTP. The public gateway exposes submit_process, get_process_task, wait_process_task, and terminate_process_task to submit, follow, and request cancellation of tasks with bounded output. There is no legacy public direct-execution API.

Build from source

Building from source requires Node.js 20+ and Go 1.27.2+. npm test builds the host's helper, while npm pack builds all six supported release targets. The published package includes them, so installed users need only Node.js. Helpers are built from the reviewed native/fs-helper source without CGO or downloaded runtime executables. Unsupported OS/architecture combinations fail closed.

npm install
npm run build
MACHINE_TERMINAL_ROOTS="$HOME" npm start

This starts only the local HTTP service. It does not connect a machine to the hosted gateway. For the complete companion, use npm run cli -- login and npm run cli -- connect --root . --allow-destructive after building.

The local health endpoint is http://127.0.0.1:3333/health. Its /mcp endpoint is private to the companion's local capability, as described below.

Command line

terminal-commands login
terminal-commands connect --root ~/Documents/GitHub --root ~/work

From a checkout, the same commands run through npm. Everything after -- reaches the CLI:

npm run cli -- connect --root ~/Documents/GitHub --allow-destructive
npm run cli -- connect --help

Commands: login, connect, status, logout, paired-devices, revoke-device, help. Add --help to a command to see the options it accepts. logout removes saved login credentials; it does not revoke a paired device or stop an already-running companion.

Options

| Option | Applies to | Environment variable | Meaning | | -------------------------- | ---------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | | -r, --root <path> | connect, status | MACHINE_TERMINAL_ROOTS | Approved filesystem root. Repeat the flag, or separate paths with the platform path delimiter. Defaults to the current directory. | | --name <name> | connect, status | MACHINE_TERMINAL_DEVICE_NAME | Device name shown in the client. Defaults to the hostname. | | --device-id <id> | connect, status, revoke-device | MACHINE_TERMINAL_DEVICE_ID | Defaults to the saved local device ID for connect/status; required explicitly for revoke-device. | | --port <port> | connect, status | MACHINE_TERMINAL_PORT | Port for the local MCP service. Defaults to 3333. | | --host <host> | connect, status | MACHINE_TERMINAL_HOST | Bind address for the local MCP service. Defaults to 127.0.0.1. | | --gateway-url <url> | connect, status, paired-devices, revoke-device | MACHINE_TERMINAL_GATEWAY_URL | Defaults to wss://mcp.terminalcommands.fr/device/connect. Change only for a self-hosted gateway. | | --allow-destructive | connect | MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE | Ask in the terminal before each command and file write. Without it both are refused. | | --auto-approve | connect | MACHINE_TERMINAL_AUTO_APPROVE | Approve every command and file write automatically, without a terminal prompt. Implies --allow-destructive. Use with caution. | | --allow-shell | connect | MACHINE_TERMINAL_ALLOW_SHELL | Permit shells and privilege tools such as sudo. | | --allowed-program <name> | connect | MACHINE_TERMINAL_ALLOWED_PROGRAMS | Executable allowlist. Repeat the flag or separate names with commas. | | --allow-public-bind | connect | MACHINE_TERMINAL_ALLOW_PUBLIC_BIND | Permit a non-loopback bind. Only behind authenticated HTTPS. | | --auth-issuer <url> | all | MACHINE_TERMINAL_AUTH_ISSUER | OAuth issuer, for a self-hosted gateway. | | --auth-client-id <id> | all | MACHINE_TERMINAL_AUTH_CLIENT_ID | OAuth client ID. | | --auth-audience <url> | all | MACHINE_TERMINAL_AUTH_AUDIENCE | OAuth audience. | | --dry-run | connect | — | Print the resolved settings and exit without starting anything. | | --json | connect, status | — | Print machine-readable JSON. |

A flag beats the environment variable, and the environment beats the default. --root replaces MACHINE_TERMINAL_ROOTS rather than adding to it. On/off options accept --no- forms, so --no-allow-shell overrides an environment variable that enabled shells.

Roots are expanded (~ included), resolved to absolute paths, de-duplicated, and checked before anything starts, so a typo fails immediately instead of silently approving the wrong folder. connect --dry-run prints exactly what would be approved:

terminal-commands connect --root . --dry-run

Configuration

Options with an environment variable in the table can also be configured that way, for example when running the companion through a service manager.

  • MACHINE_TERMINAL_ROOTS: path-delimited filesystem roots. Defaults to the directory where the companion starts.
  • MACHINE_TERMINAL_HOST: bind host. Defaults to 127.0.0.1.
  • MACHINE_TERMINAL_PORT: bind port. Defaults to 3333.
  • MACHINE_TERMINAL_ALLOWED_PROGRAMS: optional comma-delimited executable allowlist.
  • MACHINE_TERMINAL_ALLOW_SHELL=1: permits shells and privilege tools. Avoid enabling this unless necessary.
  • MACHINE_TERMINAL_ALLOW_PUBLIC_BIND=1: permits a non-loopback bind. Do not enable without authenticated HTTPS and OAuth 2.1.
  • MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE=1: enables a terminal prompt for every command or file write. Non-interactive sessions deny these actions.
  • MACHINE_TERMINAL_AUTO_APPROVE=1: approves every command and file write automatically, without prompting. Implies MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE=1. Use with caution, and only when you trust the connected client.

Advanced connections

terminal-commands connect starts the local service and outbound gateway companion together. This is also the normal setup for a headless server: complete login in a browser on another device using the printed URL and code, then keep connect running in an interactive terminal if you want per-command approvals. Non-interactive sessions refuse approval-gated actions unless an administrator explicitly enables --auto-approve.

terminal-commands login stores OAuth credentials in a private local configuration file. terminal-commands status shows its directory. Do not copy credentials into MCP configuration, dashboard fields, chat messages, or shell arguments.

For a self-hosted gateway, pass its --auth-issuer, --auth-client-id, and --auth-audience to login. Pass the same authentication options plus its --gateway-url to connect. Remote clients need its public HTTPS /mcp URL with OAuth support. Keep the local companion service bound to loopback.

For clients running directly on the same machine, the package also includes dist/stdio.js. Configure your client to launch it with Node.js, using the absolute path inside the installed package and MACHINE_TERMINAL_ROOTS for approved folders. This local-only mode does not pair a machine with the hosted gateway or populate the dashboard. Stdio is read-only by default; see the local approval boundary below.

Protocol-v2 production companion

The hosted gateway requires a protocol-v2 companion (0.2.0 or later). Install terminal-commands@latest and reconnect if an older companion's handshake is rejected.

A local process follows the companion's approval policy, and a repeated task ID returns its existing session instead of spawning a duplicate. The supervisor enforces a bounded process limit (32 running and 512 retained by default) and removes old completed sessions after one hour. Task-ID tombstones remain in the live companion to prevent replay after session history expires.

The local supervisor is currently memory-backed. If the local server itself restarts, an already-running OS process may become unsupervised; a gateway task will remain unknown until it can be reconciled, never automatically rerun.

Local approval boundary and replay safety

The CLI generates a fresh 256-bit MACHINE_TERMINAL_LOCAL_AGENT_TOKEN for its local MCP child and gateway companion. Only the approved companion can use destructive tools over HTTP. Direct HTTP clients (including tunnels) are denied by default, even for reads; stdio clients are read-only by default. Never expose the local agent token in logs or shell arguments. Trusted local stdio administrators can explicitly set MACHINE_TERMINAL_TRUST_STDIO=1; this grants local execution without per-call companion confirmation and must not be enabled for untrusted clients.

The CLI also creates a private, persistent device-secret paired with the device ID. The gateway stores only its hash, requires the matching secret on reconnect, and closes device WebSockets when their OAuth access token expires. Losing the secret requires an explicit re-pair: remove the server-side device registration with authorized administrative access, then connect with a new secret. Signing out alone does not rotate the device identity.

Process startup writes replay-resistant task receipts before executing commands. The CLI saves them in task-receipts.json under its private config directory. Receipts survive local-service restarts, expire after 30 days, and are bounded to 20,000 recent task IDs. The gateway retains idempotency metadata beyond output retention, so old cloud requests still cannot be silently dispatched again.

On Unix the process supervisor runs commands in their own process groups; termination sends SIGTERM and escalates to SIGKILL after a short grace period. On Windows it uses process termination plus taskkill /T /F for forced descendant cleanup. Programs that create independent/detached processes may still escape group cleanup; Terminal Commands is not a full OS sandbox.

Revoke a lost or compromised device

From a trusted terminal, use:

terminal-commands revoke-device --device-id <paired-device-id>

The command requires an interactive confirmation and a fresh Auth0 device login with the separate terminal:devices:revoke permission. It never saves the elevated management token. The Auth0 API and device-code client must first be configured to grant this permission to authorized account owners.

Revocation persists on the gateway, closes the current WebSocket and rejects future connections using the revoked device ID even with its original secret. Revocation cannot terminate processes already running on the machine, revoke stolen Auth0 tokens, or block registration under another ID. Immediately also revoke compromised Auth0 credentials and investigate the host. Restoring the same ID requires a reviewed administrative reset, not a fresh login.

Use terminal-commands paired-devices to list paired device IDs even when machines are offline, including revoked status. The CLI fetches paginated, owner-scoped metadata with the same fresh elevated OAuth permission; secrets and pairing credential hashes are never returned.

Saved projects and the ChatGPT workspace (v0.3.0 preview)

The workspace preview requires the v0.3.0 companion and an enabled workspace MCP connection. It is a development preview until the regular ChatGPT host test and release are complete; installing an older npm release does not enable this view.

In ChatGPT, ask Terminal Commands to open the workspace, then choose Parcourir…, your connected machine, and a folder inside its approved roots. Give it a unique name such as ABC Project. Next time, say “Terminal Commands, work on ABC Project and fix bug ABCD.” Saved projects belong to your account and remember the machine and folder identity. They do not grant access to new paths. If a folder moves or is replaced, browse it again and save a new project. Change approved roots in the companion's local configuration when necessary, then reconnect.

Starting a run stores a bounded source-text baseline on the gateway for seven days. Known credential files, dependencies and generated folders are excluded, but source files may still contain sensitive information. Coverage limits are shown in the view. The Activity tab follows approved commands, local approval, stdout/stderr and exit status. Changes compares captured source files with their state at the start of the run, preserving the distinction from existing edits. Reopen the run to recover logs. An offline or unknown status is not proof that a command stopped; reconnect and inspect the existing task before doing anything again. The dashboard remains available for older command history and device management; the website provides setup instructions and support.