# selfcoder
**Repository Path**: ooooinfo/selfcoder
## Basic Information
- **Project Name**: selfcoder
- **Description**: 本地编程工具
- **Primary Language**: Unknown
- **License**: MulanPSL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2026-08-20
- **Last Updated**: 2026-08-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Local AI Studio
**English** | [简体中文](README.zh-CN.md)
A local coding assistant with a **Tkinter GUI**, a **local Qwen** backend (DFlash2-accelerated), and streaming function-calling. The UI is **bilingual (English by default)** — switch via the model menu → 🌐 Language, persisted in the `language` field of `models.json` (`en`/`zh`).
Local GPU model management is built in via the embedded `gpulocal/` panel (start/stop/switch models, live GPU/system/hardware status).
> 📊 **Hardware & models write-up**: [2080Ti Second Spring — Qwen3.8-27B (DFlash2) / Qwen3-VL-32B / Ornith-1.5-35B-A3B](docs/2080ti-second-spring.md) — how two RTX 2080 Ti (44 GiB, NVLink) run three local models, and why llama.cpp over vLLM on this rig.
## Screenshots
 Embedded local model panel |
 Main coding interface add your capture as docs/screenshots/main.png |
## Features
- **Streaming chat** — body & reasoning stream live, progress spinner while running
- **Tool calling** — the model autonomously calls 8 built-in tools for coding tasks
- **Web search** — `web_search` tool (DuckDuckGo, zero deps, no API key needed)
- **MCP external tools** — connect any local stdio / remote HTTP MCP server, tools auto-discovered
- **📎 Attachment vision** — send images with a message (needs a vision model), audio/video by path
- **Embedded media** — inline images, GIFs, audio player, video thumbnails in chat
- **Copyable chat** — selectable text, Ctrl+C, right-click menu (copy / select all)
- **Auto attachment analysis** — txt/md/csv inlined; docx/pdf text extracted; zip/tar.gz extracted to `extract/` with a file manifest; rar/7z handled via `run_shell`
- **Multi-session** — auto-save, history switching, per-directory grouping, global search
- **Context compaction** — auto truncate/collapse long conversations (DeepSeek Harness style)
- **Token stats** — usage, cache hit rate, fast-reply savings shown live
- **Cache layer** — Redis / SQLite / memory backends, duplicate requests answered instantly
- **Codebase index** — semantic search over the project (opencode-codebase-index style)
- **Model management** — multiple providers, add/edit/delete, custom endpoints, vision models
- **🖥 Local GPU models** — embedded `gpulocal/` panel; start/stop/switch local models from the model dropdown, live status
- **🔗 Auto link fetching** — image URLs downloaded for vision; web pages fetched for the model (background thread)
- **Voice input** — hold-to-talk / auto-pause (local Whisper)
- **Bundled fonts** — JetBrains Mono + Noto Sans CJK shipped, consistent across platforms
- **Three permission modes** — read-only / ask every time / always allow
- **Workspace switching** — switch projects, relative paths based on the selected dir
- **Cross-platform** — Linux / Windows / macOS
## Architecture
```
local-ai-studio/
├── config.py # endpoints, models, generation params, system prompt
├── llm.py # OpenAI-compatible streaming client (tool_calls chunking + usage)
├── tools.py # 8 built-in tools + executor + permission tiers
├── mcp.py # MCP client (stdio subprocess / remote HTTP + tool discovery)
├── media.py # media support (images/GIF/audio/video thumbnails)
├── agent.py # function-calling loop + permissions + usage + multimodal
├── context.py # context compaction (budget + truncate + collapse)
├── cache.py # cache layer (Redis/SQLite/memory, auto fallback)
├── codeindex.py # codebase index (chunk + TF-IDF + SQLite search)
├── localmodels.py# local GPU model bridge (embedded gpulocal registry + cross-platform controls)
├── gpulocal/ # embedded local model panel (local_model_panel.py + services/ + setup.ps1)
├── weblinks.py # auto-fetch links (image download / web page text)
├── sessions.py # multi-session (save/switch/search/dir binding)
├── voice.py # voice input (PortAudio + local Whisper)
├── ui.py # Tkinter UI (models/cache/MCP/sessions + media + help)
├── fonts/ # bundled fonts (JetBrains Mono + Noto Sans CJK)
└── main.py # entry point
```
Data flow:
```
user question → Agent.run()
→ llm.stream_chat() streaming request (with tools schema)
→ model returns tool_calls or final text
→ if tool calls: approval (ask mode) → tools.execute_tool() → feed back results
→ loop until no more tool calls
→ final text returned and streamed
```
## Tools
| Tool | Description | Permission |
|---|---|---|
| `read_file` | Read a file (with line numbers) | read |
| `list_dir` | List a directory | read |
| `glob_search` | Find files by wildcard | read |
| `grep_search` | Search contents | read |
| `index_search` | Semantic codebase search (relevant code chunks) | read |
| `web_search` | Web search (DuckDuckGo, no API key) | read |
| `write_file` | Write / overwrite a file | **write** |
| `run_shell` | Run a shell command | **write** |
## Web search
`web_search` uses the DuckDuckGo HTML endpoint (title/URL/snippet, default 8, max 10), no dependencies or API key. Ask anything needing current info (versions, news, docs) and the model calls it automatically.
## 🖥 Local GPU models (embedded gpulocal)
The local model panel lives under `gpulocal/` and is maintained inside this repo, making Local AI Studio a local model launcher:
- **Auto registry sync** — on startup reads gpulocal's `MODELS` registry (mtime-cached) into `models.json` as `gpulocal-8097/8098/8099` providers; edits on the other side follow automatically
- **One-click start/stop from the dropdown** — each local model shows a live status dot (`●` ready / `◐` loading / `○` stopped); submenu ▶ Start / ■ Stop / ↻ Restart; auto-selects a model once ready
- **Serial management** — starting one model stops the others (44 GiB VRAM fits one at a time)
- **Two-way dynamic sync** — both sides operate the same `systemctl --user` services (Linux) / background processes (Windows); a change on either side is reflected within ~4s
- Models with `mmproj` are auto-marked vision (`vision: true`)
- Degrades gracefully if `gpulocal/` is absent
## MCP external tools
Model menu → 🔌 Manage MCP servers. Two transports:
- **Local stdio** — spawned as a subprocess (`command` + `args`), JSON-RPC 2.0 line-delimited
- **Remote streamable HTTP** — `url` (optional `headers`), POST, JSON or SSE
Config lives in `~/.config/wellfuture-coder/mcp.json`:
```json
{"servers": {"name": {"command": "...", "args": [], "url": "", "headers": {}, "enabled": true, "readonly": false}}}
```
Tools are named `mcp__` and merged into the model's tool table. `readonly` servers skip approval and are cacheable; unmarked are writable (ask mode needs confirm). MCP images are saved to `media/` and embedded. Example: `python3 examples/mcp_echo_server.py`.
## 📎 Attachments & media
- **📎 Attach** — multi-select images/audio/video with the message (privacy bar has per-item ✕)
- **Images** — converted to data URLs for vision (needs `"vision": true` on the model), downscaled to ≤1568px
- **Audio/video** — attach path + note; model analyzes with ffmpeg/ffprobe
- **Inline in chat** — images shown, GIFs animated, audio with ▶/⏸ player, video with ffmpeg first-frame thumbnail; double-click or "Open externally"; MCP images embedded too
- Chat text selectable, Ctrl+C, right-click copy/select-all
- Optional `pip install Pillow` for more formats (PNG/GIF work without it)
## Cache (speed + save tokens)
- **LLM reply cache** — identical model+messages+tools requests return cached reply
- **Tool result cache** — read-only tools cached within a short window
- **Three backends** (model menu → ⚡ Manage cache): Redis (shared), SQLite (`cache.db`, survives restart), memory (process-only), `auto` fallback Redis → SQLite → memory
- Settings in `~/.config/wellfuture-coder/cache.json`; UI can test Redis, tune TTL (LLM 3600s / tool 300s), clear cache
- Redis password supports `requirepass` (RESP2, for Redis Server <6.0; `redis://:password@host:port/db`)
- Stats bar shows token usage, KV cache hit rate, fast-reply count
## Codebase index (opencode-codebase-index style)
Not stuffing code into the prompt — parse → chunk → vectorize (TF-IDF) → SQLite. The model uses `index_search` to fetch relevant chunks (with file+line), then reads them, saving many tokens.
- **Code-aware tokenization** — camelCase/snake_case split, Chinese comments bigram-indexed, en+zh queries supported
- **Incremental** — skips unchanged files by mtime/size; builds on first use
- **Storage** — `~/.config/wellfuture-coder/index/.db`, skips .git/node_modules/build
- UI: model menu → 🗂 Rebuild code index
## Multi-session
- **Auto-save** — persisted at send time (crash-safe)
- **Directory binding** — each session records its workspace; menu shows only the current dir's sessions
- **Global search** — by title/content across projects (+ New session → 🔍)
- **Auto-switch dir** — opening another project's session switches to its workspace
- Storage: `~/.config/wellfuture-coder/sessions/*.json` (OpenAI-format messages)
## Context compaction (DeepSeek Harness style)
Over budget (~24000 tokens) auto-compacts and notifies before/after usage:
1. Stage 0: truncate any oversized tool result (old rounds 400 chars / recent 3000)
2. Stage 1: further compress old tool results if still over
3. Stage 2: collapse middle rounds into summary lines (keep system + first question + last 2 rounds)
## Model management
- Multiple providers (local Qwen / Qwen2.5-VL vision / DeepSeek / custom OpenAI-compatible)
- Add: one endpoint + key can hold multiple model IDs; auto-fetch the endpoint's `/models` list
- Edit: display name / model ID / endpoint / key
- Vision: set `"vision": true` to accept image attachments
- Config: `~/.config/wellfuture-coder/models.json` (old qwen-coder dir auto-migrates)
## Token stats
Bottom stats bar: token usage (in/out/think) & request count, KV cache hits, fast-reply count & estimated savings. Click to reset.
## Permission modes
| Mode | Behavior |
|---|---|
| `readonly` | Only read-only tools; no writes |
| `ask` (default) | Confirm before write tools (Allow / Deny) |
| `always` | Run directly, no confirmation |
## Running (Linux / Windows / macOS)
Tkinter GUI (built into Python), PortAudio (sounddevice) for recording, faster-whisper for local ASR — cross-platform, no OS-specific deps.
```bash
pip install -r requirements.txt # voice deps; skippable if not using voice
python3 main.py # Windows: python main.py
```
> Windows missing PortAudio? Reinstall sounddevice: `pip uninstall sounddevice && pip install sounddevice`.
> macOS mic permission: System Settings → Privacy & Security → Microphone → allow Python/Terminal.
### Packaging
```bash
pip install pyinstaller
pyinstaller --onefile --windowed --name LocalAIStudio main.py # Linux / Windows
pyinstaller --windowed --name LocalAIStudio main.py # macOS
```
> `WellFutureCoder.spec` is included: it excludes torch/faster-whisper/onnx, dropping size from ~3.9GB to ~69MB. Use `pyinstaller WellFutureCoder.spec`.
## Backend dependency
Local Qwen inference service (`qwen38-27b-q8.service`, port 8097, DFlash2 speculative decoding).
- Endpoint: `http://127.0.0.1:8097/v1`
- Model: `qwen3.8-27b-q8`
- Vision model: `qwen2.5-vl-7b` (`http://127.0.0.1:8099/v1`, `"vision": true`)
## Security notes
- `run_shell` / `write_file` really execute system commands / write files; default `ask` mode is safest
- Tool exec timeout (`TOOL_EXEC_TIMEOUT=60s`) and round cap (`MAX_TOOL_ROUNDS=20`) prevent runaway loops
- No sandbox isolation yet — avoid letting the model process untrusted instructions in `always` mode