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

clinkx

v1.0.0

Published

ClinkX MCP STDIO server — CLI-to-CLI bridge tool

Downloads

43

Readme

ClinkX

An MCP STDIO server with local tools for CLI delegation and workflow orchestration.

  • clink runs a configured CLI adapter (agy, Codex, Claude, Grok, or anything you add) as a subprocess and returns the output.
  • context_builder writes a persisted context bundle from allowed local roots. Selection is deterministic by default. You can also run explicit curator and finalizer adapters, then the server validates and materializes locally.
  • list_workflows, resume_workflow, and run_workflow run multi-stage workflows.

Adapters come from config. There is no hardcoded CLI allowlist. Field-level PAL compatibility is intentional.

Quick start

Node.js >= 24, plus at least one CLI adapter.

npm install
npm run build:all
node dist/index.js

stdout is MCP JSON-RPC only (one JSON object per line). Logs go to stderr.

Local workflow dashboard

After npm run build:all:

node dist/dashboard-cli.js --port 0

Passkey auth is the default. The process binds 127.0.0.1 and ::1 on the same port and prints http://localhost:<port>. An empty credential store also prints one enrollment code. Register a passkey with that code, then sign in as a separate step. Credentials live under CLINKX_WORKFLOWS_DASHBOARD_CREDENTIAL_DIR (default ${CLINKX_WORKFLOWS_STATE_DIR}/dashboard/webauthn). Sessions die on restart.

Screens: Runs, Single Calls, Context Runs, Workflows, Adapters, Artifacts. They show retained workflow state, direct-call lifecycle, standalone/refine context-builder lifecycle, persisted pre-dispatch workflow input, final outputs and errors, validated JSON artifacts, and the launch-time workflow/adapter catalogs. Runs, Single Calls, and Context Runs have their own path routes. The persisted-call inspector is an overlay that still shows up as a nested route in history.

Workflow-call, activity, and context-run detail pages also have local session logs (observability only). Timeline and Conversation are chronological; order comes from the log sequence. Each lane is fenced to one immutable parent generation (run, activity, or context) plus the matching attempt, turn, or curator/finalizer execution. Pages are at most 500 events. A lane stops at 100,000 events. Events are normalized and pattern-redacted. They are not raw provider payloads, a session browser, or a live tail.

The dashboard has no SSE, filesystem watch, worker-health inference, cross-process cancellation, or run-creation form. Session logs cannot replay, approve, cancel, or otherwise control a run. Copied action objects are MCP tool handoffs, not JSON-RPC requests.

Point the dashboard at the same CLINKX_WORKFLOWS_STATE_DIR as the workflow process or you will see a different (often empty) run set. Successful sync and async runs are kept for one day by default so you can inspect them. CLINKX_WORKFLOWS_RETAIN_SUCCEEDED_DAYS=0 or CLINKX_WORKFLOWS_RETAIN_ASYNC_DAYS=0 means keep that class forever, which can fill the disk.

Workflow and activity session logs follow retention of that exact parent generation. Context session logs follow the parent context-run/manual lifecycle. There is no separate context-run pruner yet.

Persisted inputs, outputs, errors, and artifact bytes can be sensitive. Access is loopback-only and passkey-gated. That is a shared-account boundary, not isolation from other processes as the same OS user. Redaction strips high-confidence credentials and user-home paths before write. Prompts, outputs, tool summaries, and reasoning can still be sensitive after that. Per-run state admission defaults to 16 MiB (configurable 1–64 MiB via CLINKX_WORKFLOWS_DASHBOARD_MAX_STATE_BYTES). Raw result/call reads use smaller fixed caps.

For local Docker, compose.dashboard-local.yml runs the real UI + API over plain HTTP. Caddy publishes on 127.0.0.1 and ::1. The browser uses http://localhost:<port>. Caddy shares the dashboard network namespace and proxies IPv4 to Node at 127.0.0.1:4180. The same Node process also listens on ::1:4180. See docs/dashboard-local-compose.md.

Hosted passkey topology is one UI+API service behind Traefik on a private Docker network. See deploy/dashboard-cloud/README.md. The older gateway/companion and split-origin paths exist only as a temporary bearer rollback until local and live cloud passkey ceremonies pass the proof-gated cutover.

To build the local CLI as one host-native executable, use an official Node 25.5+ runtime with SEA support:

npm run build:dashboard:standalone -- \
  --node-executable /absolute/path/to/official-node \
  --output ./artifacts/clinkx-dashboard

The binary embeds the dashboard UI, bundled configuration, workflows, and templates. At runtime it still reads state, context runs, and the inspected workspace from the usual environment paths.

Configuration

