← skcode home

skcode

The interactive, human-facing coding client of the SKWorld stack - where you code by hand, backed by the skharness engine.

🧭

Status, honestly. The read-only remote session plane ships today (skcode-hostd, P0) as a distributed feature across three repos. There is no standalone skcode package yet, and interactive Code + Dispatch is on the roadmap. This page states which is which.

skcode is one of three names in the SKWorld coding stack, and the boundary between them is the whole point. skcode is a thin client of the skharness engine, not a second engine. When it dispatches an autonomous build, it calls the engine - it never re-implements the assess → build → grade → gate → merge loop. That single rule (ADR-0001) is what keeps the system from building the autocode loop twice, and keeps a coding surface from ever loading the operator's whole personal graph.

One engine, two front doors

Three names, one clean layering. Personal context flows down as a narrow task brief; it never flows up into a build sandbox.

LayerRepoResponsibilityKnows you?
Engine skharness The autocode loop: assess → build → grade → twin-gate (score==5 + CI + coverage) → finalize/merge. Input: a repo + a task. Output: a reviewed PR. No
Operator OS skos Single pane of glass: GTD, memory, coord board, ITIL, scheduler, the AI-operator seat. Decides what and why to build, tracks the work. Yes (fully)
Coding client skcode Interactive, human-facing coding surface. Invokes skharness for heavy lifts. A thin client, not a second engine. Minimally (session-scoped)
The one-line rule: skos knows you. skharness builds code. skcode is where you code by hand. Personal context enters a build only as a distilled task brief, never as the whole graph.

Architecture

The two planes and the trust boundary between them. skcode is the interactive front door on the operator plane (alongside skos): both drive the same engine, but only ever hand it a narrow brief.

