mlx-code 0.0.19__tar.gz → 0.0.22__tar.gz

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.
Files changed (33) hide show
  1. mlx_code-0.0.22/PKG-INFO +552 -0
  2. mlx_code-0.0.22/README.md +514 -0
  3. mlx_code-0.0.22/mlx_code/bare.py +484 -0
  4. mlx_code-0.0.22/mlx_code/bats.py +300 -0
  5. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/gits.py +7 -1
  6. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/main.py +74 -12
  7. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/repl.py +152 -117
  8. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/view_log.py +1 -1
  9. mlx_code-0.0.22/mlx_code/web.py +485 -0
  10. mlx_code-0.0.22/mlx_code.egg-info/PKG-INFO +552 -0
  11. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code.egg-info/SOURCES.txt +3 -0
  12. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code.egg-info/requires.txt +2 -0
  13. {mlx_code-0.0.19 → mlx_code-0.0.22}/setup.py +3 -1
  14. mlx_code-0.0.22/tests/test.py +668 -0
  15. mlx_code-0.0.19/PKG-INFO +0 -226
  16. mlx_code-0.0.19/README.md +0 -190
  17. mlx_code-0.0.19/mlx_code.egg-info/PKG-INFO +0 -226
  18. mlx_code-0.0.19/tests/test.py +0 -218
  19. {mlx_code-0.0.19 → mlx_code-0.0.22}/LICENSE +0 -0
  20. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/__init__.py +0 -0
  21. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/apis.py +0 -0
  22. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/lsp_tool.py +0 -0
  23. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/mcb.py +0 -0
  24. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/mcb_tool.py +0 -0
  25. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/stream_log.py +0 -0
  26. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/tools.py +0 -0
  27. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/util.py +0 -0
  28. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code/view_git.py +0 -0
  29. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code.egg-info/dependency_links.txt +0 -0
  30. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code.egg-info/entry_points.txt +0 -0
  31. {mlx_code-0.0.19 → mlx_code-0.0.22}/mlx_code.egg-info/top_level.txt +0 -0
  32. {mlx_code-0.0.19 → mlx_code-0.0.22}/setup.cfg +0 -0
  33. {mlx_code-0.0.19 → mlx_code-0.0.22}/tests/__init__.py +0 -0
