mlx-code 0.0.9__tar.gz → 0.0.10__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.
- {mlx_code-0.0.9 → mlx_code-0.0.10}/PKG-INFO +24 -27
- {mlx_code-0.0.9 → mlx_code-0.0.10}/README.md +23 -26
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/main.py +14 -14
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/mcb.py +1 -1
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/mcb_tool.py +4 -4
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/repl.py +21 -19
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/stream_log.py +4 -1
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/tools.py +13 -12
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code.egg-info/PKG-INFO +24 -27
- {mlx_code-0.0.9 → mlx_code-0.0.10}/setup.py +6 -9
- {mlx_code-0.0.9 → mlx_code-0.0.10}/LICENSE +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/__init__.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/apis.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/gits.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/lsp_tool.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/util.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/view_git.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code/view_log.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code.egg-info/SOURCES.txt +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code.egg-info/dependency_links.txt +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code.egg-info/entry_points.txt +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code.egg-info/requires.txt +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/mlx_code.egg-info/top_level.txt +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/setup.cfg +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/tests/__init__.py +0 -0
- {mlx_code-0.0.9 → mlx_code-0.0.10}/tests/test.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mlx-code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.10
|
|
4
4
|
Summary: Coding Agent for Mac
|
|
5
5
|
Home-page: https://github.com/JosefAlbers/mlx-code
|
|
6
6
|
Author: J Joe
|
|
@@ -31,7 +31,7 @@ Dynamic: summary
|
|
|
31
31
|
|
|
32
32
|
A lightweight coding agent built on Apple's MLX framework.
|
|
33
33
|
|
|
34
|
-

