RepoPilotOpen in app →

coder/sshcode

Run VS Code on any server over SSH.

Mixed

Stale — last commit 6y ago

weakest axis
Use as dependencyMixed

last commit was 6y ago; no tests detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 15 active contributors
  • Distributed ownership (top contributor 29% of recent commits)
  • MIT licensed
Show all 6 evidence items →
  • CI configured
  • Stale — last commit 6y ago
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/coder/sshcode?axis=fork)](https://repopilot.app/r/coder/sshcode)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/coder/sshcode on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: coder/sshcode

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/coder/sshcode shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 6y ago

  • 15 active contributors
  • Distributed ownership (top contributor 29% of recent commits)
  • MIT licensed
  • CI configured
  • ⚠ Stale — last commit 6y ago
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live coder/sshcode repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/coder/sshcode.

What it runs against: a local clone of coder/sshcode — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in coder/sshcode | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | Last commit ≤ 2126 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>coder/sshcode</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of coder/sshcode. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/coder/sshcode.git
#   cd sshcode
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of coder/sshcode and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "coder/sshcode(\\.git)?\\b" \\
  && ok "origin remote is coder/sshcode" \\
  || miss "origin remote is not coder/sshcode (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 2126 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2096d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/coder/sshcode"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

sshcode is a CLI tool written in Go that automatically provisions and connects to code-server (a browser-based VS Code) running on a remote Linux server over SSH. It uploads your local VS Code extensions and settings via rsync, then opens the remote editor in a Chrome app-mode window, making remote development feel native. Simple CLI structure: main.go is the entry point, sshcode.go contains the core logic (SSH connection, code-server provisioning, rsync sync), settings.go manages VS Code config/extensions directories. A single Dockerfile in .sail/ provides containerized build/test. Total ~30KB Go code; minimal dependencies.

👥Who it's for

Software developers who want to code on remote servers (staging, development machines, cloud VMs) using VS Code without installing anything permanently on those servers. It targets users already comfortable with SSH who want a seamless remote development experience.

🌱Maturity & risk

The project is deprecated and no longer actively maintained—the authors explicitly recommend using the code-server install script instead (see README and issue #185). It has basic CI via Travis CI and test coverage (sshcode_test.go exists), but the codebase shows signs of age (Go 1.12, dependencies from 2019). Not suitable for new projects.

High risk: This is officially deprecated by the maintainers, with no active development. The dependency tree is dated (golang.org/x/crypto from 2019, Go 1.12 minimum), and the single-maintainer project has drifted from the ecosystem (code-server has evolved significantly). Alpine Linux support is explicitly missing (#122). Do not use for new deployments.

Active areas of work

Nothing—the project is archived/deprecated. The last activity points users to the code-server install script as the recommended replacement. No active PRs, issues, or commits are being triaged.

🚀Get running

go get -u go.coder.com/sshcode

Or download a pre-built binary from the releases page. Then run: sshcode user@host [remote_dir]

Daily commands: After go get, run directly: sshcode user@host.com or sshcode user@host.com ~/remote/path. For development: go build && ./sshcode [flags]. Tests via go test ./...

🗺️Map of the codebase

  • sshcode.go: Core logic: SSH connection, code-server setup, extension/settings sync, and browser launch—largest surface area for bugs and changes
  • main.go: CLI entry point, flag parsing (--skipsync, port selection), and orchestration of sshcode.go functions
  • settings.go: Resolves VS Code config and extensions directories; handles custom paths via VSCODE_CONFIG_DIR and VSCODE_EXTENSIONS_DIR env vars
  • go.mod: Declares minimum Go version (1.12) and dependency versions; update here for version bumps
  • ci/build.sh: Multi-platform release binary builder; run this locally before cutting a release

🛠️How to make changes

main.go: CLI argument parsing and entry point. sshcode.go: All SSH provisioning, code-server download/install, rsync sync logic—this is where 95% of changes happen. settings.go: Handle custom VS Code config/extension directory paths. sshcode_test.go: Unit tests (sparse; add tests here for new features). Add CI/shell scripts in ci/ for release builds.

🪤Traps & gotchas

Env vars required for non-standard VS Code: If using Code Insiders or Nightly, you must set VSCODE_CONFIG_DIR and VSCODE_EXTENSIONS_DIR (examples in README for macOS/Linux). Remote server requirements: Only glibc-based Linux x86_64 supported—Alpine Linux fails. Chrome detection: Best experience requires Chrome installed; falls back to other browsers. No sudo support: Cannot provision on servers where your SSH user lacks write access to installation directory (~/.cache/sshcode/). rsync dependency: Local machine must have rsync available; remote server must have it too (not always pre-installed).

💡Concepts to learn

  • SSH tunneling & port forwarding — sshcode establishes an SSH tunnel to the remote server and forwards a local port to code-server's listening port; understanding port forwarding is key to diagnosing connection issues
  • rsync protocol — sshcode uses rsync to efficiently sync local VS Code extensions and settings to the remote machine; rsync's delta-transfer algorithm means repeat syncs are fast even on slow connections
  • Binary patching & portable distributions — sshcode downloads prebuilt code-server binaries for the remote server architecture; understanding glibc vs musl and x86_64 constraints explains why Alpine Linux is unsupported
  • Chrome app mode — sshcode launches the browser in --app mode to hide the address bar and browser chrome, making the remote VS Code feel native; this is a UX detail that makes the tool special
  • SSH key-based authentication — sshcode relies on your existing SSH config and key setup; the tool doesn't manage credentials itself, so SSH pubkey auth must be already configured
  • Cross-platform CLI argument parsing — sshcode uses spf13/pflag to handle --flags consistently across Linux, macOS, and WSL; understanding flag parsing helps when adding new options
  • cdr/code-server — The upstream project that sshcode wraps—code-server is the actual VS Code server that runs on the remote machine; sshcode just automates its installation and sync
  • microsoft/vscode-remote-release — Microsoft's official remote development extension for VS Code; a modern alternative to sshcode for remote SSH editing (built into recent VS Code versions)
  • vim/vim — Historical alternative for remote editing; sshcode was designed to modernize the remote development UX that vim+SSH provided
  • golang/go — The language sshcode is written in; understanding Go 1.12+ idioms is essential for contributing

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add integration tests for SSH connection and code-server deployment in sshcode_test.go

The repo has sshcode_test.go but given the core functionality involves SSH connections and remote code-server installation/execution, there are likely missing integration test cases. The test file should cover: SSH connection failures, remote code-server installation validation, extension upload via SSH, and connection teardown. This is critical since the whole value proposition depends on reliable remote deployment.

  • [ ] Examine existing sshcode_test.go to identify test gaps
  • [ ] Add test cases for SSH authentication failures and timeout scenarios
  • [ ] Add test cases for code-server installation verification on remote host
  • [ ] Add test cases for extension sync/upload functionality
  • [ ] Test cleanup and SSH session termination
  • [ ] Run tests locally with go test ./...

Add GitHub Actions workflow to replace deprecated .travis.yml and add Windows/macOS cross-platform testing

The repo uses .travis.yml (outdated CI service) but doesn't have GitHub Actions. Given that sshcode is a CLI tool that needs to work across Unix-like systems and potentially Windows users, adding a GitHub Actions workflow with matrix testing across Linux, macOS, and Windows would prevent regressions. The current ci/ scripts (build.sh, lint.sh, ensuremod.sh) exist but aren't properly integrated into modern CI.

  • [ ] Create .github/workflows/test.yml with matrix strategy for ubuntu-latest, macos-latest, windows-latest
  • [ ] Add job steps that run ci/lint.sh and ci/build.sh
  • [ ] Add job to run go test ./... with coverage reporting
  • [ ] Add go mod tidy verification step (ci/ensuremod.sh)
  • [ ] Remove or deprecate .travis.yml with comment pointing to new Actions workflow
  • [ ] Test workflow by pushing to a branch and verifying Actions tab

Add missing settings.go test coverage and document configuration options in README

The repo has settings.go (likely handling CLI flags and configuration) and go.mod includes github.com/spf13/pflag for flag parsing, but there's no visible unit test file for settings.go and the README is incomplete (cuts off mid-sentence at 'It uploads your extensions'). A new contributor should add tests for settings parsing and complete the README to document all CLI options that settings.go provides.

  • [ ] Create settings_test.go with unit tests for flag parsing and configuration validation
  • [ ] Test edge cases like missing required flags, invalid values, and conflicting options
  • [ ] Complete the README.md by reviewing main.go and settings.go for all CLI flags/options
  • [ ] Document: usage examples, supported flags, environment variables, and configuration precedence
  • [ ] Add a 'Configuration' section explaining each flag that spf13/pflag provides
  • [ ] Verify documentation matches actual flag definitions in settings.go

🌿Good first issues

  • Add end-to-end tests for the SSH connection and code-server provisioning flow in sshcode_test.go. Currently sshcode_test.go is sparse; tests for runSSHCommand() and installCodeServer() would catch regressions.
  • Document the VSCODE_CONFIG_DIR and VSCODE_EXTENSIONS_DIR environment variable behavior with examples for VS Code Insiders in multiple shells (.bashrc, .zshrc, .fish). Add a FAQ section to README.md.
  • Add support for custom remote working directories passed via flag (e.g., sshcode --dir /opt/project user@host) instead of requiring positional args. Update main.go flag parsing and sshcode.go launch logic.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • b52faf9 — Add deprecation notice to README (nhooyr)
  • 50e859c — Add git bash and mingw support (#132) (deansheather)
  • ceab32b — Merge pull request #157 from hassieswift621/master (coadler)
  • 7ebef26 — Remove duplicated word from sync user settings error (hassiexx)
  • f3adebb — Merge pull request #147 from BCallifornia/fix-http-warning-nopasswd (sreya)
  • fd95a40 — Fixed allow-http-warning and no auth (BCallifornia)
  • 4f12e8f — Merge pull request #143 from grhbit/ci-build-tar-gzip (deansheather)
  • 6277c6b — Update tarname and tar option for ci build (grhbit)
  • 7e6845d — Update deps (sreya)
  • 926191a — Merge pull request #136 from cdr/upload-custom-binary (deansheather)

🔒Security observations

The sshcode project presents significant security concerns. The codebase is officially deprecated with no active maintenance, uses outdated Go 1.12 with known vulnerabilities, and relies on an old version of golang.org/x/crypto. The project should not be used for new deployments. If currently in use, immediate migration to the official code-server install script is strongly recommended. The incomplete README regarding extension uploads also suggests potential security gaps in the SSH file transfer mechanism that warrant careful code review.

  • High · Outdated Cryptographic Dependencies — go.mod - golang.org/x/crypto dependency. The golang.org/x/crypto dependency (version 0.0.0-20190422183909-d864b10871cd) is from April 2019 and contains known vulnerabilities. This package is critical for SSH operations and cryptographic operations. Fix: Update to the latest version of golang.org/x/crypto. Run 'go get -u golang.org/x/crypto' to fetch security patches.
  • High · Deprecated Project — README.md - Project status. The project is officially deprecated in favor of the code-server install script. This means security updates and maintenance have stopped, leaving the codebase vulnerable to future threats. Fix: Migrate to the official code-server install script (https://github.com/cdr/code-server#quick-install). Do not use sshcode for new deployments.
  • High · Outdated Go Version — go.mod - go version specification. The project specifies Go 1.12 (go.mod), released in February 2019. This version is no longer supported and contains multiple known vulnerabilities in the standard library, particularly in crypto/tls and other security-critical packages. Fix: Update to Go 1.19 or later. Ensure all dependencies are re-validated after the upgrade.
  • Medium · SSH Extension Upload Mechanism — sshcode.go - Extension upload logic (not provided). README mentions uploading extensions over SSH, but details are incomplete. Without reviewing the actual implementation (sshcode.go), there's a risk of insecure file handling, path traversal, or lack of integrity verification during the upload process. Fix: Implement secure file handling: validate file paths to prevent directory traversal, verify file integrity with checksums, use secure copy protocols, and implement proper error handling.
  • Medium · Indirect Dependency: pkg/errors — go.mod - github.com/pkg/errors indirect dependency. The github.com/pkg/errors dependency (marked as indirect) is no longer maintained. While Go 1.13+ provides native error wrapping, using an unmaintained package may pose maintenance risks. Fix: Refactor to use Go's native error wrapping (errors.Is, errors.As, fmt.Errorf with %w) instead of pkg/errors.
  • Low · Missing Security Documentation — Repository root. No evidence of security policy, vulnerability disclosure procedure, or security guidelines in the visible file structure. Fix: Create a SECURITY.md file documenting vulnerability disclosure procedures. However, given the project is deprecated, this may not be necessary.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · coder/sshcode — RepoPilot