{"id":"7b9f65da-3639-4e58-9a9c-549c50aa1fbe","slug":"shellink","kind":"skill","name":"Shellink","summary":"One stable CLI and daemon for SSH, local PTY sessions, file transfer, and remote editing — built for AI agents and humans alike.","owner":"jie123108","repoUrl":"https://github.com/jie123108/Shellink","license":"MIT","licenseTier":"permissive","trust":"community","stars":6,"match":null,"fewStars":false,"format":"skill","createdAt":"2026-07-19T05:15:28.000Z","addedAt":"2026-10-22T01:28:58.995Z","logoUrl":"https://avatars.githubusercontent.com/u/5270270?u=f11b152546b04572bef06840f60d69d60a4f5e7d&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["cloud-infra","files-documents"],"tags":["ai-agents","bastion","cli","devops","jump-host","pty","ssh","ssh-client"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T21:22:15.774Z","sample":false,"url":"https://conduits.dev/tools/shellink","language":"TypeScript","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<div align=\"center\">\n\n<img src=\"web/public/shellink-logo.png\" alt=\"Shellink logo\" width=\"120\" />\n\n# Shellink\n\n**One stable CLI and daemon for SSH, local PTY sessions, file transfer, and remote editing — built for AI agents and humans alike.**\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Node.js >= 22.19](https://img.shields.io/badge/node-%3E%3D22.19.0-339933?logo=node.js&logoColor=white)](https://nodejs.org/)\n[![TypeScript](https://img.shields.io/badge/built%20with-TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](#contributing)\n\n[Features](#features) ·\n[Quick Start](#quick-start) ·\n[Documentation](#table-of-contents) ·\n[Contributing](#contributing) ·\n[中文文档](README.zh-CN.md)\n\n</div>\n\n<div align=\"center\">\n\n<img src=\"docs/screenshots/shellink-agent-jump.gif\" alt=\"An AI agent hopping through a jump host to work on the target server via Shellink\" width=\"720\" />\n\n*An AI agent hops through a jump host and runs commands on the target server — driven entirely through the Shellink CLI.*\n\n</div>\n\nShellink is an open-source session middleware for AI agents and humans working with SSH and local terminal sessions. It provides one stable CLI for connection profiles, interactive sessions, command execution, file transfer, remote editing, and session state. A local daemon owns the sessions and exposes a browser-friendly Web UI plus HTTP and WebSocket compatibility APIs.\n\nRepository: <https://github.com/jie123108/Shellink>\n\n> **Security warning:** `command` profiles execute their configured command as the server process user. Run Shellink only in a trusted environment and protect `SHELLINK_TOKEN`. Shellink also lets an AI agent connect directly to production servers; this carries real operational risk, so prefer read-only, inspection, or analysis operations, or point the agent at non-production environments.\n\n## Table of Contents\n\n- [Shellink](#shellink)\n  - [Table of Contents](#table-of-contents)\n  - [Screenshots](#screenshots)\n  - [Features](#features)\n  - [Why Shellink Is Designed for AI Agents](#why-shellink-is-designed-for-ai-agents)\n  - [Architecture](#architecture)\n  - [Technology Stack](#technology-stack)\n  - [Installation](#installation)\n    - [Install binary (recommended)](#install-binary-recommended)\n    - [Upgrade](#upgrade)\n    - [From source](#from-source)\n  - [Quick Start](#quick-start)\n  - [Usage](#usage)\n    - [Custom Command Profiles](#custom-command-profiles)\n    - [Client and Server Modes](#client-and-server-modes)\n      - [Client mode](#client-mode)\n      - [Server mode](#server-mode)\n    - [HTTP Endpoints](#http-endpoints)\n    - [AI Agent Workflow](#ai-agent-workflow)\n    - [Agent Skills](#agent-skills)\n      - [`shellink-cli`](#shellink-cli)\n      - [`shellink-iterm2-import`](#shellink-iterm2-import)\n  - [Environment Variables](#environment-variables)\n  - [Development](#development)\n  - [Tests and Coverage](#tests-and-coverage)\n  - [Contributing](#contributing)\n  - [License](#license)\n\n## Screenshots\n\nWeb UI dashboard (session list):\n\n<img src=\"docs/screenshots/web-dashboard.png\" alt=\"Web UI dashboard\" width=\"720\" />\n\nWeb UI live session terminal (xterm.js), including a jump-host hop:\n\n<img src=\"docs/screenshots/web-session.png\" alt=\"Web UI live session\" width=\"720\" />\n\nCLI/TUI session view (`shellink cli`):\n\n<img src=\"docs/screenshots/tui-session.png\" alt=\"CLI/TUI session view\" width=\"720\" />\n\n## Features\n\n- **SSH and custom command sessions:** Connect directly with SSH, or run a command/script inside a PTY.\n- **Multi-hop login automation:** `connectType: \"command\"` supports `expect` and similar scripts for multi-level bastion hosts, jump-host menus, OTP prompts, and legacy authentication flows.\n- **Command execution and state handling:** Execute commands, inspect state, provide interactive input, and wait for the session to become ready before the next operation.\n- **File transfer across jump hosts:** Upload and download files through the existing PTY instead of requiring SFTP. This keeps transfers working through custom command chains and multi-hop connections.\n- **Remote file editing:** Apply precise replacements with `shellink session edit`.\n- **Audit history and supervision:** Session input/output is retained as history for audit and replay, while `MANUAL` mode lets a human take control and supervise or answer prompts.\n- **CLI/TUI, Web UI, REST, and WebSocket:** Use the interface that fits the workflow, with stable `--json` output for automation.\n- **Encrypted profiles and optional single-file binaries:** Credentials are protected in SQLite, and Bun builds are available for macOS and Linux.\n\n## Why Shellink Is Designed for AI Agents\n\nShellink is designed around the situations where an AI agent needs reliable access but should not guess or bypass human controls:\n\n- **Scriptable multi-hop access:** Agents can reuse `expect` or other custom login scripts for several bastion hops instead of implementing each site's authentication flow themselves.\n- **PTY-based continuity:** Commands and file transfers use the same PTY path, so an agent can work through jump hosts even when no direct SFTP or SSH endpoint is available.\n- **Human supervision:** `AUTO` mode is for agent actions; `MANUAL` mode hands the terminal to a person for approval, OTP entry, or intervention before automation continues.\n- **Auditable operations:** Session input/output history and daemon logs give operators a record for reviewing what the agent saw and did.\n- **Observable progress:** Explicit session states and machine-readable CLI output let an agent decide whether to execute, send input, wait, or ask for human help.\n\n## Architecture\n\nThe repository is an npm workspace monorepo with one additional non-workspace directory for agent skills:\n\n| Path | Type | Responsibility |\n| --- | --- | --- |\n| `protocol/` | npm workspace | Versioned RPC methods, MessagePack frames, and Zod schemas |\n| `client/` | npm workspace | Shared Unix-socket RPC client used by the CLI and plugins |\n| `cli/` | npm workspace | `shellink` CLI, daemon lifecycle commands, and terminal UI |\n| `server/` | npm workspace | Unix-socket daemon, session engine, services, HTTP, and WebSocket gateway |\n| `web/` | npm workspace | Vue 3 browser console with xterm.js |\n| `plugin-dsh/` | npm workspace | Optional DeepSeek Harness bundle `shellink-dsh` |\n| `skills/` | plain directory | Agent skills for remote operations and iTerm2 profile import |\n\nThe runtime flow is:\n\n```mermaid\nflowchart LR\n  Client[\"CLI / TUI\"] -->|Unix socket, MessagePack RPC| Daemon[\"Daemon services\"]\n  Daemon --> Sessions[\"SSH / local PTY sessions\"]\n  Daemon --> Storage[\"SQLite state and encrypted credentials\"]\n  Daemon --> Gateway[\"HTTP REST / WebSocket gateway / Web UI\"]\n```\n\nThe Unix socket is the primary local interface. HTTP, WebSocket, and the Web UI are compatibility and browser layers. New local automation should use the CLI rather than implementing the socket protocol directly.\n\n## Technology Stack\n\n- **Runtime:** Node.js `>=22.19.0`; Bun is optional for compiled binaries.\n- **Language:** TypeScript with npm workspaces.\n- **Server:** Fastify, `ssh2`, `node-pty`, `ws`, SQLite via `better-sqlite3` and Drizzle ORM.\n- **Protocol:** MessagePack framing and Zod validation.\n- **Web:** Vue 3, Vite, Naive UI, Pinia, and xterm.js.\n- **Testing:** Vitest with V8 coverage and Docker-backed end-to-end fixtures.\n\n## Installation\n\n> **Using an AI coding agent?** Paste this prompt into your agent's chat:\n>\n> ```text\n> Please help me install Shellink and its skills by following https://raw.githubusercontent.com/jie123108/Shellink/main/AGENTS_INSTALL.md\n> ```\n\n### Install binary (recommended)\n\nPrebuilt binaries are published for macOS and Linux (`darwin-arm64`, `darwin-x64`, `linux-arm64`, `linux-x64`). Windows is not supported; build from source instead (see below).\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/jie123108/Shellink/main/install.sh -o /tmp/shellink-install.sh\ncat /tmp/shellink-install.sh\nsh /tmp/shellink-install.sh\n```\n\nPin a release tag if needed:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/jie123108/Shellink/main/install.sh -o /tmp/shellink-install.sh\ncat /tmp/shellink-install.sh\nsh /tmp/shellink-install.sh --version v0.1.0\n```\n\nFor a system-wide install into `/usr/local/bin` (already on `PATH` on most systems), run with `sudo`:\n\n```bash\nsudo sh /tmp/shellink-install.sh --dir /usr/local/bin\n```\n\nThe script downloads the matching asset from GitHub Releases, verifies `SHA256SUMS.txt`, and installs `shellink` to `$HOME/.local/bin` by default. If that directory is not on `PATH`, the installer appends an `export PATH=...` line to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.). Open a new shell (or re-export `PATH`), then verify:\n\n```bash\nshellink -V\n```\n\n### Upgrade\n\nUpgrade an existing standalone binary from GitHub Releases:\n\n```bash\nshellink upgrade --check\nshellink upgrade\n```\n\nPin a release tag or skip the confirmation prompt:\n\n```bash\nshellink upgrade --version v0.2.0\nshellink upgrade --yes\n```\n\n`shellink upgrade` only supports Bun prebuilt installs. Source installs should rebuild, or re-run `install.sh`.\nIt displays download progress on stderr and retries transient network failures automatically. If GitHub is slow or unreachable, configure a proxy before retrying:\n\n```bash\nexport HTTPS_PROXY=http://127.0.0.1:7890\nshellink upgrade\n```\n\n### From source\n\nRequirements:\n\n- Node.js 22.19 or newer.\n- npm.\n- Docker, only if you want to run the Docker-backed end-to-end tests.\n- Bun, only if you want to build a standalone binary.\n\n```bash\ngit clone https://github.com/jie123108/Shellink.git\ncd Shellink\nnpm install\nnpm run build\n```\n\nThe built CLI is available at `./node_modules/.bin/shellink`. To build a standalone executable for the current platform:\n\n```bash\nnpm run build:binary\nmkdir -p \"$HOME/.local/bin\"\ncp dist/shellink \"$HOME/.local/bin/shellink\"\nexport PATH=\"$HOME/.local/bin:$PATH\"\n```\n\nCross-build scripts are available for `macos-arm64`, `macos-x64`, `linux-arm64`, and `linux-x64`.\n\n## Quick Start\n\nStart the interactive terminal UI. It starts the user-level daemon automatically when necessary:\n\n```bash\nshellink cli\n```\n\nCheck the daemon and print the machine-readable agent reference:\n\n```bash\nshellink server status --json\nshellink agent-doc\n```\n\nCreate a command profile and session without putting credentials in shell history:\n\n```bash\nshellink profile create --input - --json <<'JSON'\n{\"name\":\"local-shell\",\"connectType\":\"command\",\"command\":\"/bin/sh\"}\nJSON\n\nshellink profile list --query local --json\nshellink session create --profile <profile-id> --json\nshellink session exec <session-id> --command 'uname -a' --json\nshellink session close <session-id> --json\n```\n\nFor SSH profiles, pass passwords, passphrases, and private keys through `--input FILE` or stdin. Never put them in command-line arguments.\n\nWhen running from source, `npm run dev` starts the server and Vite development UI. Open `http://localhost:5173`. A built daemon serves the embedded UI at `http://127.0.0.1:7070/shellink/ui/` by default; the exact URL is shown by `shellink server run` or `shellink server status --json`.\n\n## Usage\n\n### Custom Command Profiles\n\nCustom command profiles are intended for connections that cannot be represented by a single direct SSH login. Set `connectType` to `command` and provide any command available on the server host, for example:\n\n```json\n{\n  \"name\": \"Bastion menu\",\n  \"connectType\": \"command\",\n  \"command\": \"expect /opt/shellink/login-through-bastion.exp\"\n}\n```\n\nShellink starts the command in a PTY and exposes the same command, input, history, file-transfer, and editing APIs used by SSH sessions. An `expect` script can therefore drive several bastion hosts and authentication steps as one Shellink session. The script, its dependencies, and its credentials run on the server host as the daemon user; only execute trusted commands.\n\n> **Note:** Shellink itself does not handle a host's automatic login process. For automated login (multi-hop hops, jump-host menus, OTP prompts, and other interactive authentication flows), use an [`expect`](https://linux.die.net/man/1/expect) script driven by a `command` profile. Other tools such as `sshpass` (password-only logins) or `ssh` with key-based authentication and `ProxyJump`/`ProxyCommand` can also work, depending on your environment.\n\n### Client and Server Modes\n\n#### Client mode\n\nThe `shellink` executable is the client. TUI commands and resource commands (`profile`, `session`, and `webhook`) connect to the local daemon through a Unix socket. If the socket is unavailable, the client starts a detached daemon, waits for it to become ready, and then sends the request. Add `--json` for stable, one-line machine-readable output.\n\n#### Server mode\n\n```bash\nshellink server start                 # Start in the background\nshellink server status --json         # Inspect health and active sessions\nshellink server logs --lines 100      # Read recent daemon logs\nshellink server restart               # Restart the daemon\nshellink server stop                  # Stop the daemon\nshellink server run                   # Run in the foreground\n```\n\n`server run` is suitable for development or a process manager. The daemon always starts its Unix socket. HTTP/WebSocket support is enabled by default and can be disabled with `SHELLINK_HTTP_ENABLED=false`. HTTP binds to `127.0.0.1` by default; set `SHELLINK_HOST=0.0.0.0` only when remote access is intentional.\n\nLocal requests from `localhost` or `127.0.0.1` can omit authentication, including permanent session-record deletes. Remote HTTP and WebSocket requests require `Authorization: Bearer <SHELLINK_TOKEN>` (or the WebSocket token query parameter used by existing clients). The Web UI probes `GET /shellink/api/auth/sensitive-ops` to decide whether a token is required for delete/purge actions.\n\nWhen nginx (or another reverse proxy) sits in front, the backend usually sees a loopback TCP peer but a public `Host` header. That is treated as remote access: sensitive ops still require a token. `X-Forwarded-For` / `X-Real-IP` are not trusted for the local bypass.\n\n### HTTP Endpoints\n\nAll HTTP, WebSocket, and Web UI routes are served under the `/shellink` prefix:\n\n| Path | Description |\n| --- | --- |\n| `/shellink/ui/` | Embedded Web UI (browser console) |\n| `/shellink/api/*` | REST compatibility API (profiles, sessions, webhooks, auth) |\n| `/shellink/ws/sessions/{id}` | Per-session terminal WebSocket stream |\n| `/shellink/ws/events` | Global session-state event WebSocket stream |\n| `/shellink/agent.md`, `/shellink/llms.txt` | Machine-readable agent reference (same content as `shellink agent-doc`) |\n| `/shellink/healthz` | Liveness probe |\n\n### AI Agent Workflow\n\nUse the installed reference before integrating:\n\n```bash\nshellink agent-doc\n```\n\nThe recommended flow is to search profiles, create a session, wait for `WAITING_INPUT`, execute commands, inspect history when needed, and close the session. Session states are `CONNECTING`, `OUTPUTTING`, `WAITING_INPUT`, `IDLE`, and `DISCONNECTED`; interaction modes are `AUTO` and `MANUAL`.\n\nImportant commands include:\n\n```bash\nshellink profile list --query '<name, host, or command>' --json\nshellink session create --profile <profile-id> --json\nshellink session state <session-id> --json\nshellink session exec <session-id> --command 'ls -la' --json\nshellink session input <session-id> --text 'yes' --json\nshellink session history <session-id> --since 0 --json\nshellink session download <session-id> --path /remote/file --output ./file --json\nshellink session upload <session-id> --input ./file --path /remote/file --json\nshellink session edit <session-id> --input edits.json --json\nshellink session close <session-id> --json\n```\n\nRemote editing accepts exact, non-overlapping replacements and requires an `AUTO` session in `WAITING_INPUT`.\n\n### Agent Skills\n\nThe repository includes two skills under `skills/`. Install with the\n[`skills`](https://skills.sh/) CLI (`npx`). Always pass `--skill` so only the\nmatching subdirectory is installed (the repo contains more than one skill).\n\n```bash\n# List available skills\nnpx skills add jie123108/Shellink --list\n\n# shellink-cli (Codex example; see skills/shellink-cli/README.md for other agents)\nnpx skills add jie123108/Shellink --skill shellink-cli --agent codex\nnpx skills add jie123108/Shellink --skill shellink-cli --agent codex -g\n\n# shellink-iterm2-import\nnpx skills add jie123108/Shellink --skill shellink-iterm2-import --agent codex\n\n# Update\nnpx skills update shellink-cli\nnpx skills update shellink-iterm2-import\n```\n\nPer-agent install and update commands (Cursor, Claude Code, Codex, Pi, Trae,\nAntigravity, OpenClaw) are documented in\n[`skills/shellink-cli/README.md`](skills/shellink-cli/README.md).\n\n#### `shellink-cli`\n\nUse this skill for profiles, SSH or command sessions, interactive input, file transfer, and remote editing. It requires a working `shellink` executable on `PATH`.\n\n#### `shellink-iterm2-import`\n\nUse this skill on macOS to scan and import iTerm2 Profiles and DynamicProfiles:\n\n```bash\npython3 skills/shellink-iterm2-import/scripts/import_iterm2.py --json\npython3 skills/shellink-iterm2-import/scripts/import_iterm2.py --dry-run --name \"Production\"\npython3 skills/shellink-iterm2-import/scripts/import_iterm2.py --guid <guid>\n```\n\nIt requires Python 3.9 or newer and an available `shellink` executable. Review scan results before using `--all`. Re-imports match by `uniqueId` (iTerm2 Guid) first, then by name; matching profiles are updated by default. iTerm2 passwords are not exported; add them later through the Web UI when necessary.\n\n## Environment Variables\n\n| Variable | Description | Default |\n| --- | --- | --- |\n| `SHELLINK_HOME` | Data, master-key, and PID directory | `$HOME/.Shellink` |\n| `SHELLINK_SOCKET` | Unix socket path | Platform-specific runtime path |\n| `SHELLINK_LOG` | Daemon log path | `$SHELLINK_HOME/shellink.log` |\n| `SHELLINK_HTTP_ENABLED` | Enable HTTP/WebSocket compatibility services | `true` |\n| `SHELLINK_HOST` | HTTP bind address | `127.0.0.1` |\n| `SHELLINK_PORT` | HTTP port | `7070` |\n| `SHELLINK_TOKEN` | API and Web UI token for remote access | `change-me` |\n| `SHELLINK_REQUIRE_TOKEN_FOR_SENSITIVE_OPS` | Force token for session delete/purge (`true`/`false`); unset derives from local vs remote | derived from request |\n| `SHELLINK_MASTER_KEY` | 32-byte key as 64 hex characters | Generated on first start |\n| `SHELLINK_DB` | SQLite database path override | `$SHELLINK_HOME/shellink.db` |\n| `SHELLINK_MAX_FRAME_BYTES` | Maximum RPC payload | `16777216` |\n| `SHELLINK_SOCKET_MAX_QUEUE_BYTES` | Maximum buffered bytes per Unix-socket client before backpressure | `4194304` |\n| `SHELLINK_SILENCE_MS` | Quiet-period threshold for state detection | `800` |\n| `SHELLINK_EXEC_TIMEOUT_MS` | Default command timeout | `20000` |\n| `SHELLINK_TRANSFER_MAX_BYTES` | Maximum upload/download size | `6291456` |\n| `SHELLINK_TRANSFER_TIMEOUT_MS` | Default transfer timeout | `120000` |\n| `SHELLINK_EDIT_TIMEOUT_MS` | Default remote-edit timeout | `25000` |\n| `SHELLINK_SSH_READY_TIMEOUT_MS` | SSH readiness timeout | `30000` |\n\nFor production, set `SHELLINK_MASTER_KEY` explicitly and keep it stable for the lifetime of the database. The generated key is stored as `$SHELLINK_HOME/master.key` with restrictive permissions.\n\n## Development\n\n```bash\nnpm run dev                 # Server and Web UI\nnpm run dev:server         # Server only\nnpm run dev:web            # Web UI only\nnpm run build              # Production runtime build\n```\n\n## Tests and Coverage\n\nThe project has unit, integration, protocol, CLI/TUI, WebSocket, and Docker-backed end-to-end tests.\n\n```bash\nnpm run test:protocol\nnpm run test:client\nnpm run test:server\nnpm run test --workspace=cli\nnpm run test:plugin-dsh\nnpm run test:server:coverage\nnpm run test:coverage:full --workspace=server\n```\n\nServer coverage uses Vitest's V8 provider and enforces these thresholds:\n\n| Metric | Threshold |\n| --- | ---: |\n| Lines | 98% |\n| Statements | 98% |\n| Functions | 97% |\n| Branches | 90% |\n\n`test:server:coverage` excludes the long-running `extreme` and `abnormal` E2E suites. Use `test:coverage:full` when Docker and the full integration environment are available. HTML and JSON coverage reports are written under `server/coverage/`.\n\n## Contributing\n\nBug reports, feature proposals, tests, and documentation improvements are welcome. Please keep credentials out of commits, run the relevant test and build commands before submitting changes, and keep protocol changes synchronized across `protocol/`, `cli/`, and `server/`. Every code submission must include corresponding unit tests, and must not lower any of the coverage thresholds listed above.\n\n## License\n\nShellink is licensed under the [MIT License](LICENSE).\n"}