flowchart TD subgraph operator["Operator plane · knows you"] SKOS["🧠 skos
operator OS · GTD · memory · coord
ITIL · scheduler · operator-seat"]:::os SKCODE["⌨️ skcode
interactive coding client
session-scoped context"]:::client end subgraph engine["Engine plane · knows only repo + task"] SKH["⚙️ skharness
autocode loop
assess→build→grade→gate→merge"]:::eng SB["📦 sandbox
repo + task brief + grounding
NO personal context"]:::sandbox end SKOS -- "narrow task brief (what/why)" --> SKH SKCODE -- "build this / fix this" --> SKH SKH -- "runs each task in" --> SB SB -- "reviewed PR" --> SKH SKH -- "PR + verdict" --> SKOS SKH -- "PR + verdict" --> SKCODE SKOS -. "tracks in coord/GTD" .-> SKOS classDef os fill:#1e3a5f,stroke:#4a90d9,color:#fff classDef client fill:#3a2f5f,stroke:#9a7fd9,color:#fff classDef eng fill:#1f5f3a,stroke:#4ad98f,color:#fff classDef sandbox fill:#5f4a1f,stroke:#d9a94a,color:#fff

skcode is the interactive front door in this diagram (the purple node). It sends "build this / fix this" to skharness exactly as skos sends its distilled brief - same engine, driven by a human.

The autocode workflow (where you are in the system)

The end-to-end path when a build is dispatched. The final note is the key one for this site: skcode uses the same engine path, just driven by a human interactively.

sequenceDiagram participant U as Operator (you) participant OS as skos (operator OS) participant H as skharness (engine) participant S as sandbox U->>OS: capture intent (a card on the coord board) OS->>OS: triage + ground the card (repo facts, coherence gate) OS->>H: dispatch task brief (repo + acceptance, NOT your graph) H->>S: assess → build (Ralph loop) in an isolated sandbox S-->>H: diff H->>H: grade 1-5 → twin-gate (score==5 + CI + coverage) H-->>OS: reviewed PR + verdict OS->>U: report (tracked in coord/GTD) Note over U,OS: skcode uses the SAME engine path, just driven by a human interactively

When skcode's interactive Dispatch lands (P2), the operator drives this same sequence by hand: the gated dispatch is a thin call into skharness.autocode.ratify, never a re-forked engine.

The two-plane Harness

By deliberate design, skcode's host daemon is skharness, promoted and hardened - not a new repo. skharness grew from a single-purpose engine into a two-plane Harness that speaks one contract:

  • Task plane - the autocode engine. A repo + a brief become a reviewed PR, run in an isolated Docker sandbox. session_plane = False.
  • Session plane - skcode. Remote control over your live agent sessions over a PTY + tmux backing. session_plane = True, headless_api = "pty".

These are two separate Harness classes on the same ABC, so flipping on the session plane never touches the frozen autocode adapter. The engine is untouched; skcode is additive.

What ships today

skcode is real, delivered as a distributed feature. The code lives in three repos that already ship:

PieceLives inStatusWhat it does
skcode-hostd (host daemon, session plane) skharness SHIPPED · P0 Read-only MVP. Entry skharness.serve:main, binds a Tailscale IP only on port 9394, capauth-gated (audience skcode), systemd unit skcode-hostd.service, 36 tests. Three data routes plus a live WS stream; zero write surface (POST/DELETE → 405).
Flutter client pane skchat-app SHIPPED · Grade B A "Code" pane (lib/features/skcode/) embeds the hostd web client same-origin over the 443 funnel. Renders the session list + live transcript; stays gated until the device is paired (shown as a hint).
Operator adapter skcapstone SHIPPED Atlas (the AI-operator seat) watches and steers hostd: probe health, archive a stale session, restart the daemon, and pause dispatch once P2 exists (operator_seat/skcode_adapter.py).
There is no standalone skcode package or repo yet. The daemon is skharness, the client is skchat-app, the operator adapter is skcapstone. That distribution is deliberate: the daemon is skharness promoted, not a fork.

The P0 surface (read-only, by construction)

GET  /api/v1/hosts/self            host id, harnesses, health
GET  /api/v1/sessions              live sessions (registry + harness merge)
GET  /api/v1/sessions/{sid}        descriptor + status + last message
WS   /api/v1/sessions/{sid}/stream typed SessionEvent stream (?token=)
GET  /  ·  /app                    static, inert, unauthenticated client

# no /inject, no /dispatch, no spawn/kill. POST/DELETE -> 405. By design.

The phase ladder

Each phase is standalone-shippable and security-reviewable on its own. The highest-risk surface - spawning a session on your machine - does not exist until pairing and authorization land under it.

PhaseDeliverableGate / prereq
P0 · DONE Read-only Code: list + stream, capauth-gated, one device, sandbox scope. Zero write authority. skharness P0 (exists) + a paired device.
P1 · NEXT Input injection: text + voice (Whisper) + file; manual/auto toggle; per-session model switch via the shared resolver; rename / archive / share. Unified resolver + dynamic catalog landed · authz.decide interface frozen.
P2 · Dispatch Code + Dispatch: spawn & steer a new session (harness, repo, branch, profile, prompt). Gated dispatch calls skharness.autocode.ratify - a thin call, never a re-forked engine. Mandatory RCE guards. capauth.pairing (M2) live + authz.decide (M3) + repo allowlist.
P3 · Fleet Pi + opencode adapters behind the seam; harness switch = fork/re-spawn; roll hostd fleet-wide; cross-host session merge; skcoord card store. Pi spike + fleet install · skcoord extraction.
P4 · Off-tailnet + shell skcomms stream_channel for cellular / off-tailnet attach (reusing the skchat coturn relay); skcode as a Grade A native module in the SKWorld shell. Shell phase + skcomms stream seam.

Security posture

skcode is, ultimately, remote code execution on your own hosts, so the design is security-first from P0:

  • Tailscale-only binding. The daemon refuses 0.0.0.0, ::, and any public Funnel port. It binds a tailnet IP or it does not start.
  • capauth-gated, fail-closed. Every HTTP route needs a valid capauth bearer scoped to audience skcode; the WS stream checks the token before it accepts. A bad, expired, wrong-audience, or unscoped token is rejected.
  • Read-only P0. The write surface (inject, spawn, kill, dispatch) does not exist yet - a test proves POST/DELETE return 405 and there is no /inject or /dispatch route. The riskiest capability is added last, behind pairing + authorization.
  • Least-privilege by construction. A dispatched sandbox session gets no SKAGENT, no sk* MCP stack, and no memory - enforced by not wiring the modules, not by asking nicely.
  • RCE guards (P2). argv-list subprocess only (never a shell string), per-host repo allowlist, [A-Za-z0-9_-]+ name charset, git-worktree isolation, prompt-as-data.
  • Audited & revocable. Every mutating action emits an audit obligation; short-lived tokens make device revocation effectively immediate.

References


These docs are a static, self-contained page - skcode is a distributed feature with no single source repo yet, so unlike the skos docs viewer there is no GitHub folder to render live. When skcode is packaged, this page will point at its repo. Everything above is grounded in ADR-0001 and the skcode design spec cited under References.