A cross-platform chat application built with Kotlin Multiplatform. It provides a web app, an Android APK, and optional desktop clients, with a Kotlin backend, Weaviate for vector search, and OpenAI-compatible AI APIs.
- Backend: Kotlin (Ktor), serves API and static web assets. Reads config from project-root
.env. - Frontend: Kotlin/JS WebApp (production build is copied to
backend/staticand served there). - Android: Kotlin Multiplatform Android app; APK can be built and served for download.
- Vector store: Weaviate (run via Docker by
silk.sh). Used for context and file search. - AI: Any OpenAI-compatible API; configure
API_BASE_URL,OPENAI_API_KEY, andAI_MODELin.env. - Workflow: Named, persistent Claude Code agent sessions. Each workflow creates a dedicated chat room with CC mode always active — no need to type
/cc.
Todo is treated as a long-term core module. Any todo-related feature must follow:
- Update/align roadmap first:
docs/todo-roadmap.md - Then implement code changes.
- Write back status/changelog to roadmap after implementation.
Persistent Cursor rule:
.cursor/rules/todo_planning_governance.mdc
All day-to-day operations (build, run, stop, logs, Weaviate) are driven by the silk.sh script in the project root.
| Path | Description |
|---|---|
silk.sh |
Main script: deploy, start/stop, build, logs, Weaviate management. |
.env |
Local config (create from .env.example). Not committed. |
.env.example |
Template and documentation for required/optional env vars. |
backend/ |
Kotlin backend (Ktor), static files, chat history. |
backend/.../claudecode/ |
Claude Code integration module (StreamParser, SessionStore, Runner, Manager). |
cc_bridge/ |
CC Bridge Agent: connects an external Claude CLI to Silk via WebSocket. |
frontend/webApp/ |
Kotlin/JS web frontend. |
frontend/androidApp/ |
Android app; APK output can be copied to backend/static. |
frontend/desktopApp/ |
Desktop client (optional). |
frontend/shared/ |
Shared KMP code for frontends. |
backend/workflows/ |
Workflow data store (workflow_store.json). |
search/ |
Weaviate schema and indexing (e.g. schema.py). |
Configuration is done via a .env file in the project root. The script silk.sh loads it automatically (and strips CRLF line endings).
- Copy the example:
cp .env.example .env - Edit
.envand set at least:- Backend / public URL:
BACKEND_HOST,BACKEND_HTTP_PORT(default8006) - Protocol: set
BACKEND_SCHEME=https(or directly setBACKEND_BASE_URL=https://...) - AI:
OPENAI_API_KEY,API_BASE_URL,AI_MODEL - Weaviate:
WEAVIATE_URL(e.g.http://<host>:8008)
- Backend / public URL:
- Optional: external search (e.g.
SERPAPI_KEY), feature flags. See.env.examplefor comments.
Do not commit .env; it is listed in .gitignore.
Follow these steps to get Silk running using silk.sh. The script expects Java 17, Python 3, and (for Weaviate) Docker. Gradle is used via the project’s wrapper.
cd /path/to/silk # or your repo rootcp .env.example .env
# Edit .env: set BACKEND_HOST, BACKEND_HTTP_PORT, OPENAI_API_KEY, API_BASE_URL, AI_MODEL, WEAVIATE_URLUse your real API base URL and key; set BACKEND_HOST to the IP or hostname other devices will use to reach this machine (e.g. for the web UI and APK download).
This builds the WebApp and APK, frees the ports used by Silk, starts Weaviate (Docker), then starts the backend and the web frontend:
./silk.sh deployWhen it finishes, the script prints the URLs (backend, web UI, APK download). Use ./silk.sh status to confirm all services.
If you have already run deploy or built manually:
./silk.sh start./silk.sh status # Backend, frontend, Weaviate, APK path
./silk.sh logs # Tail backend/frontend logs| Service | Port | Note |
|---|---|---|
| Backend | 8006 | API + static + APK URL |
| Web frontend | 8005 | HTTP server for WebApp |
| Weaviate HTTP | 8008 | Vector DB |
| Weaviate gRPC | 50051 | Vector DB |
If a port is in use, deploy will try to free it; for start, the script may prompt. You can stop everything with ./silk.sh stop.
All commands are run from the project root. silk.sh loads .env automatically.
| Command | Description |
|---|---|
./silk.sh deploy |
Clean ports, build WebApp + APK, start Weaviate, backend, and frontend. |
./silk.sh start |
Start Weaviate, backend, and frontend (builds WebApp if missing). |
./silk.sh stop |
Stop backend, frontend, and Weaviate. |
./silk.sh restart |
Stop then start. |
./silk.sh status |
Show status of backend, frontend, Weaviate, and latest APK. |
./silk.sh logs |
Tail backend and frontend logs. |
./silk.sh build |
Build WebApp only; output is copied to backend/static. |
./silk.sh build-apk |
Build Android APK; copies to backend/static and sets silk.apk link. |
./silk.sh build-all |
Build WebApp and APK. |
./silk.sh weaviate start|stop|status|schema |
Manage Weaviate (Docker) and schema. |
APK download URL (when backend is up): https://<BACKEND_HOST>:8006/api/files/download-apk (or http:// if BACKEND_SCHEME=http).
Workflows give each user a dedicated Claude Code programming session with its own persistent chat history. Unlike regular chats where you type /cc to enter CC mode, a workflow chat has CC mode always on — every message goes directly to the Claude Code agent.
- Open the Workflow tab in the left navigation bar.
- Click + 创建, enter a name, and confirm.
- Select the workflow to open its chat panel — Claude Code is ready immediately.
- Type any programming task; Claude Code will read, write, and edit files via the Bridge Agent.
- Use standard CC commands (
/new,/cancel,/status,/cd,/session,/compact,/help) inside the workflow chat.
- Creating a workflow automatically creates a chat group behind the scenes and links them together.
- When you open a workflow, the WebSocket connection detects it and silently activates CC mode — no
/ccneeded. - Workflows are per-user; each user's workflow list and sessions are isolated.
- Workflow data is stored in
backend/workflows/workflow_store.json.
| Method | Path | Description |
|---|---|---|
| GET | /api/workflows?userId=... |
List workflows |
| POST | /api/workflows |
Create workflow ({userId, name, description}) |
| DELETE | /api/workflows/{id}?userId=... |
Delete workflow |
Workflows require a running CC Bridge Agent — see CC Bridge below.
Silk supports a Claude Code (CC) mode that lets users interact with a Claude Code CLI from any chat session. This turns Silk into a programming assistant interface — users can ask Claude to read, write, and edit code on the filesystem.
CC mode uses a Bridge Agent architecture: the Silk backend does not run the Claude CLI itself. Instead, a separate Python process (cc_bridge/bridge_agent.py) connects to the backend via WebSocket, receives commands, and executes the Claude CLI locally. This decouples the backend deployment from the Claude execution environment.
- CC Bridge Agent running and connected to the Silk backend (see CC Bridge below)
- Claude CLI installed on the machine running the Bridge Agent (
npm install -g @anthropic-ai/claude-codeor equivalent)
The following environment variables are used by the Bridge Agent (set on the machine running bridge_agent.py, not the Silk backend):
# Claude CLI binary path (default: auto-detected from PATH)
# CLAUDE_CODE_PATH=claude
# Max tool-call rounds per execution (default: 100)
# CLAUDE_CODE_MAX_TURNS=100
# Per-execution timeout in seconds (default: 36000 = 10 hours)
# CLAUDE_CODE_TIMEOUT=36000
# Max output characters per execution (default: 30000)
# CLAUDE_CODE_MAX_OUTPUT_CHARS=30000In any Silk chat (group or private), send /cc to enter Claude Code mode:
/cc Enter CC mode (new session each time)
<any text> Send as prompt to Claude Code
/exit Exit CC mode, return to normal Silk chat
/new Start a new CC session (reset context)
/session List historical sessions
/session <id> Resume a previous session by ID prefix
/cd <path> Change working directory (creates new session)
/cd Reset to default working directory
/compact Compress session context
/cancel Cancel running task and clear queue
/queue View queued messages
/queue clear Clear the message queue
/status Show current CC state (session, directory, running/idle)
/help Show all CC commands
- Per-user isolation: each user has their own CC state per group; one user entering CC mode does not affect others
- CC responses are private: only the user who activated CC sees the responses; other group members see the user's messages but not CC output
- Message queue: if a task is running, new messages are queued (max 10) and auto-executed when the current task finishes
- Session persistence: CC sessions are managed by the Bridge Agent (
~/.silk/cc_sessions.json); sessions expire after 7 days of inactivity - Permission mode: currently uses
bypassPermissions(all tool operations are allowed without confirmation)
CC mode is implemented in backend/src/main/kotlin/com/silk/backend/claudecode/:
| File | Responsibility |
|---|---|
ClaudeCodeManager.kt |
Command routing (/cc, /exit, /new, etc.), per-user state, message queue |
BridgeRegistry.kt |
Manage Bridge WebSocket connections, send commands to bridge, track connection status and IP |
StreamParser.kt |
Parse Claude CLI's stream-json JSONL output |
The integration point is an interception block in ChatServer.broadcast() (in WebSocketConfig.kt) that routes CC-mode messages to ClaudeCodeManager before the normal Silk AI logic.
The Claude CLI runs on a separate machine (or the same machine in a different process) via the CC Bridge Agent, which connects to Silk via WebSocket. This is useful when:
- The backend runs in a container or VM without Claude CLI installed
- You want to run Claude CLI on a machine with direct access to your codebase
- You need to separate the backend deployment from the Claude execution environment
User (browser) ──→ Silk backend ──WebSocket──→ CC Bridge (bridge_agent.py) ──→ Claude CLI
The Bridge Agent (cc_bridge/bridge_agent.py) connects to the Silk backend via WebSocket, authenticates with a token, and executes Claude CLI commands on behalf of the user. The Silk backend routes CC-mode messages to the bridge instead of spawning a local CLI process.
-
Generate a Bridge Token in the Silk web UI:
- Go to Settings → Claude Code section
- Click Generate Token (or Regenerate Token if one already exists)
- Copy the token
-
Install dependencies on the machine where you want to run Claude CLI:
cd cc_bridge pip install -r requirements.txt # websockets>=12.0
-
Ensure Claude CLI is available on that machine:
claude --version # should print the Claude CLI version -
Configure — create
cc_bridge/.env:BRIDGE_SERVER=<silk-backend-host>:8006 BRIDGE_TOKEN=<your-token> # BRIDGE_WORKING_DIR=/path/to/workdir # optional # BRIDGE_LOG_LEVEL=INFO # optional
-
Start the Bridge Agent:
cd cc_bridge ./bridge.sh start # background (recommended) # or: python bridge_agent.py --server <host>:8006 --token <token> # foreground
-
Verify connection in the Silk web UI:
- Settings page should show a green status dot with Connected
- Bridge IP displays the IP address of the machine running bridge_agent.py
- Click Refresh Status to update the connection status
| Command | Description |
|---|---|
./bridge.sh start |
Start bridge in background |
./bridge.sh stop |
Stop bridge (graceful shutdown) |
./bridge.sh restart |
Restart bridge |
./bridge.sh status |
Check running status |
./bridge.sh logs |
Tail the log file |
| File | Responsibility |
|---|---|
cc_bridge/bridge.sh |
Management script: start/stop/restart/status/logs |
cc_bridge/bridge_agent.py |
WebSocket client, message routing, authentication |
cc_bridge/executor.py |
Claude CLI subprocess management |
cc_bridge/session_manager.py |
Session persistence and lifecycle |
cc_bridge/requirements.txt |
Python dependencies (websockets>=12.0) |
- Backend only:
./gradlew :backend:run(still need.envand optionally Weaviate). - Web dev:
./gradlew :frontend:webApp:browserDevelopmentRun(dev server; for production use./silk.sh buildthen serve via backend or./silk.sh start). - Env:
silk.shsources.envwith CRLF stripped. Prefer LF line endings in.envto avoid issues.
If the APK build fails with “Unable to delete directory” under frontend/androidApp/build/snapshot/, remove that directory and run ./silk.sh build-apk again.
MIT