@@ -0,0 +1,552 @@
1
+ Metadata-Version: 2.4
2
+ Name: mlx-code
3
+ Version: 0.0.22
4
+ Summary: Coding Agent for Mac
5
+ Home-page: https://josefalbers.github.io/mlx-code/
6
+ Author: J Joe
7
+ Author-email: albersj66@gmail.com
8
+ License: Apache-2.0
9
+ Project-URL: Source, https://github.com/JosefAlbers/mlx-code
10
+ Project-URL: Issues, https://github.com/JosefAlbers/mlx-code/issues
11
+ Project-URL: Documentation, https://josefalbers.github.io/mlx-code/
12
+ Requires-Python: >=3.12.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: mlx-lm>=0.31.3; platform_system == "Darwin"
16
+ Requires-Dist: httpx
17
+ Requires-Dist: pydantic
18
+ Requires-Dist: textual>=8.2.7
19
+ Requires-Dist: rich>=15.0.0
20
+ Requires-Dist: starlette
21
+ Requires-Dist: uvicorn
22
+ Provides-Extra: all
23
+ Requires-Dist: python-lsp-server[all]; extra == "all"
24
+ Requires-Dist: GitPython; extra == "all"
25
+ Requires-Dist: pygments; extra == "all"
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: description
29
+ Dynamic: description-content-type
30
+ Dynamic: home-page
31
+ Dynamic: license
32
+ Dynamic: license-file
33
+ Dynamic: project-url
34
+ Dynamic: provides-extra
35
+ Dynamic: requires-dist
36
+ Dynamic: requires-python
37
+ Dynamic: summary
38
+
39
+ # mlx-code
40
+
41
+ A Git-native coding agent that can run entirely on your Mac. No API keys, no cloud, and no data leaving your machine. Powered by Apple MLX, it turns commits, branches, and worktrees into the agent’s state, history, and execution model
42
+
43
+ [![v0.0.27](https://github.com/user-attachments/assets/8a1c131a-dda1-4b52-9fa6-9c0fbccb5ea6)](https://youtube.com/shorts/1LuifKFKixc)
44
+
45
+ ---
46
+
47
+ ## Architecture
48
+
49
+ ```
50
+ Worktrees:
51
+
52
+ main ──●──●──●──●──●──●──●──●──●──●──●──●──●──●───────────► Node = git commit + chat hx
53
+ │ │
54
+ │ └── branch-1 ──●──●──●
55
+ │ │ ┌────────────┐
56
+ │ └─┤ branch-1-0 ├──●──●
57
+ │ └─────┬──────┘
58
+ └── branch-0 ──●──●──● │
59
+
60
+ Tabs: ├────────────► Tab = git branch + Agent
61
+
62
+ ┌──────────────────────────────────────────────│─────────┐
63
+ │ TUI tabs │ │
64
+ │ ┌──────┐ ┌──────────┐ ┌──────────┐ ┌─────┴──────┐ │
65
+ │ │ main │ │ branch-0 │ │ branch-1 │ │ branch-1-0 │ │
66
+ │ └──────┘ └────┬─────┘ └──────────┘ └────────────┘ │
67
+ └─────────────────│──────────────────────────────────────┘
68
+
69
+ Agents: ├─────────────────────────────────────────► Each tab runs its own Agent
70
+
71
+ ┌────┴─────────────────────────────────────┐
72
+ │ Agent │
73
+ │ ┌────────────────┐ ┌────────────────┐ │
74
+ │ │ API: │ │ Tools: │ │
75
+ │ │ Local (mlx-lm) │ │ Read Write │ │
76
+ │ │ Gemini │ │ Edit Bash │ │
77
+ │ │ Claude │ │ Grep Find │ │
78
+ │ │ Codex │ │ Ls Skill │ │
79
+ │ │ DeepSeek │ │ Agent ─────────┼──┼───► Recursively spawns sub-Agents
80
+ │ └────────────────┘ └────────────────┘ │
81
+ │ Git worktree │
82
+ │ (isolation + session state) │
83
+ └──────────────────────────────────────────┘
84
+ ```
85
+
86
+ Each layer is importable and composable on its own. A commit records state, a branch records an alternative path, and a tab is just a live view over an `Agent`.
87
+
88
+ ```python
89
+ from mlx_code.repl import Agent
90
+ from mlx_code.tools import ReadTool, WriteTool, EditTool
91
+
92
+ agent = Agent(api='claude', tool_names=['Read', 'Write', 'Edit'])
93
+ result = await agent.run('refactor utils.py to use dataclasses')
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Core ideas
99
+
100
+ - **Git is the state machine.** Every file-changing agent step is committed with the conversation that produced it, so you can inspect, resume, and branch from any checkpoint.
101
+ - **Branches are alternative futures.** A branch is not just a Git branch; it is a different reasoning path with its own worktree and session state.
102
+ - **Agents are the primitive.** Tabs, branches, and delegated subtasks are all instances of the same `Agent` abstraction.
103
+ - **Worktrees provide isolation.** The agent edits in a separate worktree, so your main checkout stays clean and recoverable.
104
+
105
+ ---
106
+
107
+ ## Quick start
108
+
109
+ ```bash
110
+ # ephemeral run (no installation)
111
+ uvx --from mlx-code mlc
112
+
113
+ # or install into the current environment
114
+ pip install mlx-code
115
+
116
+ # launch
117
+ mlc # with a local MLX model
118
+ mlc-run --api gemini # or use a remote provider
119
+ ```
120
+
121
+ That's it. The first run starts a local inference server and drops you into the REPL.
122
+
123
+ ---
124
+
125
+ ## Why mlx-code
126
+
127
+ **Agents as reusable workflow atoms.** Tabs, branches, and tasks are all managed within instances of `Agent`. Each one gets its own conversation, its own tools, and its own worktree. Agents can spawn sub-agents to delegate subtasks, and each child is a full agent with its own scoped tool set.
128
+
129
+ **Git is the database.** When the agent makes file changes, they’re committed to a git worktree with the full conversation embedded in the commit message. Resume any past session by hash, branch from any checkpoint, and inspect the agent timeline with `git log`. No proprietary state files, just Git.
130
+
131
+ **Built-in safety nets.** Your working directory is never at risk. The agent operates inside a `git worktree`, not your checkout. It can make a mess, and you can inspect or discard it without ever touching `main`. Subprocess environment variables go through an explicit allowlist, so secrets in your shell are never leaked to agent-spawned processes.
132
+
133
+ **Batteries included.** Everything ships in one pip install: the MLX inference engine, the multi-protocol API server, the agent loop, the tools, and the TUI. No llama.cpp, no ollama, no vLLM bridge to find and configure. And the server natively speaks OpenAI, Anthropic, Gemini, and Codex wire formats simultaneously, so `claude`, `codex`, and `gemini` CLIs can all work against your local model without a translation layer.
134
+
135
+ **Continuous batching.** The local inference server runs a continuous batching engine that processes multiple sequences concurrently. When you spawn parallel agents (eg, multiple tabs, `asyncio.gather` pipelines, or delegated sub-tasks) they all share the same GPU context and are stepped together each tick. A prefix cache persists KV snapshots to disk, so repeated system prompts and conversation prefixes are prefilled once and reused across sessions. No request queueing, no waiting for the previous agent to finish.
136
+
137
+ ---
138
+
139
+ ## Agent primitive
140
+
141
+ Every surface in mlx-code composes the same abstraction:
142
+
143
+ | Surface | What it does | How it creates an Agent |
144
+ |---------|-------------|------------------------|
145
+ | Python API | Programmatic pipeline | `Agent(...)` |
146
+ | Agent tool | Model delegates a subtask | `agent.spawn()` |
147
+ | `/branch` | Fork from any checkpoint | `agent.branch()` |
148
+ | TUI tab | Parallel conversation thread | `Tab('title', Agent(...))` |
149
+
150
+ They're all the same object. A branch is an agent. A sub-task is an agent. A tab is an agent in a tab container. This means patterns compose: a branched agent can spawn sub-agents, a sub-agent can be branched, and any agent can be inspected, diffed, or resumed because it's backed by git.
151
+
152
+ ---
153
+
154
+ ## Sessions as git history
155
+
156
+ When the agent makes file changes, they're committed to the worktree with the full conversation embedded in the commit message. This means you can always pick up where you left off:
157
+
158
+ ```bash
159
+ # Resume a session from any commit hash
160
+ mlc --resume abc1234
161
+ ```
162
+
163
+ ```python
164
+ # Or from Python
165
+ from mlx_code.gits import resume_worktree
166
+ from mlx_code.repl import Agent
167
+
168
+ gwt, messages = resume_worktree(".", "abc1234")
169
+ agent = Agent(ctx={"gwt": gwt})
170
+ agent.messages = messages
171
+ await agent.run("now add unit tests")
172
+ ```
173
+
174
+ Branch from any point in the conversation. Each branch gets its own worktree:
175
+
176
+ ```
177
+ /branch # branch from current state
178
+ /branch --rev 2 # branch from the 2nd user turn
179
+ /branch --rev 3 make it use httpx instead
180
+ ```
181
+
182
+ Since it's just git, you can inspect the timeline outside the REPL:
183
+
184
+ ```bash
185
+ git log --oneline # commits = agent turns that changed files
186
+ git diff HEAD~1 # what the agent changed
187
+ git worktree list # all active worktrees
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Swapping agents for different phases
193
+
194
+ Coding is a pipeline: spec, draft, review, verify. Each phase benefits from a different mind: a planner needs broad context and no write access; a coder needs tight constraints and fast iteration; a reviewer needs read-only access and a critical eye.
195
+
196
+ mlx-code lets you hot-swap the agent configuration mid-session. The conversation continues, but the system prompt, model, and tool set change:
197
+
198
+ ```
199
+ /clear --config reviewer.yaml
200
+ ```
201
+
202
+ ```yaml
203
+ # reviewer.yaml
204
+ model: gemini-3.1-flash-lite
205
+ api: gemini
206
+ system: |
207
+ Do NOT make edits. Only comment.
208
+ Challenge incorrect assumptions.
209
+ Identify edge cases and failure modes.
210
+ Prefer robust solutions over quick hacks.
211
+ Keep implementations simple.
212
+ Avoid introducing dependencies unless they provide clear value.
213
+ Ask when unsure.
214
+ tools:
215
+ - Read
216
+ - Grep
217
+ - Bash
218
+ ```
219
+
220
+ ```yaml
221
+ # coder.yaml
222
+ model: deepseek-v4-flash
223
+ api: deepseek
224
+ system: |
225
+ Read first. Change second.
226
+ Understand the relevant files before editing.
227
+ Make focused, minimal changes.
228
+ Follow existing code style and architecture.
229
+ Do not rewrite working code unnecessarily.
230
+ Fix root causes rather than symptoms.
231
+ After coding, verify that the solution is consistent with the requirements and surrounding code.
232
+ tools:
233
+ - Read
234
+ - Write
235
+ - Edit
236
+ - Bash
237
+ - Grep
238
+ ```
239
+
240
+ Reliability comes from specialization plus constraint. A read-only reviewer can't silently break your code. A scoped implementer can't wander off into architecture discussions. Each agent does one thing well.
241
+
242
+ ---
243
+
244
+ ## Continuous batching
245
+
246
+ The local server can run multiple inference sequences concurrently inside a single batch step. Instead of a global lock that serialises one request at a time, the batching engine maintains a live set of active sequences and yields tokens for all of them on every step.
247
+
248
+ ```bash
249
+ mlc --engine batch # continuous batching + built-in REPL
250
+ ```
251
+
252
+ This unlocks true parallelism for multi-agent workloads:
253
+
254
+ ```python
255
+ import asyncio
256
+ from mlx_code.repl import Agent
257
+
258
+ async def main():
259
+ agents = [Agent() for _ in range(4)]
260
+ await asyncio.gather(*[
261
+ a.run(f"Research topic: {t}")
262
+ for a, t in zip(agents, ["consensus", "cryptography", "networking", "storage"])
263
+ ])
264
+
265
+ asyncio.run(main())
266
+ ```
267
+
268
+ All four agents generate simultaneously inside the same batch. No sequential blocking.
269
+
270
+ ### Health endpoint
271
+
272
+ ```bash
273
+ curl http://127.0.0.1:8000/health
274
+ # {"status":"ok","model":"mlx-community/Qwen3.5-4B-OptiQ-4bit","active_sequences":2,"prefix_cache_files":5}
275
+ ```
276
+
277
+ `active_sequences` shows how many agents are generating right now; `prefix_cache_files` shows how many prefix KV snapshots are stored on disk.
278
+
279
+ ---
280
+
281
+ ## Command Line
282
+
283
+ ### `mlc`: local server + harness
284
+
285
+ Starts the MLX inference server and launches the built-in TUI harness against it.
286
+
287
+ ```bash
288
+ # Default: local server + default harness
289
+ mlc
290
+
291
+ # Continuous batching mode (default is sequential caching mode)
292
+ mlc --engine batch
293
+
294
+ # Server only, no harness
295
+ mlc --leash none
296
+
297
+ # Use a different harness (routes traffic through the local server)
298
+ mlc --leash claude
299
+ mlc --leash gemini
300
+ mlc --leash codex
301
+
302
+ # Specify a model
303
+ mlc --model mlx-community/Qwen3.5-4B-OptiQ-4bit
304
+
305
+ # Restrict the tools available to the agent
306
+ mlc --tools Read Write Bash
307
+
308
+ # Custom system prompt
309
+ mlc --system "You are a helpful assistant."
310
+
311
+ # Load skills from a directory (scans recursively for SKILL.md files)
312
+ mlc --skill ./my-skills
313
+
314
+ # Resume a previous session from a git commit hash
315
+ mlc --resume <commit-hash>
316
+
317
+ # Send an initial prompt automatically when the REPL starts
318
+ mlc --prompt "summarise all changes in the last 7 days"
319
+
320
+ # Stream the agent log to a file (useful for monitoring long runs)
321
+ mlc --stream agent.log
322
+
323
+ # Bind to a specific host/port (default: 127.0.0.1:8000, auto-increments if busy)
324
+ mlc --host 0.0.0.0 --port 9000
325
+ ```
326
+
327
+ Because `mlc` reads from stdin when it isn’t a TTY, it composes naturally with shell pipes:
328
+
329
+ ```bash
330
+ echo "Here's the solution you proposed: <excerpt>$(mlc -p "write code for a chrome extension to play youtube x5 speed")</excerpt> Now argue against it." | mlc
331
+ ```
332
+
333
+ ### `mlc-run`: harness only
334
+
335
+ Runs the agent harness against an already-running server or a remote provider.
336
+
337
+ ```bash
338
+ # Connect to a local server at 127.0.0.1:8000 (default)
339
+ mlc-run
340
+
341
+ # Remote providers
342
+ mlc-run --api claude
343
+ mlc-run --api gemini
344
+ mlc-run --api deepseek
345
+ mlc-run --api deepseek --model deepseek-v4-pro
346
+ mlc-run --api codex
347
+
348
+ # Custom endpoint
349
+ echo "explain lsp.py" | mlc-run -a deepseek | cat - PLAN.md | mlc-run --url http://localhost:9000
350
+
351
+ # Simple terminal REPL (no TUI)
352
+ mlc-run --bare
353
+ ```
354
+
355
+ ---
356
+
357
+ ## Using as a Library
358
+
359
+ Import the pieces you need to build background workers, scheduled jobs, or event-triggered handlers.
360
+
361
+ ### Spawn an agent from Python
362
+
363
+ ```python
364
+ import asyncio
365
+ from mlx_code.repl import Agent
366
+
367
+ async def main():
368
+ agent = Agent(system="You are a concise technical writer.")
369
+ await agent.run("Summarise all *.py files changed in the last 7 days. Save to digest.md.")
370
+
371
+ asyncio.run(main())
372
+ ```
373
+
374
+ ### Multi-agent pipeline
375
+
376
+ ```python
377
+ import asyncio
378
+ from mlx_code.repl import Agent
379
+
380
+ async def main():
381
+ researcher = Agent(system="You are a research assistant.")
382
+ await researcher.run("Research PBFT consensus. Save a structured summary to kb/draft.md.")
383
+
384
+ reviewer = Agent(system="You are a critical reviewer.")
385
+ await reviewer.run(
386
+ "Read kb/draft.md. Write a one-paragraph critique to kb/critique.md. "
387
+ "Use only information in that file."
388
+ )
389
+
390
+ asyncio.run(main())
391
+ ```
392
+
393
+ ### Parallel workers with `asyncio.gather`
394
+
395
+ ```python
396
+ import asyncio
397
+ from mlx_code.repl import Agent
398
+
399
+ async def main():
400
+ topics = ["history", "algorithms", "industry_usage"]
401
+ agents = [Agent() for _ in topics]
402
+ await asyncio.gather(*[
403
+ a.run(f"Research the {t} of Byzantine Fault Tolerance. Save to kb/{t}.md.")
404
+ for a, t in zip(agents, topics)
405
+ ])
406
+ reducer = Agent()
407
+ await reducer.run("Read all files in kb/. Synthesise into final_report.md.")
408
+
409
+ asyncio.run(main())
410
+ ```
411
+
412
+ ### Branch an agent
413
+
414
+ ```python
415
+ child = agent.branch() # deep-copies messages; independent worktree
416
+ await child.run("Try an alternative approach and save to alt.py.")
417
+ ```
418
+
419
+ ### Resume a session from a git commit
420
+
421
+ mlx-code stores the full conversation as JSON in each commit message, so you can restore both the workspace state and the agent's memory from any checkpoint.
422
+
423
+ ```python
424
+ import asyncio
425
+ from mlx_code.gits import resume_worktree
426
+ from mlx_code.repl import Agent, repl
427
+
428
+ async def main():
429
+ gwt, messages = resume_worktree(".", "abc1234")
430
+ agent = Agent(ctx={"gwt": gwt})
431
+ agent.messages = messages
432
+ await repl(agent)
433
+
434
+ asyncio.run(main())
435
+ ```
436
+
437
+ ### Load agent config from a file
438
+
439
+ Pass a JSON or YAML file to reconfigure the agent at runtime (also available as `/clear --config F` in the TUI).
440
+
441
+ ```python
442
+ from mlx_code.repl import load_agent_config
443
+ config = load_agent_config("agent.yaml")
444
+ agent = Agent(**config)
445
+ ```
446
+
447
+ ### Custom tools
448
+
449
+ Subclass `Tool`, define a Pydantic schema, and pass the class at instantiation.
450
+
451
+ ```python
452
+ from mlx_code.tools import Tool
453
+ from mlx_code.repl import Agent
454
+ from pydantic import BaseModel, Field
455
+
456
+ class QueryParams(BaseModel):
457
+ query: str = Field(description="SQL query to run")
458
+
459
+ class LiveDBTool(Tool):
460
+ name = "QueryDB"
461
+ description = "Execute a query against the dev database"
462
+ parameters = QueryParams
463
+
464
+ async def execute(self, params: QueryParams, signal=None) -> dict:
465
+ result = run_query(params.query) # your logic here
466
+ return {"content": [{"type": "text", "text": result}], "is_error": False}
467
+
468
+ agent = Agent(extra_tool_classes=[LiveDBTool], tool_names=["QueryDB"])
469
+ ```
470
+
471
+ ## Reference
472
+
473
+ ### Commands
474
+
475
+ | Command | Description |
476
+ |---|---|
477
+ | `/branch [--rev N] [prompt]` | Open a new branch tab from the current (or earlier) checkpoint |
478
+ | `/diff [--all]` | Show a side-by-side diff of changes in the worktree |
479
+ | `/clear [--config F]` | Clear conversation; `--config` reloads agent from a JSON/YAML file |
480
+ | `/tab [N]` | Jump to tab N |
481
+ | `/history [--raw]` | Show conversation transcript; `--raw` shows the raw API message log |
482
+ | `/tools` | List active tools |
483
+ | `/abort` | Abort the running agent |
484
+ | `/errors` | Show timestamped error log for the current tab |
485
+ | `/export [path]` | Export session to JSON |
486
+ | `/exit [--all]` | Close branch tab, or exit the app |
487
+ | `/help` | Show command reference |
488
+ | `!command` | Run a shell command; output captured in the TUI (eg, `ls`, `cat hello.c`) |
489
+ | `$command` | Run an interactive command (eg, `vim`, `yazi`, `less hello.c`) |
490
+
491
+ ### Key bindings
492
+
493
+ | Key | Action |
494
+ |---|---|
495
+ | `Enter` | Submit |
496
+ | `Ctrl-J` | Insert newline |
497
+ | `Ctrl-1` … `Ctrl-9` | Jump to tab N |
498
+ | `Ctrl-,` / `Ctrl-.` | Cycle through tabs |
499
+ | `Ctrl-C` | Clear input, or abort running agent |
500
+ | `Ctrl-D` | Close branch tab, or exit app |
501
+ | `Ctrl-R` | Recall last prompt into editor |
502
+
503
+ ### Tools
504
+
505
+ | Tool | What it does |
506
+ |------|-------------|
507
+ | `Read` | Read file with optional offset/limit for large files |
508
+ | `Write` | Create or overwrite a file |
509
+ | `Edit` | Replace an exact unique string in a file |
510
+ | `Bash` | Run a shell command with timeout and abort support |
511
+ | `Grep` | Search files by pattern, respects .gitignore |
512
+ | `Find` | Find files/dirs by name glob, respects .gitignore |
513
+ | `Ls` | List directory contents, respects .gitignore |
514
+ | `Skill` | Retrieve named skill instructions from config |
515
+ | `Agent` | Spawn an autonomous sub-agent for delegated work |
516
+
517
+ All file tools enforce path sandboxing. The agent cannot read or write outside the worktree.
518
+
519
+ ### Backends
520
+
521
+ | Backend | Flag | Notes |
522
+ |---------|------|-------|
523
+ | MLX-LM (local) | `--api noapi` | Default. Runs on-device, no API key needed |
524
+ | Claude | `--api claude` | Requires `ANTHROPIC_API_KEY` |
525
+ | Gemini | `--api gemini` | Requires `GOOGLE_API_KEY` |
526
+ | DeepSeek | `--api deepseek` | Requires `DEEPSEEK_API_KEY` |
527
+ | Codex | `--api codex` | OpenAI Codex CLI integration |
528
+ | OpenAI | `--api openai` | Any OpenAI-compatible endpoint |
529
+
530
+ ### Frontends
531
+
532
+ The local MLX server speaks OpenAI, Anthropic, and Gemini wire formats simultaneously, so you can use any compatible CLI as the frontend:
533
+
534
+ ```bash
535
+ mlc # default
536
+ mlc --web # web UI (api.mlx-code.com)
537
+ mlc --bare # no TUI
538
+ mlc --leash none # no harness
539
+ mlc --leash codex # codex CLI
540
+ mlc --leash gemini # gemini CLI
541
+ mlc --leash claude # claude code
542
+ ```
543
+
544
+ ---
545
+
546
+ ## Credits
547
+
548
+ Built on [mlx](https://github.com/ml-explore/mlx) and [mlx-lm](https://github.com/ml-explore/mlx-lm). Inspired by Mario Zechner's [pi](https://github.com/badlogic/pi-mono).
549
+
550
+ ## License
551
+
552
+ Apache License 2.0: see [LICENSE](LICENSE) for details.