Adapter JSON is discovered in this order:

  1. CLINKX_CONFIG_PATH (file or directory). This replaces the whole search path. Shipped adapters are not loaded.
  2. ${XDG_CONFIG_HOME:-~/.config}/clinkx/adapters/*.json. First-wins on name.
  3. Packaged conf/adapters/*.json next to the installed package (import.meta.url). Not process.cwd().

A conf/adapters/*.json file in the current working directory is ignored unless CLINKX_CONFIG_PATH points at it. Full reference: docs/configuration.md.

Dashboard deployment controls:

| Setting | Contract | |---|---| | CLINKX_WORKFLOWS_DASHBOARD_CREDENTIAL_DIR | Optional absolute, non-root credential directory. Host default: ${CLINKX_WORKFLOWS_STATE_DIR}/dashboard/webauthn. Compose pins the writable /data/dashboard-credentials volume. | | DASHBOARD_DEPLOYMENT_SLUG | Required Compose identity, ^[a-z][a-z0-9-]{0,31}$. Local and cloud names keep distinct stack-kind prefixes. | | DASHBOARD_CREDENTIAL_BOOTSTRAP_MODE | Required Compose state assertion. First start is bootstrap. Flip to existing-enrolled right after enrollment, before restart. |

Passkey challenge capacity is 96 login slots and 32 registration/add-passkey slots, with 8 concurrent verifications. Saturation returns 503 auth_busy and Retry-After: 1. Live challenges are not evicted. Local session and challenge cookie names are port-scoped. WebAuthn still uses the shared bare localhost RP ID.

On browser startup, a valid same-origin passkey status beats provisional bearer state. The only bearer fallback is the split-origin static server's exact no-store 404 {"error":{"code":"not_found"}}. Malformed or ambiguous status, and uncertain logout, fail closed. Bearer is the explicit tested rollback.

Dashboard shutdown closes listeners first, then auth/gateway resources. Cleanup failures are aggregated across both.

Context bundles

Use context_builder when a later clink call needs curated repo context and you do not want that source inlined in the first tool response. You must pass a bounded anchor: at least one focus_paths entry or a nonblank search_terms entry. include_globs only narrows the scan when those anchors exist. It does not select context by itself.

The tool writes a durable run directory (manifest.json, artifacts/bundle.md) and returns one minified JSON receipt. The receipt includes recommended_clink.absolute_file_paths. Pass those as absolute_file_paths on a later clink call. The handoff files are the persisted artifacts/bundle.md and manifest.json.

Delegate mode needs an explicit request shape and explicit providers:

{
  "task": "Collect context for the server tool registration",
  "roots": ["/path/to/workspace"],
  "focus_paths": ["src/server.ts"],
  "delegate": {
    "enabled": true,
    "curator": {
      "cli_name": "<curator-cli>",
      "role": "<curator-role>"
    },
    "finalizer": {
      "cli_name": "<finalizer-cli>",
      "role": "<finalizer-role>",
      "min_score": 8.5
    },
    "failure_policy": "fallback",
    "timeout_seconds": 120,
    "max_response_chars": 20000
  }
}

There are no built-in curator or finalizer provider defaults. Provider output is advisory. The server checks strict JSON, rebuilds accepted content from local candidates, reapplies budgets and secret checks, and does not persist raw provider output. failure_policy:"fallback" publishes deterministic local selection as a partial v2 run if delegate curation fails. failure_policy:"fail" returns an error and does not publish a manifest.

Adding an adapter

Put the JSON in ${XDG_CONFIG_HOME:-~/.config}/clinkx/adapters/. Or set CLINKX_CONFIG_PATH to a directory that also contains every shipped adapter you still need. That env var replaces the search path.

{
  "name": "echo",
  "command": "node",
  "args": ["-e", "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>process.stdout.write(d));"],
  "parser": "text",
  "prompt_mode": "stdin",
  "timeout_seconds": 60
}

MCP client config

The exact shape depends on the client.

Via npx (recommended):

{
  "mcpServers": {
    "clinkx": {
      "command": "npx",
      "args": ["-y", "clinkx@latest"],
      "env": {
        "CLINKX_ALLOWED_ROOTS": "/path/to/your/workspace",
        "CLINKX_WORKFLOWS_WORKSPACE_ROOT": "/path/to/your/workspace"
      }
    }
  }
}

From a local clone:

{
  "mcpServers": {
    "clinkx": {
      "command": "node",
      "args": ["/path/to/clink-mcp/dist/index.js"],
      "env": {
        "CLINKX_ALLOWED_ROOTS": "/path/to/your/workspace",
        "CLINKX_WORKFLOWS_WORKSPACE_ROOT": "/path/to/your/workspace"
      }
    }
  }
}

Safety

ClinkX validates request paths, environment variables, and argument policy. It does not sandbox the spawned process.

CLINKX_ALLOWED_ROOTS limits which file paths the tool accepts. Default is process.cwd(). It is required only if the MCP host starts ClinkX with cwd at /. Set it anyway so path admission does not depend on whatever cwd the host chose. The subprocess has the same permissions as whoever started ClinkX.

Set CLINKX_WORKFLOWS_WORKSPACE_ROOT to the same workspace. If you omit it, workflows use process.cwd() and warn on stderr.

context_builder validates roots and blocks symlink escapes. Secret material (API keys, private keys, tokens, .env / .pem / id_rsa / credentials.json) is included as written by default (allow_secrets:true) so delegates can probe. Opt out with allow_secrets:false, cb_allow_secrets:false, or CLINKX_CONTEXT_ALLOW_SECRETS=false. Bundle artifacts are not a sandbox and not an access-control boundary.

See docs/security.md.

License

Copyright (c) 2026 jim380. All rights reserved. Proprietary package (license: UNLICENSED). See LICENSE.