Skip to content

Marukohe/Gate

Repository files navigation

Gate

English | 中文

Gate opens a portal to AI coding CLIs (Claude Code, OpenAI Codex) on remote servers — code from anywhere, on any device.

Waiting in line, on the couch, on the train — pull out your phone and pick up right where you left off. Gate bridges your browser to CLI sessions over SSH, so your coding environment is always one tap away.

Browser (React) ◄──WebSocket──► Node.js Backend ◄──SSH──► Remote Server (Claude / Codex CLI)

Example

Planning mode
Planning mode
Interactive questions
Interactive questions
Chat with Claude
Chat with Claude
Command execution
Command execution

Key Features

  • Code from anywhere — Start on your desktop, pick up on your phone. Sessions persist across devices via SSH and CLI resume.
  • Attach to existing sessions — Already running a CLI in a terminal? Gate finds its transcript and resumes right where you left off.
  • Clean chat UI — Terminal output parsed into markdown messages, collapsible tool cards, syntax-highlighted code blocks, and scrollable tables.
  • Multi-server, multi-session — Manage several remote servers with multiple sessions each. Swipe or tap to switch.
  • Live plan tracking — Checklists auto-extracted from Claude's output into a side panel. Check off steps, edit plans, send them back for execution.
  • Transcript sync — Catch up on work done outside Gate by syncing the transcript from the remote CLI session.
  • Responsive everywhere — Three-column desktop, drawers on tablet, bottom sheets and swipe gestures on mobile. Notch-safe.
  • Multi-CLI support — Works with Claude Code and OpenAI Codex CLI. Switch between CLI tools within a session with automatic context sync. Provider sessions are preserved — switching back resumes your previous conversation, not a new one.
  • Switch Chat — Start a fresh CLI conversation or resume a previous one within the same session. Messages are scoped per CLI session so switching gives you a clean view.
  • Persistent history — SQLite-backed chat history survives reconnects and server restarts.

Quick Start

Prerequisites

  • Node.js >= 20
  • A remote server with SSH access and at least one of:
    • Claude Code CLI — run claude once on the server to complete authentication
    • OpenAI Codex CLI — run codex once on the server to complete authentication

Install via npm (recommended)

npm i -g @marukohe/gate
gate

Open http://localhost:3030 in your browser. Data is stored in ~/.gate/.

CLI options:

gate --port 8080          # custom port (default: 3030)
gate --host 127.0.0.1     # bind address (default: 0.0.0.0)
gate --data-dir /my/data  # custom data directory (default: ~/.gate)

Add a Server

Open the app → click Add Server → fill in your SSH credentials (password or private key). Set a default working directory for new sessions.

Development

Setup

git clone https://github.com/Marukohe/Gate.git gate
cd gate
npm install
npm run dev

The client runs on http://localhost:5173 (proxies API/WS to the server on port 3030).

Scripts

Command Description
npm run dev Start client + server in parallel
npm run dev:client Vite dev server only (port 5173)
npm run dev:server Express + WS server only (port 3030)
npm run build Build both client and server
npm run start Start production server
cd server && npx vitest run Run server tests
cd server && npx tsc --noEmit Type-check server

Project Structure

gate/
├── client/                      # React frontend
│   └── src/
│       ├── components/
│       │   ├── chat/            # ChatView, SessionBar, MessageBubble, ToolActivityBlock,
│       │   │                    # ChatInput, ProviderSwitcher, ResumeChatDialog, BranchSwitcher
│       │   ├── layout/          # AppShell, Sidebar, TopBar
│       │   ├── plan/            # PlanPanel, PlanStepItem
│       │   ├── plan-mode/       # PlanModeOverlay, PlanModeQuestion, PlanModeThinking
│       │   ├── server/          # ServerDialog
│       │   └── ui/              # shadcn/ui components
│       ├── hooks/               # use-websocket, use-swipe
│       ├── stores/              # Zustand stores (server, session, chat, plan, plan-mode, ui)
│       └── lib/                 # Utilities (plan-parser, server-utils, notification)
├── server/                      # Node.js backend
│   └── src/
│       ├── index.ts             # Express entry point
│       ├── db.ts                # SQLite (servers, sessions, messages)
│       ├── ssh-manager.ts       # SSH connection pool + CLI channel management
│       ├── ssh-browse.ts        # Remote directory browsing
│       ├── ws-handler.ts        # WebSocket server
│       ├── routes/              # REST API
│       ├── providers/
│       │   ├── types.ts         # CLIProvider interface, OutputParser, ParsedMessage
│       │   ├── registry.ts      # Provider registration and lookup
│       │   ├── claude/          # Claude Code CLI provider
│       │   └── codex/           # OpenAI Codex CLI provider
│       └── __tests__/           # Vitest test suites
└── docs/                        # Design documents

Tech Stack

Client: Vite · React 19 · TypeScript · Tailwind CSS · shadcn/ui · Zustand

Server: Express 5 · ws · ssh2 · better-sqlite3 · TypeScript

Testing: Vitest

WebSocket Protocol

Client → Server:

{ "type": "connect" | "input" | "disconnect", "serverId": "...", "sessionId": "...", "text": "..." }
{ "type": "switch-provider", "serverId": "...", "sessionId": "...", "provider": "codex" }
{ "type": "reset-conversation" | "resume-cli-session", "serverId": "...", "sessionId": "...", "claudeSessionId": "..." }
{ "type": "list-cli-sessions", "serverId": "...", "workingDir": "...", "provider": "claude" }

Server → Client:

{ "type": "message" | "status" | "history" | "sessions" | "git-info", "serverId": "...", ... }
{ "type": "cli-sessions", "serverId": "...", "sessions": ["..."] }

Responsive Layout

Breakpoint Layout
Desktop (≥1024px) Sidebar + Chat + Plan panel (3-column)
Tablet (768–1023px) Chat fullwidth, sidebar/plan as drawers
Mobile (<768px) Fullscreen chat, bottom sheet for servers, swipe to switch sessions

Why "Gate"?

Named after Steins;Gate — the anime where messages travel through time to change the worldline. Here, your messages travel through SSH to reach Claude on a remote server, opening a gate between any device and your coding environment.

License

MIT

About

Gate connects mobile and remote Claude/Codex cli.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages