FunCode is a Tauri 2 desktop workbench that embeds the official Cline SDK in a Rust-managed Node.js sidecar. The WebView never receives direct shell access: commands and events cross a small, versioned JSON-lines protocol.
Tauri WebView
└─ invoke / events
└─ Rust host (process lifecycle and native boundary)
└─ stdin / stdout JSONL
└─ Node sidecar
└─ @cline/sdk / ClineCore
The current implementation uses ClineCore in local mode. Each task is an
independent chat with its own workspace and approval mode. Ask first prompts
before every tool call, Auto approves the built-in workspace tools while
prompting for unknown or external tools, and Full access runs all tools without
approval prompts.
.
├── packages/
│ └── protocol/ Shared host/sidecar message contracts
├── sidecar/
│ ├── scripts/ Bundle and platform binary build scripts
│ └── src/
│ ├── cline/ ClineCore task runtime and approval bridge
│ ├── ipc/ JSONL output and serialization
│ └── main.ts Sidecar process entry
├── storage/ Runtime task and conversation persistence
├── src/
│ ├── features/
│ │ ├── approvals/ Tool approval UI
│ │ └── chat/ Agent event rendering
│ ├── services/ Tauri IPC client
│ ├── main.ts Desktop UI coordinator
│ └── styles.css
└── src-tauri/
├── binaries/ Generated target-specific sidecar binaries
├── capabilities/
├── src/
│ ├── lib.rs Tauri application setup
│ └── sidecar.rs Sidecar lifecycle and event bridge
└── tauri.conf.json
- Node.js 22 LTS (
.nvmrcpins the development runtime) - Rust stable and Cargo
- Tauri's platform prerequisites
# Web UI only
npm run dev
# Type-check the WebView and sidecar
npm run typecheck
# Generate the target-specific sidecar binary
npm run sidecar:build
# Run the complete desktop application
npm run tauri dev
# Build production frontend assets
npm run buildThe npm run tauri wrapper prepares the sidecar before invoking Tauri, so Vite
can start immediately when Tauri begins waiting for its dev URL. Unchanged
sidecar sources reuse the existing binary. The generated binary follows Tauri's
required target-triple naming:
src-tauri/binaries/testcline-agent-<target-triple>[.exe]
Host commands include:
system.pingtask.starttask.sendtask.deletetask.listtask.config.saveworkspace.files.listtask.abortapproval.resolve
Sidecar events include:
system.readyandsystem.statustask.statusfor per-task running, idle, and failed statecommand.resultagent.eventapproval.requestedsidecar.log
The sidecar reserves stdout for JSONL protocol messages. Operational logs go to stderr and are bridged to the desktop as structured log events.
In development, FunCode creates the ignored storage/ directory in the project
root. Packaged builds use the operating system's application-data directory.
Set TESTCLINE_STORAGE=/absolute/path to override either location.
storage/
├── tasks/
│ └── <task-id>/
│ ├── task.json Task workspace and model configuration
│ └── events.jsonl FunCode-only notices and lifecycle events
└── cline/
├── db/sessions.db Cline session metadata and lookup index
└── sessions/<session-id>/
└── <session-id>.messages.json
Authoritative model conversation
FunCode does not duplicate user or assistant messages. Task history is projected
from Cline's persisted session messages when the app starts, while
events.jsonl contains only application-specific records such as cancellation
and failure notices. Legacy conversation.jsonl files are not read or written.
The tasks/ index also keeps configurations saved before their first Cline
session starts; removing it requires either making those drafts ephemeral or
migrating drafts and FunCode-only notices into Cline-owned metadata.
API keys are stored as plaintext per model connection in the
funcode_connection_credentials table inside Cline's db/sessions.db. A saved
credential can be reused by new tasks that use the same provider, model, and
Base URL. Task metadata, task-list responses, and restored frontend state do not
contain the credential. The API key field shows a masked saved state after the
sidecar confirms that a matching credential exists.
- The frontend does not receive Tauri shell-plugin permissions.
- Rust owns sidecar start, write, stop, and event forwarding.
- Persisted API keys are not returned to the WebView or written into task metadata and Cline session manifests. They are plaintext in the local Cline SQLite database, so filesystem access to that database exposes them.
- Every task is scoped to the configured absolute workspace path.
- Approval behavior is selected per task with Ask first, Auto, or Full access.
For production, add native workspace selection, workspace path canonicalization, signed release binaries, and per-platform CI.

