RepoPilotOpen in app →

yudai/gotty

Share your terminal as a web application

Mixed

Stale — last commit 2y ago

worst of 4 axes
Use as dependencyMixed

last commit was 2y 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.

  • 14 active contributors
  • MIT licensed
  • CI configured
Show 3 more →
  • Stale — last commit 2y ago
  • Single-maintainer risk — top contributor 84% of recent commits
  • 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/yudai/gotty?axis=fork)](https://repopilot.app/r/yudai/gotty)

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/yudai/gotty on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: yudai/gotty

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/yudai/gotty 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 2y ago

  • 14 active contributors
  • MIT licensed
  • CI configured
  • ⚠ Stale — last commit 2y ago
  • ⚠ Single-maintainer risk — top contributor 84% of recent commits
  • ⚠ 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 yudai/gotty repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/yudai/gotty.

What it runs against: a local clone of yudai/gotty — 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 yudai/gotty | 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 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 676 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>yudai/gotty</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of yudai/gotty. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/yudai/gotty.git
#   cd gotty
#
# 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 yudai/gotty and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "yudai/gotty(\\.git)?\\b" \\
  && ok "origin remote is yudai/gotty" \\
  || miss "origin remote is not yudai/gotty (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"

# 4. Critical files exist
test -f "main.go" \\
  && ok "main.go" \\
  || miss "missing critical file: main.go"
test -f "server/server.go" \\
  && ok "server/server.go" \\
  || miss "missing critical file: server/server.go"
test -f "backend/localcommand/local_command.go" \\
  && ok "backend/localcommand/local_command.go" \\
  || miss "missing critical file: backend/localcommand/local_command.go"
test -f "js/src/webtty.ts" \\
  && ok "js/src/webtty.ts" \\
  || miss "missing critical file: js/src/webtty.ts"
test -f "server/handlers.go" \\
  && ok "server/handlers.go" \\
  || miss "missing critical file: server/handlers.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 676 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~646d)"
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/yudai/gotty"
  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

GoTTY is a Go-based CLI tool that wraps any terminal command and exposes it as a real-time web application via WebSocket. Users run gotty top or gotty bash and get an interactive terminal in their browser at localhost:8080, using xterm.js on the frontend to render TTY output and hterm for additional terminal emulation features. Standard CLI tool structure: main.go is the entry point, backend/localcommand/ handles spawning and managing the subprocess and PTY, server/ serves HTTP/WebSocket endpoints, js/src/ contains the TypeScript frontend (main.ts orchestrates hterm/xterm rendering, websocket.ts handles the WebSocket protocol), and resources/ holds static HTML/CSS.

👥Who it's for

System administrators and DevOps engineers who need to share live terminal sessions with team members remotely without SSH access, and developers who want to turn command-line tools (monitoring dashboards, databases CLIs, build processes) into shareable web interfaces without additional code.

🌱Maturity & risk

Moderately mature but aging: the project has a stable release pattern and MIT license, but the last visible commit activity appears dated relative to modern Go/TypeScript standards (Godeps dependency management is legacy). Wercker CI is configured but the TypeScript tooling (webpack 2, TypeScript 2.3) is 5+ years old. No comprehensive test suite is visible in the file structure.

Single maintainer (yudai) with outdated dependency tooling (Godeps instead of Go modules, webpack 2 instead of modern bundlers). The xterm.js dependency is pinned to v2.7.0 (released ~2017), and libapps is forked from a third party (github:yudai/libapps#release-hterm-1.70), raising security patch concerns. No visible GitHub Actions or modern CI. Breaking changes in Go or JavaScript ecosystems are unlikely to be addressed quickly.

Active areas of work

No active development is visible; the repository appears dormant. The file structure shows it's frozen at a functional state with TypeScript/webpack 2 and Go 1.9+ requirement, but no recent pull requests or issue milestones are evident from the provided data.

🚀Get running

git clone https://github.com/yudai/gotty.git
cd gotty
make build
# or with go get: go get github.com/yudai/gotty
./gotty top  # Replace 'top' with any command

Daily commands:

# Development:
make dev  # Assumes Makefile has dev target
# or manually:
go run main.go -p 8080 -- bash

# Production binary (after build):
./gotty --address 0.0.0.0 --port 8080 --permit-write -- top

🗺️Map of the codebase

  • main.go — Entry point for the GoTTY application; defines CLI flags and orchestrates server startup
  • server/server.go — Core HTTP server and WebSocket handler; manages client connections and session lifecycle
  • backend/localcommand/local_command.go — Implements terminal command execution and PTY management; bridges local shell to web interface
  • js/src/webtty.ts — Client-side WebSocket protocol handler; manages bidirectional terminal communication
  • server/handlers.go — HTTP request handlers for authentication, WebSocket upgrade, and asset serving
  • js/src/main.ts — Frontend initialization; wires xterm display to WebSocket terminal backend
  • vendor/github.com/gorilla/websocket — WebSocket dependency for real-time bidirectional communication between browser and server

🧩Components & responsibilities

  • main.go (Go codegangsta/cli) — Parse CLI flags, instantiate server options, start HTTP listener
    • Failure mode: Application refuses to start; reports flag parsing or port binding errors
  • server/server.go (Go net/http, Gorilla WebSocket) — Register HTTP routes, accept connections, dispatch to handlers
    • Failure mode: Port already in use, or handler panic crashes entire server
  • backend/localcommand/local_command.go (Go os/exec, syscall (PTY ioctls)) — Allocate PTY, spawn shell process, manage Read/Write I/O streams
    • Failure mode: PTY allocation fails (no ptmx), shell crash closes connection, OOM from large output
  • js/src/webtty.ts (TypeScript, Binary protocol (custom wire format)) — Encode/decode terminal messages (input, output, resize), manage protocol state
    • Failure mode: Malformed message causes parsing error, connection drops silently
  • js/src/xterm.ts (x) — Render terminal output, capture user input, handle ANSI escape sequences

🛠️How to make changes

Add a new authentication method

  1. Define auth logic in server/handlers.go as a new middleware or handler function (server/handlers.go)
  2. Add auth options to server/options.go for configuration (server/options.go)
  3. Call auth middleware from server/server.go in the router setup (server/server.go)

Support a new terminal backend (e.g., SSH, container exec)

  1. Create backend/mybackend/my_backend.go implementing the backend interface (backend/localcommand/local_command.go)
  2. Add factory logic in backend/mybackend/factory.go with options handling (backend/localcommand/factory.go)
  3. Wire backend selection in main.go via CLI flags and server.go (main.go)

Add a new UI feature (keybinding, resize handler, theme)

  1. Implement feature logic in js/src/main.ts or create a new module in js/src/ (js/src/main.ts)
  2. If it requires server communication, extend js/src/webtty.ts protocol (js/src/webtty.ts)
  3. Add styling in resources/index.css or resources/xterm_customize.css (resources/index.css)
  4. Run npm install && npm run build in js/ to bundle changes (js/webpack.config.js)

🔧Why these technologies

  • Go + net/http — Cross-platform compilation, minimal dependencies, built-in HTTP server suitable for distributing as single binary
  • WebSocket (gorilla/websocket) — Enables low-latency bidirectional communication; essential for real-time terminal keystroke and output streaming
  • xterm.js (frontend) — Mature, battle-tested terminal emulator; handles ANSI escapes, mouse events, and wide character support
  • TypeScript + Webpack — Type safety for complex WebSocket protocol; bundling ensures assets embed cleanly into Go binary
  • PTY (Unix pseudo-terminal) — Allows arbitrary CLI tools to believe they're connected to a real terminal, preserving colors, pagination, interactivity

⚖️Trade-offs already made

  • Single server instance (no clustering)

    • Why: Simplicity; avoids distributed session management complexity
    • Consequence: Horizontal scaling requires sticky sessions or external load balancer state
  • Embedded static assets (no separate CDN)

    • Why: Minimal deployment friction; single binary includes UI
    • Consequence: Browser caches entire ~100KB bundle per version; no incremental updates
  • No built-in user/tenant isolation in core

    • Why: Flexibility for different deployment models (single user, reverse proxy auth, etc.)
    • Consequence: Production use requires external auth (reverse proxy, OAuth middleware)
  • Command spawned as direct child (not containerized)

    • Why: Works with any CLI tool out-of-the-box
    • Consequence: Limited resource isolation; runaway processes consume server CPU/RAM

🚫Non-goals (don't propose these)

  • Does not provide built-in authentication or user management beyond basic header parsing
  • Does not handle persistence, logging, or session replay (stateless per client)
  • Does not cluster or distribute across multiple machines in core
  • Does not provide true multi-user collaboration (each connection is independent)
  • Does not isolate or sandbox shell processes; assumes trusted commands

🪤Traps & gotchas

PTY allocation: The backend/localcommand/ relies on syscall-level PTY setup (Unix-only; Windows is unsupported despite Go's cross-platform pretense). Subprocess zombie processes: If the server crashes mid-request, child processes may not be reaped. WebSocket framing: The init_message.go format is non-standard; check the schema if adding new clients. TypeScript compilation: The js/ build requires Node.js and webpack 2; modern npm may fail due to old peer dependencies—use npm ci or pin Node version. Credential format: --credential user:pass is plaintext in the CLI command; no documented secure alternative (env var GOTTY_CREDENTIAL is plaintext too). TLS default paths: Certs default to ~/.gotty.crt and ~/.gotty.key; must be pre-generated (no auto-generation).

🏗️Architecture

💡Concepts to learn

  • Pseudoterminal (PTY) — GoTTY's entire value proposition depends on allocating a PTY to the subprocess and bridging it bidirectionally over WebSocket; understanding POSIX PTY semantics (master/slave, signal handling, window resizing) is essential to debug terminal-related bugs
  • WebSocket Protocol — GoTTY uses WebSocket for real-time, bidirectional TTY I/O; understanding frame types, message serialization in init_message.go, and reconnection semantics is critical for debugging frontend-backend communication
  • Terminal Emulation (xterm/hterm) — The frontend uses two terminal emulators (xterm.js and hterm); knowing the difference (VT100/VT102 escape sequence support, performance trade-offs) helps choose the right one and debug rendering issues
  • HTTP Upgrade and Connection Hijacking — GoTTY upgrades HTTP connections to WebSocket in server/handlers.go; understanding the Upgrade header, 101 Switching Protocols response, and socket-level I/O is needed to extend or debug the server
  • Process Signal Handling — GoTTY must forward signals (SIGTERM, SIGWINCH for window resize) from the WebSocket client to the subprocess; Go's signal.Notify and syscall patterns are non-obvious and critical to graceful shutdown and responsive resizing
  • TypeScript Webpack Bundling — The js/ source is compiled and bundled into js/dist/gotty-bundle.js; understanding webpack 2 loaders (ts-loader), entry points, and the dev/prod split is required to modify or upgrade the frontend build
  • HTTP Basic Authentication — GoTTY supports optional HTTP Basic Auth via the --credential flag; understanding the Base64-encoded Authorization header and stateless auth validation in the server is needed to extend or audit security
  • ttyd/ttyd — Direct competitor: C-based terminal-over-HTTP tool with similar feature set (TTY sharing, auth, TLS) but lighter footprint and more active maintenance
  • jerch/xterm-pty — Companion project: xterm.js with Node.js PTY integration; useful for understanding modern terminal emulation beyond GoTTY's aging xterm v2.7.0
  • yudai/windy — Related by author: a different approach to terminal sharing using libapps/hterm, may inform architectural decisions
  • libapps/libapps — Upstream dependency: hterm source repository (GoTTY forks release-hterm-1.70); needed to understand terminal emulation layer and potential security patches
  • xtermjs/xterm.js — Upstream dependency (v2.7.0): the frontend terminal renderer; major version upgrades would require significant testing

🪄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 unit tests for backend/localcommand package

The backend/localcommand directory contains critical logic for spawning and managing local commands (factory.go, local_command.go, options.go) but has no corresponding test files. This is a core component that deserves test coverage to catch regressions in command execution, option parsing, and error handling across different platforms.

  • [ ] Create backend/localcommand/local_command_test.go with tests for command spawning and I/O handling
  • [ ] Create backend/localcommand/factory_test.go with tests for command factory creation logic
  • [ ] Create backend/localcommand/options_test.go with tests for option parsing and validation
  • [ ] Run tests with 'go test ./backend/localcommand' to verify coverage
  • [ ] Consider platform-specific tests (Windows vs Unix) given the nature of local command execution

Add TypeScript tests for js/src modules (especially webtty.ts and websocket.ts)

The frontend TypeScript code in js/src/ handles critical WebSocket communication and terminal emulation logic (webtty.ts, websocket.ts, main.ts) but has no test suite configured. The package.json already has webpack and ts-loader configured but no test runner. Adding Jest or Mocha tests would catch bugs in terminal state management and WebSocket message handling.

  • [ ] Install test dependencies (jest, ts-jest, or mocha + typescript) in js/package.json
  • [ ] Create js/src/webtty.test.ts with tests for terminal state, resize handling, and data transmission
  • [ ] Create js/src/websocket.test.ts with tests for connection handling, message framing, and error recovery
  • [ ] Create jest.config.js or mocha configuration for TypeScript compilation
  • [ ] Add test script to js/package.json and document in CONTRIBUTING.md

Add GitHub Actions CI workflow for multi-platform Go builds and tests

The repo currently uses Wercker for CI (referenced in README), but Wercker is deprecated. The Makefile and Go code suggest the project supports multiple platforms. Adding a GitHub Actions workflow would provide native, maintainable CI that tests Go compilation on Linux, macOS, and Windows, runs the existing test suite, and validates the JavaScript build.

  • [ ] Create .github/workflows/go-build-test.yml with matrix strategy for ubuntu-latest, macos-latest, windows-latest
  • [ ] Include steps to run 'go test ./...' for all packages including backend/localcommand
  • [ ] Include steps to build JavaScript: 'cd js && npm install && npm run build' (or equivalent from Makefile)
  • [ ] Include step to build the final binary using Make or 'go build'
  • [ ] Update README.md to replace Wercker badge with GitHub Actions badge

🌿Good first issues

  • Add comprehensive unit tests for backend/localcommand/local_command.go (PTY lifecycle, signal handling). Currently no test files visible in the file list, making this area error-prone.
  • Modernize TypeScript tooling: upgrade webpack from v2 to v4+, TypeScript from v2.3 to v4+, and xterm.js from v2.7.0 to v4+. Includes updating js/webpack.config.js, js/tsconfig.json, and js/package.json with new compiler options.
  • Add documentation for the WebSocket message protocol in docs/ (specify the JSON schema for init_message.go payloads, input/output frame format, error responses). Currently only code serves as documentation, making client implementations difficult.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • a080c85 — Release v2.0.0-alpha.3 (yudai)
  • 8df0bf4 — Merge pull request #179 from badoo/hterm_deactivate_fix_pull (yudai)
  • b4728f6 — set deactivated terminal handlers to empty functions instead of null (DenKoren)
  • 9ac120a — Support local webpack (yudai)
  • 0bb62e0 — Mention minimum go compiler version (yudai)
  • 513b3a5 — Do not compile asset by default (yudai)
  • 79e1328 — Update README.md (yudai)
  • 2c50c43 — Release v2.0.0-alpha.2 (yudai)
  • 6ab3093 — Pickup random port when port option is 0 (yudai)
  • b2c2db0 — Move responsibility to decode output encoding to terminal implementation (yudai)

🔒Security observations

  • High · Outdated TypeScript Dependencies — js/package.json - devDependencies.typescript. The package.json specifies TypeScript 2.3.2 (released in 2017), which is severely outdated and contains multiple known security vulnerabilities and bugs. This version is no longer supported and lacks security patches. Fix: Update to the latest stable TypeScript version (4.x or 5.x). Run 'npm update typescript' and test thoroughly.
  • High · Outdated Webpack and Build Tools — js/package.json - devDependencies (webpack, ts-loader, uglifyjs-webpack-plugin). Webpack 2.5.1 (2017), ts-loader 2.0.3 (2017), and uglifyjs-webpack-plugin 1.0.0-beta.2 are all severely outdated. These contain known vulnerabilities and lack modern security features. The beta version of uglifyjs indicates incomplete/untested code. Fix: Update to Webpack 5.x+, ts-loader 9.x+, and use TerserPlugin instead of uglifyjs. Review and update all build tooling.
  • High · Outdated XTerm Dependency — js/package.json - dependencies.xterm. XTerm 2.7.0 is outdated (released 2017) and likely contains known vulnerabilities. Modern versions include critical security fixes for terminal emulation and input handling. Fix: Update to the latest stable version of xterm (4.x or 5.x). Review changelog for security fixes between current and target version.
  • Medium · Potential Terminal Injection via WebSocket — server/ws_wrapper.go, js/src/websocket.ts, server/handlers.go. The application shares terminals via WebSocket. File 'server/ws_wrapper.go' and WebSocket handling in TypeScript files suggest bidirectional command/input transmission. Without proper input validation/sanitization, this could allow command injection attacks. Fix: Implement strict input validation and sanitization for all WebSocket messages. Validate that terminal input doesn't contain shell metacharacters or escape sequences that could alter command execution. Use parameterized execution where possible.
  • Medium · Missing Authentication/Authorization Framework — server/, main.go. No visible authentication mechanism in the file structure. The README mentions sharing terminals as web applications, but there's no evidence of user authentication, authorization, or access control in server/handlers.go or server/options.go. Fix: Implement authentication (e.g., JWT, OAuth2) and authorization mechanisms. Require credentials before granting terminal access. Support role-based access control.
  • Medium · Potential XSS via Terminal Output Rendering — js/src/xterm.ts, js/src/hterm.ts, resources/index.html. XTerm and hterm render terminal output as HTML. If malicious terminal output contains HTML/JavaScript, it could execute in the browser context, especially if rendered with insufficient sanitization in the web frontend. Fix: Ensure XTerm and hterm are configured to safely escape HTML content. Validate that terminal output is treated as plain text. Implement Content Security Policy (CSP) headers to restrict script execution.
  • Medium · Missing Security Headers — server/middleware.go, server/handlers.go. No visible implementation of security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options) in the server code. This leaves the web interface vulnerable to clickjacking, MIME-type sniffing, and other browser-based attacks. Fix: Implement security middleware that adds: Content-Security-Policy, Strict-Transport-Security, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, X-XSS-Protection headers.
  • Medium · Potential Arbitrary Command Execution — backend/localcommand/local_command.go, backend/localcommand/factory.go. The backend spawns local commands via 'backend/localcommand/local_command.go'. Without strict restrictions on what commands can be executed, users could execute arbitrary system commands with the privileges of the GoTTY process. Fix: Implement a whitelist of allowed commands. Validate command arguments

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 · yudai/gotty — RepoPilot