MoonshotAI / MoonshotAI/kimi-code

Integrated RemoteSSH

Open
#3,443 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

What feature would you like to see?

Summary

Kimi Code currently only runs against local working directories. For users who develop on remote Linux hosts over SSH (dev servers, GPU boxes), the agent's file tools, Bash, plan files, and session state all assume a local filesystem, so there is no way to point a session at a remote workspace. Current bypass is to install kimi-code-cli on remote servers which exposes private api_keys&login_status and does not work at all when remote servers have limited internet access (which is common).

Proposal: support ssh://[user@]host[:port]/abs/path as a first-class workspace spec across the CLI/TUI, SDK, and server, so a session executes against a remote host while the client stays local.

Key design choices

flowchart LR
  subgraph local["Local machine — everything except tool execution"]
    ui["CLI / TUI / Web UI"]
    eng["Agent engine (agent-core-v2)<br/>sessions · transcripts · plans"]
    llm["LLM API calls<br/>keys never leave this machine"]
    ui --- eng --- llm
  end
  subgraph remote["Remote host — no internet access required"]
    rts["RTS (Remote Tool Server)<br/>~/.kimi-code/remote-agent/rts-bin"]
    fs["workspace filesystem<br/>Read · Write · Edit · Glob · Grep"]
    sh["bash & spawned processes"]
    rts --> fs
    rts --> sh
  end
  local -- "single ssh connection<br/>stdio = one multiplexed framed-RPC pipe<br/>the RTS itself is uploaded through this pipe" --> remote

Remote-as-VM execution model ("shell-vm"). The remote host is treated like a freshly provisioned VM: the design assumes nothing about what is installed on it, what distro it runs, or whether it has any network access at all. On first connect, the CLI deploys a self-contained Remote Tool Server (RTS) to ~/.kimi-code/remote-agent/ on the remote host, in one of two flavors: a prebuilt Node SEA single-executable (rts-bin, so the remote needs literally nothing but a POSIX shell and bash), or — as a fallback — a single-file Node.js program (rts.js) when the remote happens to have Node ≥ 20. The RTS is the only thing that ever runs remotely besides the user's own commands: it serves filesystem operations (Read/Write/Edit/Glob/Grep, with a built-in grep fallback when rg is absent) and process spawning for Bash. Version skew is handled by automatic redeploy on version mismatch, so upgrades need no manual cleanup.

Everything goes through plain ssh pipes — the remote needs no internet access. All connectivity is the system OpenSSH client; there is no listener, no port, and no daemon protocol of our own on the remote side. Concretely:

  • Deploy: the RTS bundle/binary is uploaded through the ssh connection itself (ssh host 'cat > rts-bin.tmp && chmod 755 && mv' — tmp file + atomic rename, so a dropped connection never leaves a half-written live artifact). Nothing is ever downloaded on the remote — no package manager, no outbound fetch — so a fully air-gapped or egress-firewalled host works as long as you can ssh into it.
  • Steady state: one long-lived ssh host rts-bin process whose stdin/stdout forms a single multiplexed framed-RPC pipe carrying every file op and process spawn of the workspace. One ssh connection per workspace, nothing else.
  • Auth and network features come from the user's own OpenSSH setup: Host aliases, ProxyJump/ProxyCommand, ssh-agent, ControlMaster sharing, and known_hosts verification all apply unchanged. The CLI always runs ssh with BatchMode=yes (no interactive prompts), and remote command strings are fixed constants with no user-controlled interpolation.
  • Failure semantics: if the connection drops, the RTS dies with the pipe and kills its process groups; in-flight commands are never silently retried, and the workspace stays blocked behind an explicit user resume (/resume-remote or the REST resume route).

Agent API traffic never leaves the local machine. The agent engine, session storage, transcripts, and all LLM API calls run locally; the remote side only executes tool calls (file operations and processes). No API keys, model traffic, or session state are ever sent to or stored on the remote host. The one deliberate exception is execution-side scratch state — plan documents and stateful-shell snapshots under ~/.kimi-code/remote-sessions/<sessionId>/ — which must be visible to the remote Write/Bash tools to be useful; it contains no credentials and is garbage-collected when the session is closed or archived.

Reference implementation

A working implementation is available on this branch, rebased onto recent main (218 files, ~16.7k insertions, with tests, docs, and changesets):

What it contains:

  • New @moonshot-ai/remote-ssh package — a framed RPC protocol over an ssh pipe (fs ops, glob, process spawn/mux, server facts), OpenSSH ~/.ssh/config alias resolution (case-sensitive Host matching like OpenSSH), and a self-test/bundle smoke suite.
  • agent-core-v2 — ssh remote workspaces behind the runtime provider seam; stateful Bash mode with remote execution-side support; plan files kept on the execution side for ssh workspaces; shadow mode with cross-workspace session fork; garbage collection of remote session homes on close/archive; Edit matching tolerant of Read-view artifacts (shown \r, one extra trailing newline, leftover line-number prefixes).
  • kaos — a resuming-based stateful shell core (shell state survives across Bash calls) with benchmarks and docs.
  • kap-server — ssh workspace registration via POST /workspaces without local path checks, plus connection-state and resume routes.
  • node-sdk — exposes ssh connection state and resume; session file listing/search routed through the workspace filesystem.
  • apps/kimi-code TUIssh:// workdir support end to end: /session new ssh://host/path with recent-workdir completion, remote-aware footer cwd display, remote file mentions, and resume of remote sessions.
  • Docs & changesetsssh-sessions and stateful-bash guides in en/zh; one changeset per user-visible change.
  • This branch also implements a shadow mode in which remote agents can temporarily access local device to handle specific jobs.

Since external feature PRs are not accepted, I'm opening this issue for discussion first. Happy to split the branch into reviewable pieces, adjust the design (e.g. protocol framing, scope placement of the new services), or hand it over entirely — whichever is most useful to maintainers.

Additional information

The proposed feature has been carefully tested by my daily usage for about one month.
Also the branch passes all of the regression tests the main branch does, plus a bunch of remote specific tests.
These features work better with a modified webui though.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the referenced branch and its diff against main, then trace the runtime provider seam in agent-core-v2 and the workspace registration paths in kap-server. Read the remote-ssh package tests and existing regression tests first. Done would require an agreed, reviewable scope and integrated tests for SSH workspaces across the CLI, server, SDK, and remote tool execution.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
api, cli, distributed-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.