|
|
34
|
+
[](https://youtu.be/0lkY7YQCyCo)
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
@@ -48,68 +48,65 @@ A lightweight coding agent built on Apple's MLX framework.
|
|
|
48
48
|
## Quick Start
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
pip install mlx-code
|
|
52
|
-
|
|
51
|
+
pip install mlx-code
|
|
52
|
+
mlc
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
57
57
|
## Command Line
|
|
58
58
|
|
|
59
|
-
### `
|
|
59
|
+
### `mlc`: local server + harness
|
|
60
60
|
|
|
61
61
|
Starts the MLX inference server and launches a harness against it.
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
64
|
# Default: local MLX server + built-in REPL harness
|
|
65
|
-
|
|
65
|
+
mlc
|
|
66
66
|
|
|
67
67
|
# Use a different harness (routes traffic through the local server)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
mlc --leash claude
|
|
69
|
+
mlc --leash gemini
|
|
70
|
+
mlc --leash codex
|
|
71
71
|
|
|
72
72
|
# Server only, no harness
|
|
73
|
-
|
|
73
|
+
mlc --leash none
|
|
74
74
|
|
|
75
75
|
# Specify a model
|
|
76
|
-
|
|
76
|
+
mlc --model mlx-community/Qwen3.5-4B-OptiQ-4bit
|
|
77
77
|
|
|
78
78
|
# Restrict the tools available to the agent
|
|
79
|
-
|
|
79
|
+
mlc --tools Read Write Bash
|
|
80
80
|
|
|
81
81
|
# Custom system prompt
|
|
82
|
-
|
|
82
|
+
mlc --system "You are a helpful assistant."
|
|
83
83
|
|
|
84
84
|
# Load skills from a directory (scans recursively for SKILL.md files)
|
|
85
|
-
|
|
85
|
+
mlc --skill ./my-skills
|
|
86
86
|
|
|
87
87
|
# Resume a previous session from a git commit hash
|
|
88
|
-
|
|
88
|
+
mlc --resume <commit-hash>
|
|
89
89
|
|
|
90
|
-
# Because `
|
|
91
|
-
echo "
|
|
90
|
+
# Because `mlc` reads from stdin when it isn't a TTY, it composes naturally with shell pipes:
|
|
91
|
+
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. What are the edge cases this doesn't handle? What assumptions did you make that might not hold in a production system? What would you change if you knew this code would be read by a senior engineer in a security audit?" | mlc
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
### `
|
|
94
|
+
### `mlc-run`: harness only
|
|
95
95
|
|
|
96
96
|
Runs the agent harness against an already-running server or a remote provider.
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
# Connect to a local server at 127.0.0.1:8000 (default)
|
|
100
|
-
|
|
100
|
+
mlc-run
|
|
101
101
|
|
|
102
102
|
# Remote providers
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
mlc-run --api claude
|
|
104
|
+
mlc-run --api gemini
|
|
105
|
+
mlc-run --api deepseek --model deepseek-v4-pro
|
|
106
|
+
mlc-run --api codex
|
|
107
107
|
|
|
108
108
|
# Custom endpoint
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# With skills
|
|
112
|
-
mlxc-run --skill ./my-skills
|
|
109
|
+
echo "explain lsp.py" | mlc-run -a deepseek | cat - PLAN.md | mlc-run --url http://localhost:9000
|
|
113
110
|
```
|
|
114
111
|
|
|
115
112
|
---
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A lightweight coding agent built on Apple's MLX framework.
|
|
4
4
|
|
|
5
|
-

|
|
5
|
+
[](https://youtu.be/0lkY7YQCyCo)
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -19,68 +19,65 @@ A lightweight coding agent built on Apple's MLX framework.
|
|
|
19
19
|
## Quick Start
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
pip install mlx-code
|
|
23
|
-
|
|
22
|
+
pip install mlx-code
|
|
23
|
+
mlc
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
28
|
## Command Line
|
|
29
29
|
|
|
30
|
-
### `
|
|
30
|
+
### `mlc`: local server + harness
|
|
31
31
|
|
|
32
32
|
Starts the MLX inference server and launches a harness against it.
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
# Default: local MLX server + built-in REPL harness
|
|
36
|
-
|
|
36
|
+
mlc
|
|
37
37
|
|
|
38
38
|
# Use a different harness (routes traffic through the local server)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
mlc --leash claude
|
|
40
|
+
mlc --leash gemini
|
|
41
|
+
mlc --leash codex
|
|
42
42
|
|
|
43
43
|
# Server only, no harness
|
|
44
|
-
|
|
44
|
+
mlc --leash none
|
|
45
45
|
|
|
46
46
|
# Specify a model
|
|
47
|
-
|
|
47
|
+
mlc --model mlx-community/Qwen3.5-4B-OptiQ-4bit
|
|
48
48
|
|
|
49
49
|
# Restrict the tools available to the agent
|
|
50
|
-
|
|
50
|
+
mlc --tools Read Write Bash
|
|
51
51
|
|
|
52
52
|
# Custom system prompt
|
|
53
|
-
|
|
53
|
+
mlc --system "You are a helpful assistant."
|
|
54
54
|
|
|
55
55
|
# Load skills from a directory (scans recursively for SKILL.md files)
|
|
56
|
-
|
|
56
|
+
mlc --skill ./my-skills
|
|
57
57
|
|
|
58
58
|
# Resume a previous session from a git commit hash
|
|
59
|
-
|
|
59
|
+
mlc --resume <commit-hash>
|
|
60
60
|
|
|
61
|
-
# Because `
|
|
62
|
-
echo "
|
|
61
|
+
# Because `mlc` reads from stdin when it isn't a TTY, it composes naturally with shell pipes:
|
|
62
|
+
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. What are the edge cases this doesn't handle? What assumptions did you make that might not hold in a production system? What would you change if you knew this code would be read by a senior engineer in a security audit?" | mlc
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
### `
|
|
65
|
+
### `mlc-run`: harness only
|
|
66
66
|
|
|
67
67
|
Runs the agent harness against an already-running server or a remote provider.
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
70
|
# Connect to a local server at 127.0.0.1:8000 (default)
|
|
71
|
-
|
|
71
|
+
mlc-run
|
|
72
72
|
|
|
73
73
|
# Remote providers
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
mlc-run --api claude
|
|
75
|
+
mlc-run --api gemini
|
|
76
|
+
mlc-run --api deepseek --model deepseek-v4-pro
|
|
77
|
+
mlc-run --api codex
|
|
78
78
|
|
|
79
79
|
# Custom endpoint
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# With skills
|
|
83
|
-
mlxc-run --skill ./my-skills
|
|
80
|
+
echo "explain lsp.py" | mlc-run -a deepseek | cat - PLAN.md | mlc-run --url http://localhost:9000
|
|
84
81
|
```
|
|
85
82
|
|
|
86
83
|
---
|
|
@@ -879,7 +879,7 @@ def generate_step(
|
|
|
879
879
|
y, logprobs = (next_y, next_logprobs)
|
|
880
880
|
if n <= _tl:
|
|
881
881
|
_td.append(_yi)
|
|
882
|
-
if is_stuck(_td) or
|
|
882
|
+
if (is_stuck(_td) or n == _tl) and _te not in _td:
|
|
883
883
|
y = mx.array([_te])
|
|
884
884
|
_tl = -1
|
|
885
885
|
n += 1
|
|
@@ -1505,8 +1505,19 @@ def serve(
|
|
|
1505
1505
|
|
|
1506
1506
|
|
|
1507
1507
|
def main():
|
|
1508
|
-
parser = argparse.ArgumentParser(
|
|
1509
|
-
|
|
1508
|
+
parser = argparse.ArgumentParser(description="mlx-code MAIN")
|
|
1509
|
+
parser.add_argument(
|
|
1510
|
+
"-p",
|
|
1511
|
+
"--prompt",
|
|
1512
|
+
default=None,
|
|
1513
|
+
help="Initial prompt sent automatically when the REPL starts",
|
|
1514
|
+
)
|
|
1515
|
+
parser.add_argument(
|
|
1516
|
+
"-r",
|
|
1517
|
+
"--resume",
|
|
1518
|
+
default=None,
|
|
1519
|
+
metavar="COMMIT",
|
|
1520
|
+
help="Resume a previous session from the given git commit hash",
|
|
1510
1521
|
)
|
|
1511
1522
|
parser.add_argument(
|
|
1512
1523
|
"-m",
|
|
@@ -1567,17 +1578,6 @@ def main():
|
|
|
1567
1578
|
],
|
|
1568
1579
|
help="Regex patterns stripped from model output before it is returned to the client",
|
|
1569
1580
|
)
|
|
1570
|
-
parser.add_argument(
|
|
1571
|
-
"--prompt",
|
|
1572
|
-
default=None,
|
|
1573
|
-
help="Initial prompt sent automatically when the REPL starts",
|
|
1574
|
-
)
|
|
1575
|
-
parser.add_argument(
|
|
1576
|
-
"--resume",
|
|
1577
|
-
default=None,
|
|
1578
|
-
metavar="COMMIT",
|
|
1579
|
-
help="Resume a previous session from the given git commit hash",
|
|
1580
|
-
)
|
|
1581
1581
|
parser.add_argument("--stream", default=None, help="File to stream log into")
|
|
1582
1582
|
args, leash_args = parser.parse_known_args()
|
|
1583
1583
|
logger.debug(f"args={args!r} leash_args={leash_args!r}")
|
|
@@ -38,9 +38,9 @@ class CommentKBTool(Tool):
|
|
|
38
38
|
dt = self.ctx.get("dt")
|
|
39
39
|
if dt is None:
|
|
40
40
|
return tout("No knowledge base is available", True)
|
|
41
|
-
if params.
|
|
42
|
-
return tout(f"Comment not found: {params.
|
|
43
|
-
return tout(json.dumps({"id": dt.comment(params.content, to=params.
|
|
41
|
+
if params.parent not in dt.kb:
|
|
42
|
+
return tout(f"Comment not found: {params.parent}", True)
|
|
43
|
+
return tout(json.dumps({"id": dt.comment(params.content, to=params.parent)}))
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
class SubmitKBParams(BaseModel):
|
|
@@ -70,4 +70,4 @@ def system_prompt(dt):
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
ALL_TOOLS = [ReadKBTool, CommentKBTool, SubmitKBTool]
|
|
73
|
-
ALL_NAMES = [i.name for i in ALL_TOOLS]
|
|
73
|
+
ALL_NAMES = [i.name for i in ALL_TOOLS] + ["Agent"]
|
|
@@ -234,13 +234,13 @@ class Agent:
|
|
|
234
234
|
return msg
|
|
235
235
|
|
|
236
236
|
|
|
237
|
-
_REPL_HELP = "Commands:\n /help — show this message\n /clear — clear conversation history\n /history — print message history\n /tools — list active tools\n /branch — spawn a branched sub-agent and run a one-shot prompt\n /abort — signal abort after next tool call\n
|
|
237
|
+
_REPL_HELP = "Commands:\n /help — show this message\n /clear — clear conversation history\n /history — print message history\n /tools — list active tools\n /branch — spawn a branched sub-agent and run a one-shot prompt\n /abort — signal abort after next tool call\n /quit / exit — end the session\n"
|
|
238
238
|
import sys
|
|
239
239
|
import os
|
|
240
240
|
from contextlib import contextmanager
|
|
241
241
|
|
|
242
242
|
|
|
243
|
-
def read_input(prompt: str = "\x1b[32m
|
|
243
|
+
def read_input(prompt: str = "\x1b[32m≫ \x1b[0m") -> str:
|
|
244
244
|
if sys.platform == "win32":
|
|
245
245
|
return _read_input_win(prompt)
|
|
246
246
|
else:
|
|
@@ -416,7 +416,7 @@ def _read_input_win(prompt: str) -> str:
|
|
|
416
416
|
|
|
417
417
|
|
|
418
418
|
async def repl(agent, init_prompt=None) -> None:
|
|
419
|
-
is_tty = sys.stdin.isatty()
|
|
419
|
+
is_tty = sys.stdin.isatty() and sys.stdout.isatty()
|
|
420
420
|
loop = asyncio.get_running_loop()
|
|
421
421
|
_suppress = False
|
|
422
422
|
last_block = ""
|
|
@@ -467,9 +467,7 @@ async def repl(agent, init_prompt=None) -> None:
|
|
|
467
467
|
elif et == "tool_start":
|
|
468
468
|
name_part = "\x1b[1;43;30;1m" + p["name"] + "\x1b[0m"
|
|
469
469
|
args_part = (
|
|
470
|
-
" \x1b[
|
|
471
|
-
if p["args"]
|
|
472
|
-
else ""
|
|
470
|
+
" \x1b[33m" + json.dumps(p["args"]) + "\x1b[0m" if p["args"] else ""
|
|
473
471
|
)
|
|
474
472
|
emit(name_part + args_part + "\n", "tool")
|
|
475
473
|
elif et == "tool_end":
|
|
@@ -504,6 +502,8 @@ async def repl(agent, init_prompt=None) -> None:
|
|
|
504
502
|
else:
|
|
505
503
|
user_input = sys.stdin.read()
|
|
506
504
|
if not user_input:
|
|
505
|
+
if not is_tty:
|
|
506
|
+
break
|
|
507
507
|
continue
|
|
508
508
|
last_block = ""
|
|
509
509
|
logger.debug(user_input)
|
|
@@ -556,7 +556,7 @@ async def repl(agent, init_prompt=None) -> None:
|
|
|
556
556
|
print(f"Unknown command: {cmd} (try /help)")
|
|
557
557
|
continue
|
|
558
558
|
if is_tty:
|
|
559
|
-
if user_input.lower() in {"exit", "quit"}:
|
|
559
|
+
if user_input.lower() in {"exit", "/quit"}:
|
|
560
560
|
print("Bye!")
|
|
561
561
|
break
|
|
562
562
|
print("\x1b[34mπ\x1b[0m ", end="", flush=True)
|
|
@@ -682,6 +682,19 @@ def main():
|
|
|
682
682
|
|
|
683
683
|
setup_logger(log_file=".log.json")
|
|
684
684
|
parser = argparse.ArgumentParser(description="mlx-code REPL")
|
|
685
|
+
parser.add_argument(
|
|
686
|
+
"-p",
|
|
687
|
+
"--prompt",
|
|
688
|
+
default=None,
|
|
689
|
+
help="Initial prompt sent automatically when the REPL starts",
|
|
690
|
+
)
|
|
691
|
+
parser.add_argument(
|
|
692
|
+
"-r",
|
|
693
|
+
"--resume",
|
|
694
|
+
default=None,
|
|
695
|
+
metavar="COMMIT",
|
|
696
|
+
help="Resume a previous session from the given git commit hash",
|
|
697
|
+
)
|
|
685
698
|
parser.add_argument(
|
|
686
699
|
"-a",
|
|
687
700
|
"--api",
|
|
@@ -720,17 +733,6 @@ def main():
|
|
|
720
733
|
default=None,
|
|
721
734
|
help="API key; falls back to the relevant *_API_KEY env var",
|
|
722
735
|
)
|
|
723
|
-
parser.add_argument(
|
|
724
|
-
"--prompt",
|
|
725
|
-
default=None,
|
|
726
|
-
help="Initial prompt sent automatically when the REPL starts",
|
|
727
|
-
)
|
|
728
|
-
parser.add_argument(
|
|
729
|
-
"--resume",
|
|
730
|
-
default=None,
|
|
731
|
-
metavar="COMMIT",
|
|
732
|
-
help="Resume a previous session from the given git commit hash",
|
|
733
|
-
)
|
|
734
736
|
parser.add_argument("--stream", default=None, help="File to stream log into")
|
|
735
737
|
args = parser.parse_args()
|
|
736
738
|
logger.debug(args)
|
|
@@ -743,7 +745,7 @@ def main():
|
|
|
743
745
|
elif args.api == "gemini":
|
|
744
746
|
api_key = os.environ.get("GEMINI_API_KEY") if api_key is None else api_key
|
|
745
747
|
url = "https://generativelanguage.googleapis.com" if api_key else url
|
|
746
|
-
model = "gemini-3.1-flash-lite
|
|
748
|
+
model = "gemini-3.1-flash-lite" if model is None else model
|
|
747
749
|
tool_names = [] if tool_names is None else tool_names
|
|
748
750
|
run_repl(
|
|
749
751
|
api=args.api,
|
|
@@ -45,7 +45,10 @@ class StreamLogger:
|
|
|
45
45
|
self.fp.write(self._line_prefix())
|
|
46
46
|
self._at_line_start = False
|
|
47
47
|
self.fp.write(part)
|
|
48
|
-
|
|
48
|
+
try:
|
|
49
|
+
self.fp.flush()
|
|
50
|
+
except:
|
|
51
|
+
pass
|
|
49
52
|
|
|
50
53
|
@classmethod
|
|
51
54
|
def attach_to_child(cls, child_agent, parent_ctx, tool_name="sub"):
|
|
@@ -11,7 +11,7 @@ import logging
|
|
|
11
11
|
import random
|
|
12
12
|
from abc import ABC, abstractmethod
|
|
13
13
|
from typing import Any, Literal
|
|
14
|
-
from pydantic import BaseModel, Field, ValidationError
|
|
14
|
+
from pydantic import BaseModel, Field, ValidationError, field_validator
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
@@ -438,11 +438,19 @@ class AgentParams(BaseModel):
|
|
|
438
438
|
system: str | None = Field(
|
|
439
439
|
default=None, description="System prompt override. Defaults to parent."
|
|
440
440
|
)
|
|
441
|
-
tools: list[str]
|
|
442
|
-
|
|
443
|
-
description="Restrict tools for the sub-agent, e.g. ['Read', 'Bash']. Defaults to all parent tools.",
|
|
441
|
+
tools: list[str] = Field(
|
|
442
|
+
description="Tools available to the sub-agent. Must be an explicit subset of the parent's tools."
|
|
444
443
|
)
|
|
445
444
|
|
|
445
|
+
@field_validator("tools", mode="before")
|
|
446
|
+
@classmethod
|
|
447
|
+
def coerce_tools(cls, v):
|
|
448
|
+
if isinstance(v, str):
|
|
449
|
+
v = json.loads(v)
|
|
450
|
+
if not isinstance(v, list):
|
|
451
|
+
raise ValueError("tools must be a list of strings")
|
|
452
|
+
return v
|
|
453
|
+
|
|
446
454
|
|
|
447
455
|
class AgentTool(Tool):
|
|
448
456
|
name = "Agent"
|
|
@@ -451,19 +459,12 @@ class AgentTool(Tool):
|
|
|
451
459
|
|
|
452
460
|
async def execute(self, params: AgentParams, signal=None) -> dict:
|
|
453
461
|
parent = self.ctx["agent"]
|
|
454
|
-
tool_names: list[str] | None = None
|
|
455
|
-
if params.tools is not None:
|
|
456
|
-
raw = params.tools
|
|
457
|
-
if isinstance(raw, str):
|
|
458
|
-
raw = json.loads(raw)
|
|
459
|
-
tool_names = [t for t in raw if isinstance(t, str)]
|
|
460
462
|
overrides = {}
|
|
461
463
|
if params.api is not None:
|
|
462
464
|
overrides["api"] = params.api
|
|
463
465
|
if params.system is not None:
|
|
464
466
|
overrides["system"] = params.system
|
|
465
|
-
|
|
466
|
-
overrides["tool_names"] = tool_names
|
|
467
|
+
overrides["tool_names"] = params.tools
|
|
467
468
|
child = parent.spawn(**overrides)
|
|
468
469
|
if "_stream_log_fp" in parent.ctx:
|
|
469
470
|
from .stream_log import StreamLogger
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mlx-code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.10
|
|
4
4
|
Summary: Coding Agent for Mac
|
|
5
5
|
Home-page: https://github.com/JosefAlbers/mlx-code
|
|
6
6
|
Author: J Joe
|
|
@@ -31,7 +31,7 @@ Dynamic: summary
|
|
|
31
31
|
|
|
32
32
|
A lightweight coding agent built on Apple's MLX framework.
|
|
33
33
|
|
|
34
|
-

|
|
34
|
+
[](https://youtu.be/0lkY7YQCyCo)
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
@@ -48,68 +48,65 @@ A lightweight coding agent built on Apple's MLX framework.
|
|
|
48
48
|
## Quick Start
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
pip install mlx-code
|
|
52
|
-
|
|
51
|
+
pip install mlx-code
|
|
52
|
+
mlc
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
57
57
|
## Command Line
|
|
58
58
|
|
|
59
|
-
### `
|
|
59
|
+
### `mlc`: local server + harness
|
|
60
60
|
|
|
61
61
|
Starts the MLX inference server and launches a harness against it.
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
64
|
# Default: local MLX server + built-in REPL harness
|
|
65
|
-
|
|
65
|
+
mlc
|
|
66
66
|
|
|
67
67
|
# Use a different harness (routes traffic through the local server)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
mlc --leash claude
|
|
69
|
+
mlc --leash gemini
|
|
70
|
+
mlc --leash codex
|
|
71
71
|
|
|
72
72
|
# Server only, no harness
|
|
73
|
-
|
|
73
|
+
mlc --leash none
|
|
74
74
|
|
|
75
75
|
# Specify a model
|
|
76
|
-
|
|
76
|
+
mlc --model mlx-community/Qwen3.5-4B-OptiQ-4bit
|
|
77
77
|
|
|
78
78
|
# Restrict the tools available to the agent
|
|
79
|
-
|
|
79
|
+
mlc --tools Read Write Bash
|
|
80
80
|
|
|
81
81
|
# Custom system prompt
|
|
82
|
-
|
|
82
|
+
mlc --system "You are a helpful assistant."
|
|
83
83
|
|
|
84
84
|
# Load skills from a directory (scans recursively for SKILL.md files)
|
|
85
|
-
|
|
85
|
+
mlc --skill ./my-skills
|
|
86
86
|
|
|
87
87
|
# Resume a previous session from a git commit hash
|
|
88
|
-
|
|
88
|
+
mlc --resume <commit-hash>
|
|
89
89
|
|
|
90
|
-
# Because `
|
|
91
|
-
echo "
|
|
90
|
+
# Because `mlc` reads from stdin when it isn't a TTY, it composes naturally with shell pipes:
|
|
91
|
+
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. What are the edge cases this doesn't handle? What assumptions did you make that might not hold in a production system? What would you change if you knew this code would be read by a senior engineer in a security audit?" | mlc
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
### `
|
|
94
|
+
### `mlc-run`: harness only
|
|
95
95
|
|
|
96
96
|
Runs the agent harness against an already-running server or a remote provider.
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
# Connect to a local server at 127.0.0.1:8000 (default)
|
|
100
|
-
|
|
100
|
+
mlc-run
|
|
101
101
|
|
|
102
102
|
# Remote providers
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
mlc-run --api claude
|
|
104
|
+
mlc-run --api gemini
|
|
105
|
+
mlc-run --api deepseek --model deepseek-v4-pro
|
|
106
|
+
mlc-run --api codex
|
|
107
107
|
|
|
108
108
|
# Custom endpoint
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# With skills
|
|
112
|
-
mlxc-run --skill ./my-skills
|
|
109
|
+
echo "explain lsp.py" | mlc-run -a deepseek | cat - PLAN.md | mlc-run --url http://localhost:9000
|
|
113
110
|
```
|
|
114
111
|
|
|
115
112
|
---
|
|
@@ -2,11 +2,11 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="mlx-code",
|
|
5
|
-
url=
|
|
5
|
+
url="https://github.com/JosefAlbers/mlx-code",
|
|
6
6
|
author_email="albersj66@gmail.com",
|
|
7
7
|
author="J Joe",
|
|
8
8
|
license="Apache-2.0",
|
|
9
|
-
version="0.0.
|
|
9
|
+
version="0.0.10",
|
|
10
10
|
readme="README.md",
|
|
11
11
|
description="Coding Agent for Mac",
|
|
12
12
|
long_description=open("README.md").read(),
|
|
@@ -14,14 +14,11 @@ setup(
|
|
|
14
14
|
python_requires=">=3.12.8",
|
|
15
15
|
install_requires=[
|
|
16
16
|
"mlx-lm>=0.31.3; platform_system=='Darwin'",
|
|
17
|
-
"httpx",
|
|
17
|
+
"httpx",
|
|
18
|
+
"pydantic",
|
|
19
|
+
"GitPython",
|
|
18
20
|
],
|
|
19
|
-
extras_require={
|
|
20
|
-
"all": [
|
|
21
|
-
"python-lsp-server[all]",
|
|
22
|
-
# "tree-sitter>=0.23.0", "tree-sitter-python", # "tree-sitter-javascript", ‥
|
|
23
|
-
],
|
|
24
|
-
},
|
|
21
|
+
extras_require={"all": ["python-lsp-server[all]"]},
|
|
25
22
|
packages=find_packages(),
|
|
26
23
|
entry_points={
|
|
27
24
|
"console_scripts": [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|