digitalocean/ShellPort
JavaScript
Captured source
source ↗digitalocean/ShellPort
Description: Ephemeral Coding Interview Workstation
Language: JavaScript
Stars: 0
Forks: 0
Open issues: 0
Created: 2026-03-26T19:30:33Z
Pushed: 2026-06-09T04:15:18Z
Default branch: main
Fork: no
Archived: no
README:
ShellPort
Ephemeral coding interview workstation. One command to install, a local browser dashboard to run it, one click to remove.
---
Install
Two entry points, same installer — admins set up company-owned machines, candidates set up their own.
Admin (company-owned machine):
# macOS / Linux curl -fsSL https://do.co/shellport-admin-mac | bash
# Windows (PowerShell) irm https://do.co/shellport-admin-win | iex
Candidate (own machine):
# macOS / Linux curl -fsSL https://do.co/shellport-macos | bash
# Windows (PowerShell) irm https://do.co/shellport-windows | iex
Prerequisites: Docker (running) and Node.js. Your browser opens to http://localhost:3000 — everything runs locally, no cloud. The dashboard shows build progress, then "Start in" buttons for each detected editor (VS Code, Cursor, Windsurf, VSCodium…), the web editors vscode.dev and github.dev, and the container terminal.
Deploy via MDM (Jamf / Intune)
The same one-liner is the MDM payload — no wrapper needed. ShellPort is per-user (it installs to ~/shellport, uses the logged-in user's Docker, and opens their browser), and the installer detects when an MDM runs it as root (Jamf) or SYSTEM (Intune) and automatically re-runs in the logged-in user's session, forwarding any SHELLPORT_* config.
- Jamf (macOS): paste
curl -fsSL https://do.co/shellport-admin-mac | bashinto a script and run it from a policy. Use a login or Self Service trigger so a user is present; if none is, the run exits cleanly so the next login retries. Set per-event config (questions, Slack token/channel, label) as policy parameters exported asSHELLPORT_*, or bake them into the release. - Intune (Windows): deploy
irm https://do.co/shellport-admin-win | iexas a platform script. Either set "Run this script using the logged-on credentials = Yes" (cleanest — runs as the user directly), or leave it as SYSTEM and the installer re-launches into the user's session via a one-shot scheduled task.
Prerequisites still apply per user: Docker (set to start at login) and Node.js must be installed for the logged-in user, or the installer stops with a clear message.
---
The Container
The IDE opens inside an isolated container with the latest Go, Python, Java, Node.js, C/C++, TypeScript, GitHub Copilot, Claude Code, GitHub CLI, doctl, Homebrew, neovim, jq, and yq. All candidate work must be saved in /workspaces.
---
Cleanup
Click "End Interview" in the dashboard, or run the script directly:
- macOS / Linux:
~/shellport/done.sh - Windows:
~\shellport\Done.ps1
This stops the server, kills IDE processes, tears down ShellPort's own container and volume, and deletes the project directory. It is scoped to ShellPort — never a host-wide Docker prune, and it leaves browsers and credentials untouched.
Recycle vs. End Event (operator)
Two operator actions, both gated behind OS-level admin auth (macOS/Linux sudo/pkexec, Windows UAC) so a candidate session can't reach them:
- Recycle (DO station): scrub the host and load a fresh question for the next candidate without rebuilding the machine.
- End Event: tear down the workstation — power off a DO station, or return the uninstall command on a BYOD machine.
ShellPort detects its machine type. On a candidate's own (BYOD) machine it only ever removes its own footprint — never the aggressive host scrub reserved for dedicated DO stations.
Containment leak (managed stations only): candidate work belongs in the container's /workspaces volume, which the teardown destroys. If a candidate saves to the host instead (Desktop, Documents, Downloads), the Recycle/End Event scrub diffs those folders against the pre-session snapshot and removes only the files added during the session — pre-existing station files are left untouched. The reset screen flags how many leaked files were found/removed, and the run writes .last_scrub.json (baseline, removed, and any that couldn't be removed). Verify it with:
# macOS / Linux node ~/shellport/admin/validate-containment-leak.js # Windows node $env:USERPROFILE\shellport\admin\validate-containment-leak.js
The validator confirms every removed file is gone, every pre-existing file survived, and no candidate-added file remains — exiting non-zero if anything is off. This runs only on managed DO stations (never BYOD), and never touches files outside the candidate's own work folders.
---
Security
Credential isolation is enforced via devcontainer.json: IDE settings block GitHub token injection, Git credential forwarding, SSH agent forwarding, and port forwarding; every spawned shell force-clears host tokens; the remote environment nullifies host variables and suppresses history. The container mounts only a named Docker volume — no host filesystem, Docker socket, or SSH agent socket is exposed.
Interviewer surfaces — Settings, telemetry, Recycle, End Event — are gated behind an admin unlock (the machine's OS-user password; no separate admin password) and never appear on a BYOD machine. Before each interview ShellPort confirms the host is clean and holds setup until any residue is cleared.
The troubleshooting panel (common fixes plus the manual fallback) is always available to a candidate on their own BYOD machine so they can recover unaided — destructive commands carry a warning and a confirm. On a managed DO station it is gated behind the same admin unlock, so a candidate session can't reach teardown/remove commands.
---
Optional Features
Off by default. Enable via .env or a config URL.
| Feature | .env variable | What it does | |---|---|---| | Timer | ENABLE_TIMER=true | Live active/idle countdown. On expiry: NOTIFY, LOCK, or WIPE. Idle defined by INACTIVITY_TIMEOUT_MINUTES. | | Telemetry | ENABLE_TELEMETRY=true | Exports shell history, AI usage, and Git activity on cleanup. | | Questions | QUESTIONS_URL=… | Loads the assigned question during setup. Source is a Google Sheet of [title, docId] rows (QUESTION_ROW pins the row) or a Google Doc with one question per tab — all tabs are detected automatically and one is assigned…
Excerpt shown — open the source for the full document.
Notability
notability 5.0/10New repo from notable company, lacking traction data