sshepherd
Overview
sshepherd is a compiled Bun/TypeScript CLI that lets an agent operate a real remote server over SSH — health checks, docker/systemd service control, log tailing, config file edits, read-only Postgres introspection, and declarative deploys — without ever seeing a password, private key, hostname, username, or port. Every operation shells out to the system ssh binary through a single transport path and returns the same typed Envelope<T> (ok, alias, data, error), never a raw terminal dump. The agent passes only a name — an ssh alias, a Postgres target, or a deploy recipe — that resolves entirely outside the process.
When to Use This Skill
- Use when you need to check a remote server's health (disk, memory, CPU, ports, OOM history) without handing the agent SSH credentials.
- Use when working with remote docker or systemd services — listing, inspecting, or restarting them — or tailing their logs.
- Use when the user asks to read or edit a remote config file, run a declarative deploy from a named recipe, introspect a remote Postgres database read-only, or audit SSH/security posture on a box.
How It Works
Step 1: Declare targets once, outside any prompt
Every connection detail is declared ahead of time and never appears on the command line: ssh aliases in ~/.ssh/config, Postgres targets in ~/.config/sshepherd/targets.toml, deploy recipes in recipe TOML files. OpenSSH resolves the real HostName/User/Port/IdentityFile internally.
Step 2: Invoke a group + action by name
sshepherd <group> <action> [positionals...] [--flag value]
Nine command groups — hosts, check, logs, services, deploy, config, db, files, security — 52 ops total. Output is JSON to stdout by default; add --pretty for a human-readable table/key-value view. The response only ever echoes back the alias it was given — there is no host/user/port/ip field anywhere in the response type, structurally.
Step 3: Discover the command surface
./dist/sshepherd --help # list groups
./dist/sshepherd check --help # list actions + flags for one group
Examples
Example 1: Server health overview
./dist/sshepherd check overview lms-server
Returns a JSON envelope with disk, memory, CPU, listening ports, and OOM history for the host behind the lms-server alias — the agent never learns the host's address.
Example 2: Restart a docker service and tail its logs
./dist/sshepherd services restart lms-server --name api
./dist/sshepherd logs tail lms-server --name api --lines 100
Example 3: Read-only Postgres introspection
./dist/sshepherd db tables prod
prod is a pg-target name that resolves to how to reach psql on a host — never a database password. psql runs inside the target container, authenticated by peer/trust/.pgpass already on the remote.
Best Practices
- ✅ Declare every alias/target/recipe ahead of time in
~/.ssh/config / targets.toml / recipe TOML — never inline connection details.
- ✅ Pass only names (alias, pg-target, recipe) to the CLI; let OpenSSH own authentication.
- ✅ Use
--pretty for human review and default JSON output for machine parsing.
- ❌ Don't try to inject a hostname, user, port, or password into a command — the CLI has no field for them.
- ❌ Don't reach for the
ssh2 npm library or hand-rolled SSH; the whole point is delegating to the trusted system ssh binary.
Limitations
- This skill does not replace environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, or safety boundaries are missing.
- Requires the system OpenSSH client and pre-declared aliases/targets/recipes; it cannot connect to a host that has not been configured outside the agent.
- Postgres access is read-only introspection by design.
Security & Safety Notes
- Zero-knowledge credential model: the agent never sees a password, private key, hostname, username, or port. It only ever passes an ssh alias, a pg-target name, or a recipe name; the real connection tuple is resolved by OpenSSH outside the process, and every response echoes back only the alias.
- Never reads private key material. Authentication happens entirely inside OpenSSH's own trusted code path.
- Confirmation gate on mutations: destructive/mutating actions (service restart, config write, deploy) require an explicit
--yes confirm flag.
- Human-only credential entry: the separate
setup ssh-alias install action opens a one-shot local browser form that only a human can type a password into — the agent can trigger and wait on it but never sees, logs, or relays the password.
- Environment expectation: run against hosts you are authorized to operate.
Common Pitfalls
- Problem: Trying to pass a hostname or password directly to a command.
Solution: Register the target first (
setup ssh-alias register / setup db-target), then reference it only by name.
- Problem: A mutating action returns without doing anything.
Solution: Add the
--yes confirm flag — mutations are gated by design.
Related Skills
@devops-automation - When you need broader CI/CD or infrastructure-as-code automation beyond SSH ops.
1---2name: sshepherd3description: Zero-knowledge SSH ops CLI — server health checks, docker/systemd control, log tailing, Postgres introspection, and declarative deploys, without ever exposing credentials to the agent.4license: MIT5---6
7# sshepherd
8
9## Overview
10
11`sshepherd` is a compiled Bun/TypeScript CLI that lets an agent operate a real remote server over SSH — health checks, docker/systemd service control, log tailing, config file edits, read-only Postgres introspection, and declarative deploys — without ever seeing a password, private key, hostname, username, or port. Every operation shells out to the system `ssh` binary through a single transport path and returns the same typed `Envelope<T>` (`ok`, `alias`, `data`, `error`), never a raw terminal dump. The agent passes only a *name* — an ssh alias, a Postgres target, or a deploy recipe — that resolves entirely outside the process.
12
13## When to Use This Skill
14
15- Use when you need to check a remote server's health (disk, memory, CPU, ports, OOM history) without handing the agent SSH credentials.
16- Use when working with remote docker or systemd services — listing, inspecting, or restarting them — or tailing their logs.
17- Use when the user asks to read or edit a remote config file, run a declarative deploy from a named recipe, introspect a remote Postgres database read-only, or audit SSH/security posture on a box.
18
19## How It Works
20
21### Step 1: Declare targets once, outside any prompt
22
23Every connection detail is declared ahead of time and never appears on the command line: ssh aliases in `~/.ssh/config`, Postgres targets in `~/.config/sshepherd/targets.toml`, deploy recipes in recipe TOML files. OpenSSH resolves the real `HostName`/`User`/`Port`/`IdentityFile` internally.
24
25### Step 2: Invoke a group + action by name
26
27```
28sshepherd <group> <action> [positionals...] [--flag value]
29```
30
31Nine command groups — `hosts`, `check`, `logs`, `services`, `deploy`, `config`, `db`, `files`, `security` — 52 ops total. Output is JSON to stdout by default; add `--pretty` for a human-readable table/key-value view. The response only ever echoes back the `alias` it was given — there is no host/user/port/ip field anywhere in the response type, structurally.
32
33### Step 3: Discover the command surface
34
35```bash
36./dist/sshepherd --help # list groups
37./dist/sshepherd check --help # list actions + flags for one group
38```
39
40## Examples
41
42### Example 1: Server health overview
43
44```bash
45./dist/sshepherd check overview lms-server
46```
47
48Returns a JSON envelope with disk, memory, CPU, listening ports, and OOM history for the host behind the `lms-server` alias — the agent never learns the host's address.
49
50### Example 2: Restart a docker service and tail its logs
51
52```bash
53./dist/sshepherd services restart lms-server --name api
54./dist/sshepherd logs tail lms-server --name api --lines 100
55```
56
57### Example 3: Read-only Postgres introspection
58
59```bash
60./dist/sshepherd db tables prod
61```
62
63`prod` is a pg-target name that resolves to *how* to reach `psql` on a host — never a database password. `psql` runs inside the target container, authenticated by peer/trust/`.pgpass` already on the remote.
64
65## Best Practices
66
67- ✅ Declare every alias/target/recipe ahead of time in `~/.ssh/config` / `targets.toml` / recipe TOML — never inline connection details.
68- ✅ Pass only names (alias, pg-target, recipe) to the CLI; let OpenSSH own authentication.
69- ✅ Use `--pretty` for human review and default JSON output for machine parsing.
70- ❌ Don't try to inject a hostname, user, port, or password into a command — the CLI has no field for them.
71- ❌ Don't reach for the `ssh2` npm library or hand-rolled SSH; the whole point is delegating to the trusted system `ssh` binary.
72
73## Limitations
74
75- This skill does not replace environment-specific validation, testing, or expert review.
76- Stop and ask for clarification if required inputs, permissions, or safety boundaries are missing.
77- Requires the system OpenSSH client and pre-declared aliases/targets/recipes; it cannot connect to a host that has not been configured outside the agent.
78- Postgres access is read-only introspection by design.
79
80## Security & Safety Notes
81
82- **Zero-knowledge credential model:** the agent never sees a password, private key, hostname, username, or port. It only ever passes an ssh alias, a pg-target name, or a recipe name; the real connection tuple is resolved by OpenSSH outside the process, and every response echoes back only the alias.
83- **Never reads private key material.** Authentication happens entirely inside OpenSSH's own trusted code path.
84- **Confirmation gate on mutations:** destructive/mutating actions (service restart, config write, deploy) require an explicit `--yes` confirm flag.
85- **Human-only credential entry:** the separate `setup ssh-alias install` action opens a one-shot local browser form that only a human can type a password into — the agent can trigger and wait on it but never sees, logs, or relays the password.
86- Environment expectation: run against hosts you are authorized to operate.
87
88## Common Pitfalls
89
90- **Problem:** Trying to pass a hostname or password directly to a command.
91 **Solution:** Register the target first (`setup ssh-alias register` / `setup db-target`), then reference it only by name.
92- **Problem:** A mutating action returns without doing anything.
93 **Solution:** Add the `--yes` confirm flag — mutations are gated by design.
94
95## Related Skills
96
97- `@devops-automation` - When you need broader CI/CD or infrastructure-as-code automation beyond SSH ops.