tokenicode

repository·main·Indexed 19 days ago

https://github.com/yiliqi78/tokenicode

A desktop client built with Tauri 2 that provides a native GUI wrapper for the Claude Code CLI. It features session management, a built-in file explorer and editor powered by CodeMirror, and support for multiple API providers including Anthropic, DeepSeek, Zhipu GLM, Qwen Coder, Kimi k2, and MiniMax. It implements an SDK Control Protocol for structured permission handling (code, ask, plan, and bypass modes) and manages Claude CLI processes via NDJSON streams.

Tokens
35.1K
Snippets
96
Records
161
Agent score
65%

What's inside tokenicode

  1. Overview of Zustand Stores in TOKENICODE

    main

    TOKENICODE uses Zustand for state management, distributed across several specialized stores. Some stores are persisted (e.g., to localStorage or disk), while others are transient.

    StorePurposePersisted
    chatStoreMessages, streaming, session meta/status, per-tab cache, permission stateNo
    sessionStoreSession list, selection, drafts, stdin→tab routing, custom names, pin/archiveNo
    settingsStoreTheme, colorTheme, locale, model, mode, layout, font, thinkingLevel, update stateYes (localStorage)
    fileStoreFile tree, preview, edit buffer, changed files, recent projectsNo
    agentStoreAgent tree (multi-agent), phase tracking, per-tab cacheNo
    commandStoreUnified commands (built-in + custom + skills), prefix modeNo
    skillStoreSkills CRUD, enable/disable, content editingNo
    providerStoreMulti-provider API config (base URL, key, model mappings)Yes (providers.json on disk)
    setupStoreCLI install/login progressNo
    mcpStoreMCP servers from ~/.claude.jsonNo

    Tab-Switching Pattern: The chatStore and agentStore implement saveToCache(tabId) and restoreFromCache(tabId) to allow seamless switching between different chat sessions/tabs.

  2. Export a Group to a local directory

    main

    The Export (导出) operation allows you to take all sessions within a specific Group (组) and copy them into a real folder in your file manager (e.g., Finder).

    Key behaviors:

    • It creates a copy of the session files.
    • The original session files remain untouched in their original engine-managed directory.
    • Warning: Because Export creates a copy, moving or editing the exported files will not affect the original sessions in the Tokenicode client, and you cannot resume a conversation in the client using an exported file if it has been moved from its original location.
  3. How session grouping drag-and-drop works

    main

    Session grouping in Tokenicode utilizes @dnd-kit with PointerSensor to handle three specific drag-and-drop scenarios:

    1. Reordering within a group: Moving sessions up or down within a single group.
    2. Moving sessions between groups: Dragging a session from Group A to Group B.
    3. Reordering groups: Moving entire groups up or down.

    Technical Implementation Details

    • Sensor Choice: The system uses PointerSensor (based on pointerdown, pointermove, and pointerup events) instead of the HTML5 Drag and Drop API. This is critical because the Tauri WKWebView environment intercepts HTML5 drag events (dragstart, dragover, drop) when dragDropEnabled is set to true.
    • Coexistence with File Tree: Tokenicode maintains two separate drag-and-drop mechanisms that do not interfere with each other:
      • Pointer-based (dnd-kit): Manages sessions and groups.
      • Mouse-based (custom drag-state.ts): Manages file tree interactions (e.g., dragging a file into a folder or the chat box).
    • Testing Strategy: Because simulating pointer events in jsdom is difficult, testing focuses on verifying the mapping between dnd-kit's onDragEnd event and the corresponding groupStore actions using pure function unit tests.
  4. Understand the TOKENICODE Architecture

    main

    TOKENICODE is a native desktop GUI for the Claude Code CLI, built using Tauri 2, React 19, and TypeScript. It acts as a visual wrapper around the Claude CLI, providing a structured interface for chat, file management, and agent control.

    High-Level Component Model

    • Frontend (React/TS): Handles the UI (Sidebar, ChatPanel, SecondaryPanel), state management via Zustand, and user interactions.
    • IPC Bridge: Facilitates communication between the React frontend and the Rust backend using Tauri's invoke and events.
    • Rust Backend (Tauri): Manages the lifecycle of the Claude CLI processes, handles file system watching, and implements the SDK Control Protocol.
    • Claude CLI: The core engine, communicating with the backend via stdin/stdout pipes using NDJSON (Newline Delimited JSON).
  5. Understand SDK Control Protocol and Modes

    main

    TOKENICODE uses the Claude CLI native control protocol to handle permissions via structured JSON. Permissions are passed through stdout and responded to via stdin using allow or deny messages.

    You can switch between four operational modes at runtime without restarting the session:

    • code: Standard coding mode.
    • ask: Mode for asking questions.
    • plan: Mode for planning tasks.
    • bypass: Mode to bypass certain restrictions.
  6. Understand the SDK Control Protocol

    main

    When the Claude CLI is launched with the flag --permission-prompt-tool stdio, TOKENICODE uses a bidirectional SDK Control Protocol defined in protocol.rs to manage runtime behavior.

    Communication Flow

    1. CLI → TOKENICODE (control_request): The CLI sends permission requests (e.g., can_use_tool) or hook callbacks.
    2. TOKENICODE → CLI (control_response): The frontend sends allow/deny decisions along with updatedInput.
    3. Runtime Commands: TOKENICODE can send commands to the CLI such as interrupt, set_permission_mode, set_model, and rewind_files without requiring a CLI restart.
  7. Use SDK Control Protocol for Permissions

    main

    TOKENICODE uses Claude CLI's native control protocol to handle permissions through structured JSON. This allows you to manage how the agent interacts with your system.

    Permission Modes

    You can switch between these four modes at runtime:

    • code: For code-related operations.
    • ask: For general inquiries.
    • plan: For planning tasks.
    • bypass: To bypass certain restrictions.

    Permission requests appear as structured cards where you can provide typed allow or deny responses via stdin.

  8. How session grouping works in TOKENICODE

    main

    TOKENICODE implements session grouping (Groups) using metadata mapping (tags) rather than physical subdirectories. This design ensures that moving a session between groups is a lightweight operation that does not break the underlying Claude Code session files.

    Key Concepts

    • No File Movement: Session .jsonl files are never moved from their original Claude Code storage location (~/.claude/projects/<cwd_encoded>/<uuid>.jsonl).
    • Metadata-driven: Grouping information is stored in a dedicated TOKENICODE configuration file: ~/.tokenicode/groups.json.
    • Hierarchy: The UI renders a three-level hierarchy: Workspace › Group › Session.

    Benefits for Users

    • Safe Reorganization: You can freely drag and drop sessions to change groups without breaking the resume functionality or losing session continuity.
    • Context Inheritance: Because the physical directory (CWD) of the session does not change, sessions correctly inherit the CLAUDE.md and other context files from their original workspace.
    • Exporting for Finder: Since groups are not real folders, you cannot browse them directly in Finder. Instead, use the Export feature to copy a group's sessions into a real folder structure (with readable filenames and Markdown) for external use.
  9. How the Permission Request Flow works

    main

    Tokenicode uses an SDK Control Protocol to handle tool usage and security permissions.

    1. Request: The CLI emits a control_request via stdout (e.g., { subtype: "can_use_tool", tool_name, input }).
    2. Interception: The Rust backend intercepts this and emits a tokenicode_permission_request event on the stream channel.
    3. UI Prompt: The frontend renders a PermissionCard containing Approve/Deny buttons.
    4. Response: When the user clicks a button, the frontend calls bridge.respondPermission(sessionId, requestId, allow, updatedInput).
    5. Execution: The Rust backend sends a control_response via the StdinManager to the CLI, allowing the process to proceed.
  10. Understand the Tokenicode hierarchy: Project, Group, and Session

    main

    Tokenicode organizes Claude Code sessions into a three-tier hierarchy. Understanding the distinction between these levels is critical for managing files and organization:

    1. Project (工作区): The top-level (Level 1) organization. These are automatically created by the Claude Code engine based on the session's current working directory (cwd). They correspond to real directories under ~/.claude/projects/ on disk.
    2. Group (组): The middle-level (Level 2) organization. These are logical tags manually created by the user to collect sessions. Groups do not correspond to real directories on disk. A Group belongs to a specific Project, and a Session can only belong to one Group at a time (moving a session to a new group removes it from the old one).
    3. Session (会话): The bottom-level (Level 3) unit. A single continuous conversation with Claude, which is stored as a .jsonl file.
  11. Understand the Tokenicode Data Flow

    main

    Tokenicode operates by bridging a React frontend with a Rust backend that manages a Claude Code CLI process via NDJSON (Newline Delimited JSON) streams over IPC.

    New Message Flow

    1. Input: User submits a prompt via the InputBar.
    2. Session Start: The frontend calls bridge.startSession with parameters like prompt, cwd, model, thinking_level, permission_mode, and provider_id.
    3. CLI Execution: The Rust backend spawns the CLI process using stream-json I/O.
    4. Stream Processing: A stdout reader parses NDJSON. It intercepts control_request events and forwards the rest of the stream.
    5. UI Update: The useStreamProcessor hook parses claude:stream events and updates the chatStore. React then re-renders the ChatPanel.

    Follow-up Messages

    For persistent sessions, the frontend uses bridge.sendStdin(sessionId, message). The StdinManager writes NDJSON to the existing CLI process's stdin, following the same stream processing pipeline.

  12. Configure a Custom API Provider in TOKENICODE

    main

    TOKENICODE allows you to connect to third-party AI model providers (like DeepSeek, SiliconFlow, or Moonshot) by manually entering their API credentials. This is useful for accessing different models, pricing tiers, or regional providers.

    Configuration Requirements

    To add a provider, you need the following information from your chosen provider's dashboard:

    1. Name: A label for your own reference (e.g., CloudMist AI).
    2. Base URL: The API endpoint address provided by the service (e.g., https://yunwu.ai/v1).
    3. API Key: Your unique authentication token, typically starting with sk-.
    4. Protocol Type: Most modern providers use the OpenAI 兼容 (OpenAI compatible) protocol.

    Setup Steps

    1. Open TOKENICODE and click the Settings icon (⚙️) in the left sidebar.
    2. Locate the API 提供商 (API Provider) or 自定义 API (Custom API) section and click 添加 (Add).
    3. Fill in the required fields (Name, Base URL, API Key, and Protocol Type).
    4. Click 保存 (Save) or 测试连接 (Test Connection).

    Troubleshooting Connection Failures

    ErrorLikely CauseSolution
    网络错误 (Network Error)Incorrect Base URL or service outageVerify the Base URL is correct.
    认证失败 (Authentication Failed)Invalid or expired API KeyRe-copy the Key; ensure no leading/trailing spaces are included.
    余额不足 (Insufficient Balance)Provider account has no creditsTop up your balance on the provider's website.
    | 字段 | 填什么 | 说明 |
    |------|--------|------|
    | 名称 | 随便起,比如「云雾AI」 | 只是给你自己看的标签 |
    | Base URL | `https://yunwu.ai/v1` | 第四步找到的地址 |
    | API Key | 刚才复制的 `sk-xxx...` | 第三步拿到的密钥 |
    | 协议类型 | OpenAI 兼容 | 大多数供应商都选这个 |