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

synx-connector

v0.4.3

Published

Synx Connector — the local CLI/daemon that bridges a coding agent (Claude Agent SDK or OpenAI Codex SDK) on your machine to a Synx workspace over an authenticated WebSocket control channel.

Readme

synx-connector

The Synx Connector — a local CLI/daemon that bridges a coding agent (the Claude Agent SDK) running on your machine to a Synx workspace over an authenticated WebSocket control channel. People in your workspace can launch and steer AI coding-agent sessions rooted at folders you have explicitly registered on your device; the full transcript streams back to Synx for live viewing and resume.

The connector executes code on your machine. It only ever runs an agent in a folder you registered locally (it does not trust a path the server sends), behind a permission model you control, and you can revoke a device at any time.

The connector is a paid-tier feature — the workspace owner's plan must include it, or a launch is refused with a clear "upgrade required" message.

Install

npm install -g synx-connector

Requires Node.js ≥ 20. Linux, macOS, and Windows are all supported.

Quick start

# 1. Authenticate this machine (opens a browser; OAuth 2.1 + PKCE).
synx-connector login

# 2. Register a folder into a workspace (prints a consent prompt you must accept).
synx-connector register /path/to/project --workspace my-team

# 3. Run the daemon in the foreground…
synx-connector run

# …or install it as a background service (systemd user unit / launchd agent).
synx-connector service install

Then open the Machines page in the Synx web app: your device and its registered folders appear there, and you can launch a session on any folder.

Coding agent: Claude or Codex

The connector spawns a coding agent on your machine to run each session. It can drive either the Claude Agent SDK (the default) or OpenAI Codex (via the @openai/codex-sdk). The choice is install-level, made once by the operator of this machine.

This is a different surface from connecting-codex.md. That guide covers Codex as an MCP client — pointing Codex at Synx's /mcp endpoint so Codex can drive the tracker. This section is about Codex as the coding agent the connector spawns to do work in a registered folder. The two are unrelated: you can use either, both, or neither.

Selecting the agent

Set the SYNX_CONNECTOR_AGENT environment variable in the daemon's environment:

| Value | Agent | | --------------- | -------------------------------------- | | unset (default) | claude — the Claude Agent SDK | | claude | the Claude Agent SDK | | codex | OpenAI Codex (via @openai/codex-sdk) |

The value is case-insensitive; an unset or unrecognized value falls back to claude, so a typo never silently switches agents and an existing install is unchanged.

This selection is per connector install, not per session — it is read from the daemon's environment at startup, and the wire protocol is unchanged (a session.start carries no agent field, so the server never dictates which agent runs locally). A per-folder override is a documented future follow-on and is not shipped: today one machine runs one agent for every folder it hosts.

Set it wherever the daemon reads its environment. For the background service, that means the unit/plist/task environment — for example, in the systemd user unit add it under [Service]:

[Service]
Environment=SYNX_CONNECTOR_AGENT=codex

(then systemctl --user daemon-reload && systemctl --user restart synx-connector.service). For a foreground synx-connector run, export it in the shell first:

export SYNX_CONNECTOR_AGENT=codex
synx-connector run

Running Codex — prerequisites

To run the connector with SYNX_CONNECTOR_AGENT=codex, the machine needs:

  1. The codex CLI available. It ships bundled with the @openai/codex-sdk dependency the connector installs — you do not install codex separately. The connector still needs Node.js ≥ 20 as usual (the bundled codex CLI itself requires Node 18+, which that satisfies), and the daemon's PATH must let the CLI resolve (the background-service units already seed an explicit PATH for this reason).

  2. A Codex credential provisioned on the machine, one of:

    • ChatGPT login — run codex login, which writes a token to ~/.codex/auth.json; or
    • an API key in the daemon's environment: OPENAI_API_KEY or CODEX_API_KEY.

    The daemon only checks ~/.codex/auth.json for presence (a single stat) and never reads, parses, copies, logs, or transmits it — the codex CLI subprocess is the only reader. The connector points that subprocess at your ~/.codex (via HOME/CODEX_HOME) so a headless service can find the file, and strips its own Synx credentials from the subprocess environment.

A preflight runs before each Codex session launches: if neither a ChatGPT login (~/.codex/auth.json) nor an API key (OPENAI_API_KEY/CODEX_API_KEY) is present, the launch fails fast with a clear, actionable error instead of letting the CLI fail opaquely mid-turn:

No Codex credential found: sign in with `codex login` (creates ~/.codex/auth.json)
or set OPENAI_API_KEY / CODEX_API_KEY in the daemon's environment.

Permission modes under Codex

