localcoder 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- localcoder/__init__.py +2 -0
- localcoder/__main__.py +2 -0
- localcoder/agent.py +35 -0
- localcoder/backends.py +2470 -0
- localcoder/bench.py +335 -0
- localcoder/cli.py +827 -0
- localcoder/gemma4coder_display.py +583 -0
- localcoder/setup.py +321 -0
- localcoder/tui.py +276 -0
- localcoder/voice.py +187 -0
- localcoder-0.1.0.dist-info/METADATA +187 -0
- localcoder-0.1.0.dist-info/RECORD +15 -0
- localcoder-0.1.0.dist-info/WHEEL +4 -0
- localcoder-0.1.0.dist-info/entry_points.txt +2 -0
- localcoder-0.1.0.dist-info/licenses/LICENSE +4 -0
localcoder/voice.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""Voice input — hold Space to talk, release to transcribe."""
|
|
2
|
+
import os, subprocess, signal, tempfile, time, shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
console = Console()
|
|
8
|
+
|
|
9
|
+
# ── Paths ──
|
|
10
|
+
WHISPER_BIN = shutil.which("whisper-cli") or "/opt/homebrew/bin/whisper-cli"
|
|
11
|
+
WHISPER_MODEL_DIR = Path.home() / ".local/share/whisper"
|
|
12
|
+
WHISPER_MODEL = WHISPER_MODEL_DIR / "ggml-base.bin"
|
|
13
|
+
SOX_REC = shutil.which("rec") or "/opt/homebrew/bin/rec"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def is_voice_available():
|
|
17
|
+
"""Check if voice input dependencies are installed."""
|
|
18
|
+
return os.path.exists(WHISPER_BIN) and WHISPER_MODEL.exists() and os.path.exists(SOX_REC)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def check_mic_permission():
|
|
22
|
+
"""Check macOS microphone permission by attempting a quick recording."""
|
|
23
|
+
try:
|
|
24
|
+
tmp = tempfile.mktemp(suffix=".wav")
|
|
25
|
+
proc = subprocess.run(
|
|
26
|
+
[SOX_REC, "-q", "-r", "16000", "-c", "1", "-b", "16", tmp, "trim", "0", "0.5"],
|
|
27
|
+
capture_output=True, text=True, timeout=5
|
|
28
|
+
)
|
|
29
|
+
if os.path.exists(tmp):
|
|
30
|
+
size = os.path.getsize(tmp)
|
|
31
|
+
os.unlink(tmp)
|
|
32
|
+
if size > 100:
|
|
33
|
+
return True
|
|
34
|
+
# Check stderr for permission errors
|
|
35
|
+
if "permission" in proc.stderr.lower() or "not authorized" in proc.stderr.lower():
|
|
36
|
+
return False
|
|
37
|
+
return proc.returncode == 0
|
|
38
|
+
except:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def setup_voice():
|
|
43
|
+
"""Interactive setup for voice input."""
|
|
44
|
+
console.print(f"\n [bold magenta]Voice Input Setup[/]\n")
|
|
45
|
+
|
|
46
|
+
# Step 1: Check sox/rec
|
|
47
|
+
if not os.path.exists(SOX_REC):
|
|
48
|
+
console.print(f" [yellow]Installing sox (audio recorder)...[/]")
|
|
49
|
+
r = subprocess.run(["brew", "install", "sox"], timeout=120)
|
|
50
|
+
if r.returncode != 0:
|
|
51
|
+
console.print(f" [red]Failed to install sox. Run: brew install sox[/]")
|
|
52
|
+
return False
|
|
53
|
+
console.print(f" [green]✓ sox installed[/]")
|
|
54
|
+
else:
|
|
55
|
+
console.print(f" [green]✓ sox already installed[/]")
|
|
56
|
+
|
|
57
|
+
# Step 2: Check whisper-cli
|
|
58
|
+
whisper_bin = shutil.which("whisper-cli")
|
|
59
|
+
if not whisper_bin:
|
|
60
|
+
console.print(f" [yellow]Installing whisper-cpp...[/]")
|
|
61
|
+
r = subprocess.run(["brew", "install", "whisper-cpp"], timeout=300)
|
|
62
|
+
if r.returncode != 0:
|
|
63
|
+
console.print(f" [red]Failed to install whisper-cpp. Run: brew install whisper-cpp[/]")
|
|
64
|
+
return False
|
|
65
|
+
console.print(f" [green]✓ whisper-cpp installed[/]")
|
|
66
|
+
else:
|
|
67
|
+
console.print(f" [green]✓ whisper-cpp already installed[/]")
|
|
68
|
+
|
|
69
|
+
# Step 3: Download whisper model
|
|
70
|
+
if not WHISPER_MODEL.exists():
|
|
71
|
+
console.print(f" [yellow]Downloading whisper base model (148MB)...[/]")
|
|
72
|
+
console.print(f" [dim]Supports: English, French, Arabic + 95 more languages[/]")
|
|
73
|
+
WHISPER_MODEL_DIR.mkdir(parents=True, exist_ok=True)
|
|
74
|
+
r = subprocess.run([
|
|
75
|
+
"curl", "-L", "--progress-bar",
|
|
76
|
+
"-o", str(WHISPER_MODEL),
|
|
77
|
+
"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin"
|
|
78
|
+
], timeout=300)
|
|
79
|
+
if r.returncode != 0 or not WHISPER_MODEL.exists():
|
|
80
|
+
console.print(f" [red]Failed to download whisper model[/]")
|
|
81
|
+
return False
|
|
82
|
+
console.print(f" [green]✓ Whisper base model downloaded ({WHISPER_MODEL.stat().st_size // 1024 // 1024}MB)[/]")
|
|
83
|
+
else:
|
|
84
|
+
console.print(f" [green]✓ Whisper model ready ({WHISPER_MODEL.stat().st_size // 1024 // 1024}MB)[/]")
|
|
85
|
+
|
|
86
|
+
# Step 4: Check microphone permission
|
|
87
|
+
console.print(f"\n [dim]Testing microphone access...[/]")
|
|
88
|
+
if check_mic_permission():
|
|
89
|
+
console.print(f" [green]✓ Microphone access granted[/]")
|
|
90
|
+
else:
|
|
91
|
+
console.print(f" [yellow]⚠ Microphone access needed[/]")
|
|
92
|
+
console.print(f" [dim]macOS will prompt for permission on first recording.[/]")
|
|
93
|
+
console.print(f" [dim]If denied, go to: System Settings → Privacy & Security → Microphone[/]")
|
|
94
|
+
console.print(f" [dim]and enable access for your terminal app (iTerm2 / Terminal).[/]")
|
|
95
|
+
|
|
96
|
+
console.print(f"\n [green]✓ Voice input ready![/]")
|
|
97
|
+
console.print(f" [dim]Hold Space while typing prompt to record, release to transcribe.[/]")
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def record_audio(max_seconds=30):
|
|
102
|
+
"""Record from mic until stopped. Returns path to WAV file."""
|
|
103
|
+
wav_path = tempfile.mktemp(suffix=".wav")
|
|
104
|
+
proc = subprocess.Popen(
|
|
105
|
+
[SOX_REC, "-q", "-r", "16000", "-c", "1", "-b", "16", wav_path,
|
|
106
|
+
"trim", "0", str(max_seconds)],
|
|
107
|
+
stdin=subprocess.PIPE,
|
|
108
|
+
stdout=subprocess.DEVNULL,
|
|
109
|
+
stderr=subprocess.DEVNULL,
|
|
110
|
+
)
|
|
111
|
+
return proc, wav_path
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def stop_recording(proc):
|
|
115
|
+
"""Stop the recording process."""
|
|
116
|
+
try:
|
|
117
|
+
proc.send_signal(signal.SIGINT)
|
|
118
|
+
proc.wait(timeout=3)
|
|
119
|
+
except:
|
|
120
|
+
proc.kill()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def transcribe(wav_path, language="auto"):
|
|
124
|
+
"""Transcribe audio using whisper-cli (CPU-only, no GPU conflict)."""
|
|
125
|
+
whisper = shutil.which("whisper-cli") or WHISPER_BIN
|
|
126
|
+
if not os.path.exists(whisper):
|
|
127
|
+
return None, "whisper-cli not found"
|
|
128
|
+
|
|
129
|
+
model = str(WHISPER_MODEL)
|
|
130
|
+
if not os.path.exists(model):
|
|
131
|
+
return None, "whisper model not found"
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
# Use Metal GPU if llama-server has headroom (base model ~200MB),
|
|
135
|
+
# otherwise fall back to CPU-only
|
|
136
|
+
gpu_flags = []
|
|
137
|
+
try:
|
|
138
|
+
# Check free GPU headroom
|
|
139
|
+
out = subprocess.run(["pgrep", "-f", "llama-server"], capture_output=True, text=True)
|
|
140
|
+
if out.stdout.strip():
|
|
141
|
+
# llama-server running — whisper base needs ~200MB, check if safe
|
|
142
|
+
# With 2.7GB headroom on 24GB Mac, Metal whisper is fine
|
|
143
|
+
gpu_flags = [] # let whisper use Metal (default)
|
|
144
|
+
else:
|
|
145
|
+
gpu_flags = [] # no conflict, use Metal
|
|
146
|
+
except:
|
|
147
|
+
gpu_flags = ["--no-gpu"] # safe fallback
|
|
148
|
+
|
|
149
|
+
result = subprocess.run(
|
|
150
|
+
[whisper,
|
|
151
|
+
"--model", model,
|
|
152
|
+
"--language", language,
|
|
153
|
+
"--no-timestamps",
|
|
154
|
+
"--threads", "8",
|
|
155
|
+
"--file", wav_path] + gpu_flags,
|
|
156
|
+
capture_output=True, text=True, timeout=30
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Parse output — whisper-cli outputs text lines (with --no-timestamps, just raw text)
|
|
160
|
+
lines = []
|
|
161
|
+
detected_lang = None
|
|
162
|
+
for line in result.stderr.split("\n"):
|
|
163
|
+
if "auto-detected language:" in line:
|
|
164
|
+
detected_lang = line.split("auto-detected language:")[-1].strip().split()[0]
|
|
165
|
+
|
|
166
|
+
for line in result.stdout.split("\n"):
|
|
167
|
+
line = line.strip()
|
|
168
|
+
# Skip empty lines and metadata
|
|
169
|
+
if line and not line.startswith("[") and not line.startswith("whisper_"):
|
|
170
|
+
lines.append(line)
|
|
171
|
+
|
|
172
|
+
text = " ".join(lines).strip()
|
|
173
|
+
# Clean up common whisper artifacts
|
|
174
|
+
text = text.replace("(silence)", "").replace("[BLANK_AUDIO]", "").strip()
|
|
175
|
+
|
|
176
|
+
return text, detected_lang
|
|
177
|
+
|
|
178
|
+
except subprocess.TimeoutExpired:
|
|
179
|
+
return None, "transcription timed out"
|
|
180
|
+
except Exception as e:
|
|
181
|
+
return None, str(e)
|
|
182
|
+
finally:
|
|
183
|
+
if os.path.exists(wav_path):
|
|
184
|
+
try:
|
|
185
|
+
os.unlink(wav_path)
|
|
186
|
+
except:
|
|
187
|
+
pass
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: localcoder
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local AI coding agent — auto-installs, auto-serves, zero config. Works with Gemma 4, Qwen 3.5, and any model via llama.cpp or Ollama.
|
|
5
|
+
Project-URL: Homepage, https://github.com/AnassKartit/localcoder
|
|
6
|
+
Project-URL: Repository, https://github.com/AnassKartit/localcoder
|
|
7
|
+
Author: Anass Kartit
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: agent,ai,coding,gemma4,llama.cpp,local,localcoder,ollama,qwen
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: huggingface-hub>=0.20
|
|
19
|
+
Requires-Dist: prompt-toolkit>=3.0
|
|
20
|
+
Requires-Dist: rich>=13.0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# localcoder
|
|
24
|
+
|
|
25
|
+
**The local coding CLI that does the obvious things nobody else does.**
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pipx install localcoder
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
I wanted to paste a screenshot into my coding assistant and see it inline. No tool did that locally. So I built one.
|
|
32
|
+
|
|
33
|
+
## Cost: $1.30/month vs $110/month
|
|
34
|
+
|
|
35
|
+
Running local saves 85-141x compared to cloud APIs:
|
|
36
|
+
|
|
37
|
+
| Usage | Claude Sonnet | Claude Opus | Local (US) | Local (India) |
|
|
38
|
+
|-------|--------------|-------------|------------|---------------|
|
|
39
|
+
| 4h/day | $55/mo | $91/mo | **$0.65/mo** | $0.29/mo |
|
|
40
|
+
| 8h/day | $110/mo | $183/mo | **$1.30/mo** | $0.58/mo |
|
|
41
|
+
| 10h/day | $137/mo | $228/mo | **$1.62/mo** | $0.72/mo |
|
|
42
|
+
|
|
43
|
+
*Based on: Gemma 4 26B at 47 tok/s, 30% active generation, M4 Pro 30W. Electricity: [worldpopulationreview.com](https://worldpopulationreview.com/country-rankings/cost-of-electricity-by-country). API: [anthropic.com](https://www.anthropic.com/pricing).*
|
|
44
|
+
|
|
45
|
+
**Annual savings: ~$1,300-$2,700** depending on usage and API choice.
|
|
46
|
+
|
|
47
|
+
## What's Actually Different
|
|
48
|
+
|
|
49
|
+
| Feature | localcoder | aider | OpenCode | Claude Code |
|
|
50
|
+
|---------|-----------|-------|----------|-------------|
|
|
51
|
+
| Paste image, see it inline | **Ctrl+V → shows in terminal** | no | no | cloud only |
|
|
52
|
+
| Voice input (local) | **Ctrl+R → Whisper, no cloud** | no | no | no |
|
|
53
|
+
| See GPU memory while coding | **/gpu → live stats** | no | no | no |
|
|
54
|
+
| Computer use (screenshot + click) | **built-in** | no | no | cloud only |
|
|
55
|
+
| Free GPU when it's slow | **/clean → before/after** | no | no | n/a |
|
|
56
|
+
| Browse HuggingFace models | **built-in model browser** | no | no | n/a |
|
|
57
|
+
| Works offline | **100%** | partial | partial | no |
|
|
58
|
+
| Cost | **$0.00** | API costs | API costs | $20/mo+ |
|
|
59
|
+
|
|
60
|
+
## Demo
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
❯ localcoder
|
|
64
|
+
|
|
65
|
+
localcoder · local AI coding agent · $0.00 forever
|
|
66
|
+
|
|
67
|
+
┌──────────────────────────────────────────────────┐
|
|
68
|
+
│ LOCAL CODER │
|
|
69
|
+
└──────────────────────────────────────────────────┘
|
|
70
|
+
|
|
71
|
+
● Gemma 4 26B Q3_K_XL · llama.cpp · 128K · ● GPU · 47 tok/s
|
|
72
|
+
✓ offline · no API keys · no data sent
|
|
73
|
+
|
|
74
|
+
ctrl+r voice ctrl+v image /gpu stats /clean free /models switch
|
|
75
|
+
|
|
76
|
+
❯ /gpu
|
|
77
|
+
GPU ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12/16GB 3GB free
|
|
78
|
+
Swap 3GB Pressure normal
|
|
79
|
+
Model Gemma 4 26B Q3_K_XL GPU ctx 128K footprint 2311MB
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Benchmark — M4 Pro 24GB
|
|
83
|
+
|
|
84
|
+
Real tests, real hardware, no synthetic benchmarks:
|
|
85
|
+
|
|
86
|
+
| Model | Size | tok/s | Notes |
|
|
87
|
+
|-------|------|-------|-------|
|
|
88
|
+
| **Gemma 4 26B** Q3_K_XL | 12.0GB | 47 | Best overall — vision + tool calling |
|
|
89
|
+
| **Qwen3.5-35B** MoE Q2_K_XL | 11.3GB | 46 | Best coding quality |
|
|
90
|
+
| **Qwen3.5-4B** Q4_K_XL | 2.7GB | 46 | Quick tasks |
|
|
91
|
+
| Gemma 4 E4B Q4_K_M | 5.0GB | 56 | Fastest — good for 16GB Macs |
|
|
92
|
+
| ~~Qwen3.5-27B Dense~~ | ~~13.4GB~~ | ~~7~~ | ~~Swap thrashing — don't use on 24GB~~ |
|
|
93
|
+
|
|
94
|
+
## Install
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# macOS (Apple Silicon)
|
|
98
|
+
pipx install localcoder
|
|
99
|
+
|
|
100
|
+
# First run — auto-detects hardware, shows what fits, starts model
|
|
101
|
+
localcoder
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Needs [llama.cpp](https://github.com/ggml-org/llama.cpp) or [Ollama](https://ollama.com). First run wizard handles this.
|
|
105
|
+
|
|
106
|
+
## Commands
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
localcoder # interactive coding
|
|
110
|
+
localcoder -p "build a react app" # one-shot
|
|
111
|
+
localcoder --yolo # auto-approve tools
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### While Coding
|
|
115
|
+
|
|
116
|
+
| Command | What |
|
|
117
|
+
|---------|------|
|
|
118
|
+
| `Ctrl+V` | Paste + display image from clipboard |
|
|
119
|
+
| `Ctrl+R` | Toggle voice input (local Whisper) |
|
|
120
|
+
| `/gpu` | GPU memory, swap, model status |
|
|
121
|
+
| `/clean` | Free GPU memory with before/after |
|
|
122
|
+
| `/models` | Switch model (includes HuggingFace trending) |
|
|
123
|
+
| `/clear` | Clear conversation |
|
|
124
|
+
|
|
125
|
+
### Also works with Claude Code
|
|
126
|
+
|
|
127
|
+
Don't want localcoder's agent? Use Claude Code with your local model instead:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
pip install localfit
|
|
131
|
+
localfit --launch claude --model gemma4-26b
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
One command: starts model → configures Claude Code → launches with `--bare` flag.
|
|
135
|
+
See [localfit](https://github.com/AnassKartit/localfit) for details.
|
|
136
|
+
|
|
137
|
+
### GPU Toolkit (localfit inside)
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
localcoder --simulate # will this model fit my GPU?
|
|
141
|
+
localcoder --fetch unsloth/... # check all quants from HuggingFace
|
|
142
|
+
localcoder --bench # benchmark models on YOUR hardware
|
|
143
|
+
localcoder --health # GPU health dashboard
|
|
144
|
+
localcoder --config opencode # auto-configure OpenCode for local models
|
|
145
|
+
localcoder --config aider # auto-configure aider
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Also available standalone: `pipx install localfit`
|
|
149
|
+
|
|
150
|
+
## Hardware
|
|
151
|
+
|
|
152
|
+
| Mac | RAM | Best Model | Speed |
|
|
153
|
+
|-----|-----|-----------|-------|
|
|
154
|
+
| Air M2 | 8 GB | Qwen 3.5 4B | 50 tok/s |
|
|
155
|
+
| Air M3 | 16 GB | Gemma 4 E4B | 57 tok/s |
|
|
156
|
+
| **Pro M4** | **24 GB** | **Gemma 4 26B Q3_K_XL** | **47 tok/s** |
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
Apache-2.0
|
|
161
|
+
|
|
162
|
+
## Security
|
|
163
|
+
|
|
164
|
+
Sandbox mode is **ON by default**. Protects against destructive model outputs:
|
|
165
|
+
|
|
166
|
+
| Blocked | Examples |
|
|
167
|
+
|---------|----------|
|
|
168
|
+
| Destructive commands | `rm -rf`, `sudo`, `kill`, `mkfs` |
|
|
169
|
+
| Pipe to shell | `curl ... \| bash`, `wget ... \| sh` |
|
|
170
|
+
| Protected paths | `~/.ssh`, `~/.aws`, `~/.env`, `/etc/` |
|
|
171
|
+
| Path traversal | `../../etc/passwd` |
|
|
172
|
+
| Computer use | Disabled in sandbox |
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
localcoder # sandboxed (default)
|
|
176
|
+
localcoder --yolo # auto-approve but sandbox ON
|
|
177
|
+
localcoder --unrestricted # sandbox OFF (shows warning)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Approved tools are remembered across sessions (`~/.localcoder/approved_tools.json`).
|
|
181
|
+
|
|
182
|
+
## Tests
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
pip install pytest
|
|
186
|
+
pytest tests/ -v # 19 tests
|
|
187
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
localcoder/__init__.py,sha256=eD-uC7S1gz0HbdaaORS2soj6zh5BB_tytoArAKfoioI,111
|
|
2
|
+
localcoder/__main__.py,sha256=vFZX_R8P6RBS2CiBSvkFy_IG9b7wOi8d9h5H-y9Eskw,39
|
|
3
|
+
localcoder/agent.py,sha256=tLaWfkgAmq-dQ9PqO59RziPS7deijg3HcJ1jmAyqWnM,1044
|
|
4
|
+
localcoder/backends.py,sha256=JeGS-mzIWPElWmrZnswotInC225YhcFkRNztNI-3mhE,96500
|
|
5
|
+
localcoder/bench.py,sha256=xVDRENdCrjy_Mz2Q_PeEax8ws_-6uTKcKYXmBm1eqr4,12620
|
|
6
|
+
localcoder/cli.py,sha256=Yj6s02gQi37ctWydNt8VJHG0Zl1YdcZ4tM828oXWEeM,38917
|
|
7
|
+
localcoder/gemma4coder_display.py,sha256=gGnVqmSpurOoBw_cup-ABWC_SzetWv1rk1KBz23fPck,17693
|
|
8
|
+
localcoder/setup.py,sha256=3ACjQSOSmgPM9qhd5eaPAQ5xmGdYSB5C1y3EavRiw8M,11464
|
|
9
|
+
localcoder/tui.py,sha256=wwOV8IrZumgg4QF1MCafHPtoCc5Av6sBoQoAqYnhoYU,9021
|
|
10
|
+
localcoder/voice.py,sha256=ZEBFWzSB0tFoN8OQ68sV_jPPT_uMXcn95HoCS28ZmWw,7246
|
|
11
|
+
localcoder-0.1.0.dist-info/METADATA,sha256=FOdoZ3sHADRJShBvD6-TaQO1hsQM5u-j3K-25_Rb9P0,6684
|
|
12
|
+
localcoder-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
13
|
+
localcoder-0.1.0.dist-info/entry_points.txt,sha256=svs7yRCAJO8U8945pL-hic2eQnMfqRQx8v_m9U5J5Xo,51
|
|
14
|
+
localcoder-0.1.0.dist-info/licenses/LICENSE,sha256=7KCxSOg3vOVwKw_kVsnzWCY7y0FNv4X_a0r__G0Q6hY,95
|
|
15
|
+
localcoder-0.1.0.dist-info/RECORD,,
|