mlx_commander 0.2.0__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.
@@ -0,0 +1,58 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # Virtual environments
30
+ .venv/
31
+ venv/
32
+ ENV/
33
+ env/
34
+
35
+ # macOS system files
36
+ .DS_Store
37
+ .AppleDouble
38
+ .LSOverride
39
+ ._*
40
+
41
+ # Temporary test/scratch files & local datasets
42
+ *.scpt
43
+ func-calling-singleturn.json
44
+ mlx_dataset/
45
+ mlx_out*/
46
+
47
+ # Unit test / coverage
48
+ .coverage
49
+ .coverage.*
50
+ .pytest_cache/
51
+ htmlcov/
52
+
53
+ # IDE & Editor configs
54
+ .idea/
55
+ .vscode/
56
+ *.swp
57
+ *.swo
58
+ *~
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tomkubik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,370 @@
1
+ Metadata-Version: 2.4
2
+ Name: mlx_commander
3
+ Version: 0.2.0
4
+ Summary: Convert Hugging Face datasets into Apple MLX formats, configure parameters, and run training and fine-tuning via interactive TUI and CLI
5
+ Project-URL: Homepage, https://github.com/tomkubik/mlx-commander
6
+ Project-URL: Repository, https://github.com/tomkubik/mlx-commander.git
7
+ Author: Tom Kubik
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: MacOS
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Requires-Python: >=3.9
16
+ Provides-Extra: all
17
+ Requires-Dist: datasets>=2.14.0; extra == 'all'
18
+ Requires-Dist: duckdb>=0.9.0; extra == 'all'
19
+ Requires-Dist: mcp>=1.0.0; extra == 'all'
20
+ Requires-Dist: pyarrow>=12.0.0; extra == 'all'
21
+ Requires-Dist: pylance>=0.10.0; extra == 'all'
22
+ Provides-Extra: arrow
23
+ Requires-Dist: pyarrow>=12.0.0; extra == 'arrow'
24
+ Provides-Extra: duckdb
25
+ Requires-Dist: duckdb>=0.9.0; extra == 'duckdb'
26
+ Provides-Extra: lance
27
+ Requires-Dist: pylance>=0.10.0; extra == 'lance'
28
+ Provides-Extra: mcp
29
+ Requires-Dist: mcp>=1.0.0; extra == 'mcp'
30
+ Provides-Extra: parquet
31
+ Requires-Dist: pyarrow>=12.0.0; extra == 'parquet'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # MLX Commander ๐Ÿš€
35
+
36
+ A fast, persistent dual-panel TUI (Norton Commander style) & CLI converter for preparing Hugging Face datasets into Apple Silicon MLX fine-tuning formats (`mlx-lm`).
37
+
38
+ Built entirely with Python's standard library `curses` with zero mandatory dependencies and zero pre-compiled binaries.
39
+
40
+ ![Orthodox TUI which makes MLX defaults explicit](docs/images/screenshot1.png)
41
+
42
+ *Orthodox TUI which makes MLX defaults explicit*
43
+
44
+ ---
45
+
46
+ ## ๐ŸŒŸ Key Features
47
+
48
+ - **Persistent Multi-Panel TUI (Norton Commander style)**: Full keyboard navigation (`Tab` to switch panels, `โ†‘`/`โ†“` to navigate, `Enter` to edit/open dropdowns, `F2` for Finder, `F5` to convert).
49
+ - **AI Agent Skill & TUI Pre-Population**: Coding agents (Antigravity, Claude, Cursor) can inspect dataset schemas, pre-populate format, column mappings, and splits, and launch the TUI for split-second visual confirmation.
50
+ - **macOS Terminal.app Spawner**: Seamless handoff from non-interactive agent environments to an interactive TUI window via AppleScript.
51
+ - **Model Context Protocol (MCP) Server**: Native stdio MCP server exposing dataset inspection, TUI launching, and headless conversions to Claude Desktop and Cursor.
52
+ - **Machine-Readable Manifest (`mlx_manifest.json`)**: Emits structured output with file paths, row counts, and copy-paste `mlx_lm.lora` commands for automated downstream pipelines.
53
+ - **Multi-File Selection & Dataset Merging**: Select multiple dataset files at once (e.g. combining pre-split `train.jsonl` and `test.jsonl`). Verifies that all files have identical column schemas and merges them so you can randomize fresh Train / Validation / Test sets from scratch with a custom seed.
54
+ - **Multi-Column Concatenation**: Tap `Space` to multi-select and order columns from the original dataset (e.g. `instruction + input`) to concatenate them seamlessly with `\n\n`.
55
+ - **Live Reactive Preview**: Sample records format in real time as you change target formats or adjust column mappings.
56
+ - **Instantaneous ESC Response**: Curses escape delay configured to 25ms (< 1 frame), making modal dismissal instantaneous while preserving arrow and function keys.
57
+ - **Native macOS Cocoa Finder Picker**: Seamlessly select dataset folders or files via native macOS dialogs (compiled on the fly in `/tmp` with zero checked-in binaries).
58
+ - **Supported MLX Formats**:
59
+ 1. **Text Format**: `{"text": "..."}` โ€” Causal LM / pre-training (single column, concatenated columns, or custom template).
60
+ 2. **Chat / Messages Format**: `{"messages": [{"role": "system|user|assistant", "content": "..."}]}` โ€” Supports message lists (standard role/content or ShareGPT `from`/`value`), or separate role columns.
61
+ 3. **Prompt & Completion Format**: `{"prompt": "...", "completion": "..."}` โ€” Q&A / instruction fine-tuning (`mlx_lm.lora --mask-prompt` compatible).
62
+ 4. **DPO / Preference Format**: `{"prompt": "...", "chosen": "...", "rejected": "..."}` โ€” Direct Preference Optimization.
63
+ - **Flexible Data Loader**: Parquet (`.parquet`), Arrow (`.arrow`), Hugging Face `save_to_disk` directories, JSONL (`.jsonl`), JSON arrays (`.json`), CSV (`.csv`), TSV (`.tsv`), SQLite (`.sqlite`, `.db`), and WebDataset (`.tar`).
64
+ - **Deterministic Splits & Random Seed**: Customizable Train / Validation / Test percentages with 100% reproducible shuffling via random seed.
65
+ - **Ready-to-Use `mlx_lm.lora` Command**: Generates the exact training command ready to copy-paste.
66
+ - **CLI Wizard & Headless Modes**: Run line-by-line via `--wizard` or fully automated via headless CLI flags.
67
+
68
+ ![Inspired by Norton Commander, with a classic color scheme available in TUI](docs/images/screenshot2.png)
69
+
70
+ *Inspired by Norton Commander, with a classic color scheme available in TUI*
71
+
72
+ ---
73
+
74
+ ## ๐Ÿ“ฆ Quick Start
75
+
76
+ ### 1. Launch MLX Commander (Default)
77
+
78
+ Launch the interactive dashboard using any of these equivalent commands:
79
+
80
+ ```bash
81
+ # Recommended for local repository execution (Primary):
82
+ python3 mlx_commander.py
83
+
84
+ # Or via secondary compatibility alias:
85
+ python3 run.py
86
+
87
+ # Or as a Python package module:
88
+ python3 -m mlx_commander
89
+
90
+ # Or zero-install directly via uvx from GitHub:
91
+ uvx --from git+https://github.com/tomkubik/mlx_commander.git mlx_commander
92
+
93
+ # Or via PyPI (once published):
94
+ uvx mlx_commander
95
+ ```
96
+
97
+ You can also pass arguments directly (e.g. pre-loading a dataset or multiple files):
98
+ ```bash
99
+ python3 mlx_commander.py -d /path/to/my_hf_dataset
100
+ # Or combine multiple files:
101
+ python3 mlx_commander.py -d train.jsonl test.jsonl
102
+ # (python3 run.py accepts all the same arguments)
103
+ ```
104
+
105
+ ### 2. Line-by-Line Wizard Mode
106
+
107
+ For SSH sessions or non-curses environments:
108
+
109
+ ```bash
110
+ python3 mlx_commander.py --wizard
111
+ ```
112
+
113
+ ### 3. Direct Command-Line Conversion (Automated / Headless)
114
+
115
+ You can pass all options via flags for direct scripted conversions:
116
+
117
+ ```bash
118
+ python3 mlx_commander.py \
119
+ --dataset /path/to/my_hf_dataset \
120
+ --format prompt_completion \
121
+ --prompt-col instruction \
122
+ --completion-col output \
123
+ --output ./mlx_data \
124
+ --train 80 \
125
+ --valid 10 \
126
+ --test 10 \
127
+ --seed 42
128
+ ```
129
+
130
+ ---
131
+
132
+ ## ๐Ÿ–ฅ๏ธ Command Line Reference
133
+
134
+ ```
135
+ usage: mlx_commander [-h] [-v] [-d DATASET [DATASET ...]]
136
+ [-f {text,chat,prompt_completion,dpo}]
137
+ [-o OUTPUT] [--train TRAIN] [--valid VALID] [--test TEST]
138
+ [--seed SEED] [--keep-splits] [--mapping MAPPING]
139
+ [--text-col TEXT_COL] [--text-template TEXT_TEMPLATE]
140
+ [--prompt-col PROMPT_COL] [--completion-col COMPLETION_COL]
141
+ [--messages-col MESSAGES_COL] [--user-col USER_COL]
142
+ [--assistant-col ASSISTANT_COL] [--system-col SYSTEM_COL]
143
+ [--chosen-col CHOSEN_COL] [--rejected-col REJECTED_COL]
144
+ [--commander] [--wizard]
145
+ ```
146
+
147
+ ### Key Flags:
148
+
149
+ | Flag | Description |
150
+ |---|---|
151
+ | `-d`, `--dataset` | Path to HF dataset directory or file on disk (`.arrow`, `.parquet`, `.jsonl`, `.json`, `.csv`). |
152
+ | `-f`, `--format` | Target MLX format (`text`, `chat`, `prompt_completion`, `dpo`). |
153
+ | `-o`, `--output` | Destination directory where `train.jsonl`, `valid.jsonl`, and `test.jsonl` are saved. |
154
+ | `--train` | Percentage of data for training (e.g. `80.0`). |
155
+ | `--valid` | Percentage of data for validation (e.g. `10.0`). |
156
+ | `--test` | Percentage of data for test (e.g. `10.0`, or `0` to omit). |
157
+ | `--seed` | Integer random seed for reproducible random shuffling. |
158
+ | `--keep-splits` | Preserve existing dataset splits without re-splitting. |
159
+ | `--text-col` | Column to use as `text` for `text` format. |
160
+ | `--text-template`| Template string with `{column_name}` variables for `text` format. |
161
+ | `--prompt-col` | Column to map to `prompt`. |
162
+ | `--completion-col` | Column to map to `completion`. |
163
+ | `--messages-col` | Column containing conversation turns list for `chat` format. |
164
+ | `--user-col` | Column for user turn in multi-column `chat` format. |
165
+ | `--assistant-col`| Column for assistant turn in multi-column `chat` format. |
166
+ | `--system-col` | Column for system prompt in multi-column `chat` format. |
167
+ | `--chosen-col` | Column for preferred response in `dpo` format. |
168
+ | `--rejected-col`| Column for dispreferred response in `dpo` format. |
169
+ | `--manifest-file`| Custom file path where machine-readable `mlx_manifest.json` will be saved. |
170
+ | `--prefill-state`| Pre-populate TUI state from a JSON string or path to JSON file. |
171
+ | `--spawn-terminal`| Launch interactive TUI in an external macOS Terminal window. |
172
+ | `--mcp` | Start Model Context Protocol (MCP) server over stdio. |
173
+ | `--tui` | Force launch full-screen curses TUI. |
174
+ | `--no-tui`, `--cli` | Run line-by-line CLI wizard instead of curses TUI. |
175
+
176
+ ---
177
+
178
+ ## ๐Ÿค– AI Agent Integration & MCP Support
179
+
180
+ MLX Commander is designed for the modern AI agent era (**Antigravity**, **Claude Desktop**, **Cursor**, **Zed**, **Cline**).
181
+
182
+ Instead of an agent interrogating users with 10 sequential chat prompts or guessing schemas blindly, agents can **inspect schemas, formulate recommended settings, and launch MLX Commander with pre-populated values**.
183
+
184
+ The user gets a 3-second tactile review with live JSONL preview in the Norton Commander TUI, presses **[F5 Convert]**, and hands control back to the agent with a machine-readable manifest.
185
+
186
+ ### ๐Ÿ”„ The End-to-End Workflow
187
+
188
+ ```mermaid
189
+ sequenceDiagram
190
+ autonumber
191
+ actor User as User (Human Developer)
192
+ participant Agent as AI Agent (Antigravity / Claude / Cursor)
193
+ participant TUI as MLX Commander TUI (macOS Terminal)
194
+ actor MLX as MLX Engine (mlx_lm.lora)
195
+
196
+ User->>Agent: "Convert dataset.parquet and fine-tune Llama 3 on it."
197
+ Agent->>Agent: Inspects schema, picks target format, maps columns & splits
198
+ Agent->>TUI: Launches TUI with pre-populated arguments (--tui --spawn-terminal)
199
+ Note over User,TUI: TUI pops up in macOS Terminal with fields pre-filled & live preview rendered.<br/>User reviews with arrow keys, presses [F5 Convert].
200
+ TUI->>TUI: Converts dataset, writes mlx_dataset/ & mlx_manifest.json
201
+ TUI-->>Agent: Closes window & returns exit code 0
202
+ Agent->>Agent: Reads mlx_manifest.json (split counts, paths, lora command)
203
+ Agent->>User: "Dataset converted (8,000 train / 1,000 valid / 1,000 test). Starting LoRA training..."
204
+ Agent->>MLX: Executes mlx_lm.lora training run
205
+ ```
206
+
207
+ ---
208
+
209
+ ### The Three Architectural Hand-offs
210
+
211
+ #### 1. Hand-off 1: TUI State Pre-Population
212
+ Agents can pre-populate every field of `CommanderState` via CLI flags or a JSON payload:
213
+ - **Via CLI Flags**:
214
+ ```bash
215
+ mlx_commander --tui --spawn-terminal \
216
+ --dataset "./data.parquet" \
217
+ --format chat \
218
+ --messages-col conversations \
219
+ --train 85 --valid 15 \
220
+ --output "./mlx_dataset"
221
+ ```
222
+ - **Via JSON (`--prefill-state`)**:
223
+ ```bash
224
+ mlx_commander --tui --spawn-terminal \
225
+ --prefill-state '{"dataset": "./data.parquet", "format": "prompt_completion", "prompt_col": "question", "completion_col": "answer", "train": 80, "valid": 20}'
226
+ ```
227
+ When launched with pre-fill data, the TUI opens directly with focus on the mappings panel and renders the reactive JSONL preview immediately.
228
+
229
+ #### 2. Hand-off 2: Machine-Readable Manifest Handshake (`mlx_manifest.json`)
230
+ Every conversion automatically outputs `output_dir/mlx_manifest.json` (or to a custom path specified with `--manifest-file <path>`):
231
+
232
+ ```json
233
+ {
234
+ "status": "success",
235
+ "format": "prompt_completion",
236
+ "source_path": "/path/to/source.parquet",
237
+ "output_dir": "/path/to/mlx_dataset",
238
+ "files": {
239
+ "train": {
240
+ "path": "/path/to/mlx_dataset/train.jsonl",
241
+ "filename": "train.jsonl",
242
+ "records": 8000,
243
+ "size_bytes": 1048576
244
+ },
245
+ "valid": {
246
+ "path": "/path/to/mlx_dataset/valid.jsonl",
247
+ "filename": "valid.jsonl",
248
+ "records": 1000,
249
+ "size_bytes": 131072
250
+ },
251
+ "test": {
252
+ "path": "/path/to/mlx_dataset/test.jsonl",
253
+ "filename": "test.jsonl",
254
+ "records": 1000,
255
+ "size_bytes": 131072
256
+ }
257
+ },
258
+ "splits": { "train": 8000, "valid": 1000, "test": 1000 },
259
+ "total_records": 10000,
260
+ "seed_used": 42,
261
+ "mlx_lora_command": "mlx_lm.lora --model mlx-community/Llama-3.2-3B-Instruct-4bit --train --data /path/to/mlx_dataset --mask-prompt --iters 600 --batch-size 4",
262
+ "manifest_path": "/path/to/mlx_dataset/mlx_manifest.json"
263
+ }
264
+ ```
265
+
266
+ - **Exit Code 0**: Conversion succeeded; manifest written.
267
+ - **Exit Code 130**: User cancelled/closed the TUI without converting. If `--manifest-file` was set, writes `{"status": "cancelled"}`.
268
+
269
+ #### 3. Hand-off 3: macOS Terminal.app Spawner
270
+ When invoked by background agent runners (such as IDE extensions, subshells, or MCP daemons) without an active TTY:
271
+ - Passing `--spawn-terminal` (or auto-detected on macOS in non-interactive sessions) executes the TUI in a dedicated macOS `Terminal.app` window via AppleScript.
272
+ - The calling process blocks synchronously until the user converts or exits, then unblocks and returns the exit code and manifest.
273
+
274
+ ---
275
+
276
+ ### Model Context Protocol (MCP) Server
277
+
278
+ MLX Commander includes a built-in MCP server that works over `stdio`.
279
+
280
+ #### 1. Claude Desktop Setup (`claude_desktop_config.json`):
281
+ ```json
282
+ {
283
+ "mcpServers": {
284
+ "mlx_commander": {
285
+ "command": "python3",
286
+ "args": ["-m", "mlx_commander", "--mcp"]
287
+ }
288
+ }
289
+ }
290
+ ```
291
+ *Or via zero-install `uvx`:*
292
+ ```json
293
+ {
294
+ "mcpServers": {
295
+ "mlx_commander": {
296
+ "command": "uvx",
297
+ "args": ["--from", "git+https://github.com/tomkubik/mlx_commander.git", "--with", "mcp", "mlx_commander", "--mcp"]
298
+ }
299
+ }
300
+ }
301
+ ```
302
+
303
+ #### 2. Cursor Setup (`.cursor/mcp.json`):
304
+ ```json
305
+ {
306
+ "mcpServers": {
307
+ "mlx_commander": {
308
+ "command": "python3",
309
+ "args": ["-m", "mlx_commander", "--mcp"]
310
+ }
311
+ }
312
+ }
313
+ ```
314
+
315
+ #### 3. Exposed MCP Tools:
316
+
317
+ | MCP Tool | Description | Arguments |
318
+ |---|---|---|
319
+ | `inspect_dataset` | Inspects columns, total rows, split names, sample records, and auto-detects candidate mappings. | `dataset_path: str` |
320
+ | `launch_conversion_tui` | Pre-populates and opens the TUI in macOS Terminal.app for user review. Returns conversion manifest. | `dataset_path`, `format`, `prompt_col`, `completion_col`, `messages_col`, `train_pct`, `valid_pct`, `test_pct`, `output_dir` |
321
+ | `convert_dataset_headless` | Runs direct headless conversion in background without opening TUI. Returns conversion manifest. | Same arguments as `launch_conversion_tui` |
322
+
323
+ #### 4. Exposed MCP Prompt:
324
+ - **`prepare_dataset_for_mlx`**: Instructs the model on the optimal workflow to inspect the schema, formulate column mappings, and launch the conversion TUI.
325
+
326
+ ---
327
+
328
+ ### Agent Skill (`SKILL.md`)
329
+
330
+ A standardized skill specification is included in the repository:
331
+ - Skill path: [`.agents/skills/mlx-dataset-prep/SKILL.md`](.agents/skills/mlx-dataset-prep/SKILL.md)
332
+
333
+ AI agents that support skill discovery (like **Antigravity**) automatically read this file when users ask to convert datasets or fine-tune models with Apple MLX.
334
+
335
+ ---
336
+
337
+ ## ๐Ÿ› ๏ธ Step-by-Step Wizard Walkthrough
338
+
339
+ 1. **Step 1: Dataset Source**: Select your dataset folder or file on your drive. The tool validates the file, inspects column names, row counts, and existing splits.
340
+ 2. **Step 2: MLX Format**: Choose your target format (`Text`, `Chat / Messages`, `Prompt & Completion`, `DPO / Preference`).
341
+ 3. **Step 3: Column Mapping**: Match dataset columns to MLX fields or enter a formatting template. The tool automatically detects candidate columns.
342
+ 4. **Step 4: Splitting & Seed**: Configure Train / Valid / Test percentages. A random seed is automatically generated, and you can accept it or provide your own.
343
+ 5. **Step 5: Output & Preview**: Specify the destination folder, review a live preview of the formatted JSONL lines, and confirm to write the files.
344
+ 6. **Step 6: Ready to Fine-Tune**: Review written file sizes, row counts, and copy the generated `mlx_lm.lora` fine-tuning command.
345
+
346
+ ---
347
+
348
+ ## ๐Ÿš€ Running Fine-Tuning with Apple MLX
349
+
350
+ Once your dataset is converted, fine-tune an LLM on Apple Silicon with `mlx-lm`:
351
+
352
+ ```bash
353
+ mlx_lm.lora \
354
+ --model mlx-community/Llama-3.2-3B-Instruct-4bit \
355
+ --train \
356
+ --data ./mlx_dataset \
357
+ --mask-prompt \
358
+ --iters 600 \
359
+ --batch-size 4
360
+ ```
361
+
362
+ ---
363
+
364
+ ## ๐Ÿงช Running Unit Tests
365
+
366
+ Run the test suite with Python's built-in `unittest`:
367
+
368
+ ```bash
369
+ .venv/bin/python -m unittest discover -s tests -p "test_*.py" -v
370
+ ```