The connector's permission modes (the permissionCeiling in ~/.synx/config.json, and the mode a launch requests) apply to both agents. Under Codex each mode maps to a Codex approvalPolicy × sandboxMode pair:

| Connector mode | Codex approvalPolicy | Codex sandboxMode | Network | | ------------------- | ---------------------- | ------------------- | ------- | | ask (default) | on-request | workspace-write | off | | acceptEdits | on-failure | workspace-write | off | | bypassPermissions | never | workspace-write | off |

In every mode:

  • Network access is off — set explicitly, never left to a sandbox default.
  • Writes are confined to the registered folder (the session's cwd); there is no additional writable directory. Codex's danger-full-access sandbox is never used from any mode.
  • bypassPermissions under Codex is still sandbox-confined. Unlike Claude's bypass mode — which has no OS sandbox — Codex's never approval policy still runs inside the workspace-write sandbox, so it remains bounded to the registered folder with no network. It is therefore a safer bypass than the Claude path's.

The permissionCeiling is enforced identically for both agents upstream of this mapping, so tightening it (e.g. to forbid bypassPermissions) has the same effect no matter which agent is selected.

Commands

| Command | Description | | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | login [--api-url <url>] | OAuth 2.1 + PKCE login; saves tokens to ~/.synx/credentials.json (chmod 0600). | | logout | Best-effort server-side revoke + delete local credentials. | | register <path> --workspace <slug\|id> [--name <name>] | Validate + consent + bind a folder into a workspace. | | unregister <path> | Remove a folder (server + local registry). | | list | List locally-registered folders. | | status | Show login / device / folder / config summary. | | run [--api-url <url>] | Run the foreground daemon. | | service install\|uninstall\|status [--activate] [--deactivate] | Manage the background service unit (systemd / launchd / Windows Task Scheduler). --activate on install (and --deactivate on uninstall) also runs the activation commands instead of only printing them. |

Global flags: --log-level debug|info|warn|error (default info). --api-url is accepted on every host-relevant command so one binary can target dev / prod / local without re-login churn; the default is https://api.synx-ai.app.

login

synx-connector login

Opens your browser to the Synx consent page (OAuth 2.1 with PKCE; the connector requests the connector scope). On the consent screen you confirm that this machine may connect to your account on your behalf — that is what the consent checkbox means: it authorizes the daemon to hold a token that lets workspace members start agent sessions on the folders you later register, nothing more. It does not grant access to any folder until you explicitly register one.

On success, tokens are written to ~/.synx/credentials.json (chmod 0600). The client registration is idempotent per API URL: a second login reuses the stored client_id.

register <path> --workspace <slug|id>

synx-connector register ~/code/my-project --workspace my-team --name "My Project"

Registering a folder is the trust boundary. Before anything is sent to the server the CLI:

  1. validates the path is an existing absolute directory on this machine;
  2. resolves --workspace against your memberships;
  3. prints a transcript-storage consent prompt and requires an explicit y.

The consent language makes the stakes explicit: sessions in this folder execute code on this machine, and the full transcript (the agent's messages, the tools it runs, and their output) is sent to Synx and stored there so it can be viewed and resumed from the web app. Do not register a folder containing secrets you would not want captured in a stored transcript. Only on your y is the folder bound server-side and recorded in the local registry.

run

synx-connector run

Runs the daemon in the foreground: it opens the authenticated WebSocket to Synx and waits for session launches. Useful for a first smoke test or under your own supervisor. For an always-on setup, prefer service install.

service install | uninstall | status

synx-connector service install

Installs the daemon as a user-level background service. By default it writes the unit/plist and prints the activation commands to run — it does not shell out to systemctl/launchctl/schtasks, so you stay in control and it works headless. Pass --activate to have it run those activation commands for you (one-command setup); pass --deactivate on uninstall to run the teardown commands:

  • Linux (systemd user unit) — written to ~/.config/systemd/user/synx-connector.service, then:

    systemctl --user daemon-reload
    systemctl --user enable --now synx-connector.service
    # (optional) keep it running after logout:
    loginctl enable-linger "$USER"

    The unit sets an explicit PATH= in [Service]. This is deliberate: headless systemd provides a minimal environment, and the Agent SDK spawns a subprocess that needs a usable PATH to find its tools. The unit seeds PATH with the directory of the current Node binary plus the common bins. No TTY is required — the daemon never prompts on this path; permission decisions are answered from the Synx web app.

  • macOS (launchd LaunchAgent) — written to ~/Library/LaunchAgents/com.synx.connector.plist, then:

    launchctl load ~/Library/LaunchAgents/com.synx.connector.plist

    The plist sets RunAtLoad, KeepAlive, and an explicit PATH environment variable for the same headless reason.

  • Windows (Task Scheduler logon task) — the recommended one-command path is to let service install --activate create AND start the task for you (see the Windows setup section below). The write-only default still applies for headless installs: service install writes the task XML to $env:USERPROFILE\.synx\synx-connector-task.xml (PowerShell) plus a small hidden-window launch shim, then prints the activation commands so you can run them yourself:

    schtasks /Create /TN SynxConnector /XML "$env:USERPROFILE\.synx\synx-connector-task.xml" /F
    schtasks /Run /TN SynxConnector

    The task is a per-user logon task named SynxConnector: it starts the daemon at user logon and is configured to restart on failure. It runs in the context of the interactive user, so it inherits your PATH — which is why node and the claude CLI must be resolvable on that user's PATH (see Prerequisites for Windows below). The daemon runs with a hidden console window (launched via a wscript.exe VBScript shim) so nothing pops up at logon, while keeping InteractiveToken so the Agent SDK's claude subprocess still inherits your interactive PATH. Check it with:

    schtasks /Query /TN SynxConnector

service status reports whether the unit/plist/task exists; service uninstall removes it (and the launch shim) and prints the disable/unload commands (on Windows, schtasks /Delete /TN SynxConnector /F), or pass --deactivate to run them for you. Pass --api-url <url> to bake a non-default API URL into the unit.

Windows quoting/shell gotchas. Use PowerShell and its native $env:USERPROFILE — cmd's %USERPROFILE% does not expand in PowerShell. Use plain straight double quotes ("), never smart/curly quotes. Do not run schtasks from git-bash/MSYS: it mangles /-prefixed args (e.g. /Create is rewritten to a path). Run it from PowerShell or cmd. If schtasks reports access-denied, run it from an elevated shell — and note the ownership gotcha: a task created from an elevated shell can only be managed (run/delete) from an elevated shell.

Windows setup (PowerShell)

The connector binary is cross-platform; on Windows the background service is a Task Scheduler logon task rather than a systemd/launchd unit. The full path:

  1. Prerequisites. Node.js ≥ 20, and the claude CLI installed and on your PATH. The Agent SDK spawns the claude CLI as a subprocess; on Windows the connector runs as a logon task that inherits the interactive user's PATH, so claude must be resolvable on that user's PATH for sessions to launch.

  2. Install the connector globally and confirm the version:

    npm i -g synx-connector
    synx-connector --version
  3. Log in (opens your browser for the OAuth consent screen):

    synx-connector login
  4. Register a folder into a workspace, then list your registered folders:

    synx-connector register C:\path\to\project --workspace <slug>
    synx-connector list
  5. Install the service (recommended one-command path). service install --activate writes the task XML to $env:USERPROFILE\.synx\synx-connector-task.xml (plus a hidden-window launch shim) and creates + starts the scheduled task for you:

    synx-connector service install --activate

    If schtasks reports access-denied, re-run this from an elevated (Run as administrator) PowerShell. Remember the ownership gotcha: a task created elevated can only be managed elevated.

    Headless / manual alternative. Plain service install (no --activate) only writes the files and prints the activation commands — run them yourself. Use PowerShell's $env:USERPROFILE (not cmd's %USERPROFILE%), plain straight quotes, and do not run these from git-bash (MSYS mangles the /-args):

    synx-connector service install
    # then run the printed commands:
    schtasks /Create /TN SynxConnector /XML "$env:USERPROFILE\.synx\synx-connector-task.xml" /F
    schtasks /Run /TN SynxConnector

    Confirm it took:

    synx-connector service status
    schtasks /Query /TN SynxConnector
  6. Uninstall when you're done. service uninstall --deactivate deletes the task and removes the files for you:

    synx-connector service uninstall --deactivate

    Or run the printed delete command yourself after a plain service uninstall (a task created elevated must be deleted from an elevated shell):

    synx-connector service uninstall
    # then run the printed command:
    schtasks /Delete /TN SynxConnector /F

On Windows, the OAuth credentials at %USERPROFILE%\.synx\credentials.json are restricted to the current user via an icacls owner-only ACL (on POSIX the same protection is chmod 0600).

Local state (~/.synx/)

| File | Contents | Perms | | ------------------ | -------------------------------------------------- | ------ | | credentials.json | OAuth tokens | 0600 | | device.json | this install's registered device id | 0600 | | folders.json | the local folder registry (the trust boundary) | 0600 | | config.json | optional config (see below) | — |

The ~/.synx directory itself is 0700.

Configuration (~/.synx/config.json)

All fields optional:

{
  "permissionCeiling": ["ask", "acceptEdits"],
  "maxConcurrentSessions": 4
}
  • permissionCeiling — the permission modes this machine will accept on a server-launched session. Default: all modes (ask, acceptEdits, bypassPermissions). Tighten it to e.g. forbid bypassPermissions on a shared box; a launch above the ceiling is rejected locally. With the default ask, the agent pauses for your approval on each sensitive tool use (you answer from the Synx web app).
  • maxConcurrentSessions — concurrency cap. Default 4 (matches the server).
  • sessionIdleTimeoutMinutes — idle-reap window: a multi-turn session sitting in awaiting_input with no new input for this long is ended by the daemon. Default 30; range 11440.
  • sessionMaxLifetimeMinutesmax wall-clock session lifetime: every session ends this long after launch regardless of activity (the idle reaper only bounds abandoned sessions, since input resets it). The end is graceful and identical to an idle reap — pending prompts settle as deny and the session shows as completed — with the distinct reason "max session lifetime exceeded". Default 720 (12 h); bounded 301440 (30 min – 24 h): it is a security control, so it cannot be disabled or made effectively infinite. An out-of-range value fails config validation and the defaults apply.

Security model — what Synx can and cannot do to your machine

Can:

  • Run an AI coding-agent session only in a folder you explicitly registered — and only at the exact (folderId, path) recorded in your local registry. A compromised or malicious server cannot make the daemon execute code in a folder you never registered, nor swap the path under a known folder.
  • Stream the transcript of those sessions back to Synx, where it is stored (see the registration consent) and retained for 30 days.

Cannot:

  • Touch any folder outside your local registry.
  • Escalate past your permissionCeiling. With the default ask mode, permission prompts are on by default — each sensitive tool use waits for your explicit approval, and a pending request defaults to deny after about 10 minutes.
  • See your OAuth token in any log: the bearer is sent only in the Authorization header on the WebSocket upgrade — never as a query-string token — and is scrubbed from every log field.

How to revoke:

  • Web app — Settings → Connected apps: revoke the connector's OAuth grant.
  • Machines page: revoke an individual device (kill switch). The daemon's socket is closed immediately and it can launch nothing further.
  • synx-connector logout: deletes local credentials and attempts a best-effort server-side revocation.

MCP servers in headless sessions

Sessions launched through the connector run the coding agent headless on your machine, and the agent loads MCP server configuration exactly like an interactive run: the registered folder's .mcp.json and the machine user's user-scope MCP config both apply. Two consequences:

  • OAuth-requiring MCP servers won't work. A server that needs an interactive browser sign-in (for example a hosted HTTP server like mcp.supabase.com) can never complete that flow in a headless session. The daemon surfaces each failed/auth-requiring server as an error entry in the session transcript ("MCP server 'x' failed to connect … continuing without it") and the run continues without it.
  • Connection attempts are time-bounded. The daemon sets an MCP startup timeout of 30 s (via the agent's MCP_TIMEOUT environment variable) so an unreachable or auth-blocked server cannot silently stall the turn for minutes. Set MCP_TIMEOUT yourself in the daemon's environment to override.

If a folder's sessions don't need MCP, remove unused servers from that folder's .mcp.json — and remember user-scope servers apply to every folder on the machine.

Troubleshooting

  • It says my device is offline / a launch failed with a conflict. The daemon isn't connected. Make sure synx-connector run (or the installed service) is running on the machine, and check synx-connector status. A launch can also conflict if the device is already at its concurrent-session cap.
  • The connection keeps closing with code 4401 (auth). Your credentials are bad, missing, or expired. Run synx-connector login again to re-authenticate.
  • The connection closed with code 4403 (revoked). This device's grant was revoked (from the web app or another machine) while it was connected — reconnecting won't help. Re-register by running synx-connector login again, or check whether the revocation was intentional.
  • The connection closed with code 4408 (protocol violation). A malformed message was detected on the channel. This usually means a version mismatch — update synx-connector (npm i -g synx-connector@latest).
  • A session won't launch and Synx says "upgrade required". The connector is a paid-tier feature; the workspace owner's plan must include it.
  • A launch is rejected locally as "above the permission ceiling". The requested permission mode exceeds your permissionCeiling in ~/.synx/config.json. Widen the ceiling (or launch with a lower mode).

Logs

Structured JSON, one object per line (stdout for info/debug, stderr for warn/error) so a systemd/launchd journal can parse them. Tokens are scrubbed from every field defensively. Use --log-level debug for verbose output.

License

MIT — see LICENSE.