locals 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.
- locals-0.2.0/LICENSE +21 -0
- locals-0.2.0/PKG-INFO +534 -0
- locals-0.2.0/README.md +496 -0
- locals-0.2.0/THIRD_PARTY_NOTICES.md +76 -0
- locals-0.2.0/locals/__init__.py +69 -0
- locals-0.2.0/locals/agents.py +485 -0
- locals-0.2.0/locals/api.py +333 -0
- locals-0.2.0/locals/apis.py +483 -0
- locals-0.2.0/locals/app.py +2505 -0
- locals-0.2.0/locals/attention.py +224 -0
- locals-0.2.0/locals/bench.py +112 -0
- locals-0.2.0/locals/blocks.py +485 -0
- locals-0.2.0/locals/budget.py +111 -0
- locals-0.2.0/locals/chat.py +227 -0
- locals-0.2.0/locals/cli.py +84 -0
- locals-0.2.0/locals/client.py +297 -0
- locals-0.2.0/locals/constraint.py +165 -0
- locals-0.2.0/locals/core.py +430 -0
- locals-0.2.0/locals/defaults.py +274 -0
- locals-0.2.0/locals/engine.py +1300 -0
- locals-0.2.0/locals/fields.py +48 -0
- locals-0.2.0/locals/forced.py +249 -0
- locals-0.2.0/locals/formats.py +969 -0
- locals-0.2.0/locals/fuse.py +339 -0
- locals-0.2.0/locals/gdn_kernel.py +205 -0
- locals-0.2.0/locals/grammar.py +594 -0
- locals-0.2.0/locals/harness.py +1239 -0
- locals-0.2.0/locals/hybrid_batch.py +1879 -0
- locals-0.2.0/locals/kernels.py +1441 -0
- locals-0.2.0/locals/lazy.py +224 -0
- locals-0.2.0/locals/llg.py +24 -0
- locals-0.2.0/locals/lm.py +75 -0
- locals-0.2.0/locals/lookup.py +167 -0
- locals-0.2.0/locals/menubar.py +100 -0
- locals-0.2.0/locals/mixed.py +69 -0
- locals-0.2.0/locals/mma_kernel.py +171 -0
- locals-0.2.0/locals/nax_kernel.py +471 -0
- locals-0.2.0/locals/norm_kernel.py +82 -0
- locals-0.2.0/locals/oai.py +811 -0
- locals-0.2.0/locals/packed.py +495 -0
- locals-0.2.0/locals/pda.py +558 -0
- locals-0.2.0/locals/pdactl.py +338 -0
- locals-0.2.0/locals/plan.py +1146 -0
- locals-0.2.0/locals/presets/tune_v6_applegpu_g14s.json +1 -0
- locals-0.2.0/locals/presets/tune_v6_applegpu_g17s.json +1 -0
- locals-0.2.0/locals/qmv_frag.py +344 -0
- locals-0.2.0/locals/qmv_multi.py +248 -0
- locals-0.2.0/locals/regex.py +585 -0
- locals-0.2.0/locals/regions.py +126 -0
- locals-0.2.0/locals/runtime.py +499 -0
- locals-0.2.0/locals/server.py +2300 -0
- locals-0.2.0/locals/service.py +680 -0
- locals-0.2.0/locals/siblings.py +208 -0
- locals-0.2.0/locals/solve.py +909 -0
- locals-0.2.0/locals/tree.py +211 -0
- locals-0.2.0/locals/treedec.py +133 -0
- locals-0.2.0/locals/vocab.py +172 -0
- locals-0.2.0/locals/walk.py +219 -0
- locals-0.2.0/locals.egg-info/PKG-INFO +534 -0
- locals-0.2.0/locals.egg-info/SOURCES.txt +119 -0
- locals-0.2.0/locals.egg-info/dependency_links.txt +1 -0
- locals-0.2.0/locals.egg-info/entry_points.txt +4 -0
- locals-0.2.0/locals.egg-info/requires.txt +14 -0
- locals-0.2.0/locals.egg-info/top_level.txt +1 -0
- locals-0.2.0/pyproject.toml +67 -0
- locals-0.2.0/setup.cfg +4 -0
- locals-0.2.0/tests/test_agent_requests.py +268 -0
- locals-0.2.0/tests/test_agents.py +49 -0
- locals-0.2.0/tests/test_api.py +254 -0
- locals-0.2.0/tests/test_apis.py +53 -0
- locals-0.2.0/tests/test_app.py +626 -0
- locals-0.2.0/tests/test_background_tune.py +166 -0
- locals-0.2.0/tests/test_batch_filter.py +49 -0
- locals-0.2.0/tests/test_blocks.py +154 -0
- locals-0.2.0/tests/test_budget.py +212 -0
- locals-0.2.0/tests/test_call_stream.py +219 -0
- locals-0.2.0/tests/test_chain_cache.py +53 -0
- locals-0.2.0/tests/test_chat.py +39 -0
- locals-0.2.0/tests/test_client.py +155 -0
- locals-0.2.0/tests/test_compute_dtype.py +57 -0
- locals-0.2.0/tests/test_connections.py +553 -0
- locals-0.2.0/tests/test_core.py +241 -0
- locals-0.2.0/tests/test_engine_model.py +72 -0
- locals-0.2.0/tests/test_forced.py +180 -0
- locals-0.2.0/tests/test_formats.py +430 -0
- locals-0.2.0/tests/test_gdn_fast_model.py +47 -0
- locals-0.2.0/tests/test_hangup.py +119 -0
- locals-0.2.0/tests/test_harness.py +610 -0
- locals-0.2.0/tests/test_json_safe.py +161 -0
- locals-0.2.0/tests/test_kernel_patching.py +151 -0
- locals-0.2.0/tests/test_lm.py +67 -0
- locals-0.2.0/tests/test_lookup.py +85 -0
- locals-0.2.0/tests/test_memory_guard.py +267 -0
- locals-0.2.0/tests/test_messages_api.py +306 -0
- locals-0.2.0/tests/test_mixed_prefill.py +106 -0
- locals-0.2.0/tests/test_model_size.py +98 -0
- locals-0.2.0/tests/test_nax_kernel.py +46 -0
- locals-0.2.0/tests/test_oai.py +657 -0
- locals-0.2.0/tests/test_pda.py +265 -0
- locals-0.2.0/tests/test_persistence.py +119 -0
- locals-0.2.0/tests/test_plan.py +546 -0
- locals-0.2.0/tests/test_prefix_cache.py +64 -0
- locals-0.2.0/tests/test_q35_kernels.py +199 -0
- locals-0.2.0/tests/test_regex.py +88 -0
- locals-0.2.0/tests/test_reply_parsing.py +63 -0
- locals-0.2.0/tests/test_request_temperature.py +62 -0
- locals-0.2.0/tests/test_sampling.py +57 -0
- locals-0.2.0/tests/test_server.py +175 -0
- locals-0.2.0/tests/test_server_attention.py +49 -0
- locals-0.2.0/tests/test_server_guards.py +259 -0
- locals-0.2.0/tests/test_service_idle.py +26 -0
- locals-0.2.0/tests/test_session_checkpoint.py +173 -0
- locals-0.2.0/tests/test_sliding_window_batch.py +70 -0
- locals-0.2.0/tests/test_snapshots_bounded.py +19 -0
- locals-0.2.0/tests/test_solo.py +129 -0
- locals-0.2.0/tests/test_solve.py +357 -0
- locals-0.2.0/tests/test_stock_engine_recovers.py +41 -0
- locals-0.2.0/tests/test_table_compaction.py +81 -0
- locals-0.2.0/tests/test_think_replay.py +56 -0
- locals-0.2.0/tests/test_tune_cache.py +163 -0
- locals-0.2.0/tests/test_walk_batch.py +86 -0
locals-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arip Asadulaev
|
|
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.
|
locals-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: locals
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Run many AI agents at once on your Mac, up to 3x faster: an OpenAI- and Ollama-compatible MLX server with batched decoding, a prompt cache, and tool calls and JSON that always parse
|
|
5
|
+
Author: Arip Asadulaev
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Generated-Computers/Locals
|
|
8
|
+
Project-URL: Documentation, https://github.com/Generated-Computers/Locals#readme
|
|
9
|
+
Project-URL: Issues, https://github.com/Generated-Computers/Locals/issues
|
|
10
|
+
Keywords: mlx,apple-silicon,llm,structured-output,constrained-decoding,json-schema,grammar,tool-calling,agents,inference
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
25
|
+
Requires-Dist: mlx<0.34,>=0.32
|
|
26
|
+
Requires-Dist: mlx-lm<0.33,>=0.32
|
|
27
|
+
Requires-Dist: numpy>=1.26
|
|
28
|
+
Requires-Dist: huggingface_hub>=0.30
|
|
29
|
+
Requires-Dist: llguidance>=1.8
|
|
30
|
+
Requires-Dist: outlines-core<0.3,>=0.2
|
|
31
|
+
Requires-Dist: rich>=13
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
34
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
35
|
+
Provides-Extra: menubar
|
|
36
|
+
Requires-Dist: rumps>=0.4; extra == "menubar"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
<p align="center">
|
|
40
|
+
<img src="https://raw.githubusercontent.com/Generated-Computers/Locals/8404f6b4b32b8070facd0290d157e3ed97777623/docs/assets/logo.png#gh-light-mode-only" alt="Generated Computers" width="80%">
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<h1 align="center">Locals</h1>
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<b>Run many AI agents at once on your Mac, up to 3x faster.</b><br>
|
|
47
|
+
A local server made for agents rather than plain chat: tool calls, long
|
|
48
|
+
conversations and many agents working at the same time. For OpenCode,
|
|
49
|
+
OpenHands, Cline, Aider, Claude Code and any OpenAI, Anthropic or Ollama app.
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
<p align="center">
|
|
53
|
+
<a href="https://github.com/Generated-Computers/Locals/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
|
|
54
|
+
<a href="#getting-started"><img src="https://img.shields.io/badge/macOS-Apple%20silicon-lightgrey.svg" alt="macOS on Apple silicon"></a>
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
<p align="center">
|
|
58
|
+
<a href="#getting-started"><b>Getting started</b></a> ·
|
|
59
|
+
<a href="#works-with-your-agents"><b>Agents</b></a> ·
|
|
60
|
+
<a href="https://github.com/Generated-Computers/Locals/blob/main/docs/benchmarks/README.md"><b>Benchmarks</b></a> ·
|
|
61
|
+
<a href="#documentation"><b>Documentation</b></a> ·
|
|
62
|
+
<a href="https://arxiv.org/abs/2610.09139"><b>Paper</b></a>
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
curl -LsSf https://raw.githubusercontent.com/Generated-Computers/Locals/main/install.sh | sh
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Then, in a new Terminal window:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
locals code ~/my-project
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
That is all. The first time, Locals downloads a model that suits your Mac
|
|
76
|
+
(about 3 GB), starts it in the background and opens the OpenCode assistant in
|
|
77
|
+
your project. Nothing leaves your computer.
|
|
78
|
+
|
|
79
|
+
## What it is
|
|
80
|
+
|
|
81
|
+
<img src="https://raw.githubusercontent.com/Generated-Computers/Locals/8404f6b4b32b8070facd0290d157e3ed97777623/docs/assets/emblem.png" alt="Generated Computers Co." width="35%" align="right">
|
|
82
|
+
|
|
83
|
+
Locals runs AI models on your own Mac for agents, not for chatting with a raw
|
|
84
|
+
model. An agent works differently from a person in a chat. It calls tools, and
|
|
85
|
+
every call has to be right. It sends a long prompt that grows a little every
|
|
86
|
+
turn. And it rarely works alone: coding assistants run helpers in parallel, and
|
|
87
|
+
teams of agents split one task between them. Locals is built for this work, from
|
|
88
|
+
the way it computes a batch of requests on your Mac's graphics chip to the way
|
|
89
|
+
it writes a tool call, so a team of agents gets its answers up to three times
|
|
90
|
+
faster than with the standard way of running models on a Mac.
|
|
91
|
+
|
|
92
|
+
It works with the coding agents you may already use, such as OpenCode, Cline,
|
|
93
|
+
Aider, OpenHands and Claude Code, and with any app or program that talks to
|
|
94
|
+
OpenAI, Anthropic or Ollama. Everything stays on your computer.
|
|
95
|
+
|
|
96
|
+
Locals is built on the paper
|
|
97
|
+
[Breaking the Space Barrier and its Application to Language Model Inference](https://arxiv.org/abs/2610.09139)
|
|
98
|
+
(Arip Asadulaev, 2026). A JSON format or a tool call can be described as a
|
|
99
|
+
graph, and checking a reply against it as finding a path in that graph. The
|
|
100
|
+
paper does this in less memory than Savitch's classical bound and turns it into
|
|
101
|
+
an inference engine: text the format already decides is written without running
|
|
102
|
+
the model, the checks run on the graphics chip, and a format needs about 3 MB of
|
|
103
|
+
memory instead of up to 1.5 GB. With it, sixteen tool-calling agents finish 2.5
|
|
104
|
+
times sooner than with mlx-lm and llguidance.
|
|
105
|
+
|
|
106
|
+
## Made for agents
|
|
107
|
+
|
|
108
|
+
- **Many agents at once.** Requests from every agent are computed together, with
|
|
109
|
+
GPU kernels written for a few requests at a time, so eight agents working at
|
|
110
|
+
once finish in about the time two would need one after the other.
|
|
111
|
+
- **Tool calls that always parse.** Replies are written in each model's own
|
|
112
|
+
tool-call format under a grammar applied on the GPU, so an agent can call only
|
|
113
|
+
the tools it offered, every argument arrives in the type its schema asks for,
|
|
114
|
+
and a reply cut off by its length limit still closes its call. Requests for
|
|
115
|
+
JSON follow their schema the same way.
|
|
116
|
+
- **Each turn picks up where the last one ended.** Locals keeps every
|
|
117
|
+
conversation between turns, and the long system prompt an agent tool starts
|
|
118
|
+
with (3,000 to 16,000 tokens) on disk across restarts, so an agent's next turn
|
|
119
|
+
reads only what it added: the next turn of a 138,000-token conversation starts
|
|
120
|
+
after 2.4 seconds.
|
|
121
|
+
- **Guards made for agents.** A small model can repeat itself or call the same
|
|
122
|
+
tool forever; Locals notices and stops both. A memory guard keeps many agents
|
|
123
|
+
with long prompts from ending in an out-of-memory error, and an agent that
|
|
124
|
+
hangs up frees the server at once.
|
|
125
|
+
- **One command per agent tool.** `locals code` opens OpenCode in your project,
|
|
126
|
+
and `locals launch` connects Hermes Agent, OpenClaw, Claude Code, Kilo Code,
|
|
127
|
+
Cline, OpenHands and Aider.
|
|
128
|
+
- **A team of agents for bigger tasks.** `locals run` splits a task into parts,
|
|
129
|
+
gives each part to several agents at once, each in its own copy of your
|
|
130
|
+
project, and lets your tests decide.
|
|
131
|
+
|
|
132
|
+
## Results at a glance
|
|
133
|
+
|
|
134
|
+
<picture>
|
|
135
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/requests-narrow-dark.svg">
|
|
136
|
+
<img width="70%" alt="Qwen3.5-4B on an M2 Pro with 16 GB. mlx-lm: 61, 82, 87, 87, 157 tokens per second with 1, 2, 4, 8 and 16 requests at once; Locals: 64, 116, 160, 271, 341 (1.0x, 1.4x, 1.8x, 3.1x, 2.2x)." src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/requests-narrow.svg">
|
|
137
|
+
</picture>
|
|
138
|
+
|
|
139
|
+
mlx-lm, the standard way of running models on a Mac, answers several requests
|
|
140
|
+
together, but it gets no faster from four of them to eight: it writes 87 tokens
|
|
141
|
+
per second for four requests and the same 87 for eight. Locals keeps getting
|
|
142
|
+
faster as requests are added, up to three times mlx-lm's speed with eight at
|
|
143
|
+
once.
|
|
144
|
+
|
|
145
|
+
It is faster for a single agent too: when the reply repeats a file it is
|
|
146
|
+
rewriting, after a restart, and in long conversations. The table has these
|
|
147
|
+
cases, on a MacBook Pro with an M2 Pro and 16 GB and Qwen3.5-4B, the default
|
|
148
|
+
model.
|
|
149
|
+
|
|
150
|
+
<br clear="right">
|
|
151
|
+
|
|
152
|
+
| On a MacBook Pro with an M2 Pro and 16 GB, Qwen3.5-4B | Without Locals | With Locals | |
|
|
153
|
+
|---|---|---|---|
|
|
154
|
+
| 8 requests at once | 87 tokens/s (mlx-lm) | 271 tokens/s | 3.1x |
|
|
155
|
+
| 8 agents asking at once: time to the first word | 42 s (Ollama) | 1.6 s | 26x sooner |
|
|
156
|
+
| One agent rewriting a 100-line file | 43 tokens/s (mlx-lm) | 128 tokens/s | 3.0x |
|
|
157
|
+
| An agent's first request after a restart | 16 s (mlx-lm) | 1.7 s | 9.6x sooner |
|
|
158
|
+
| A follow-up question about a 48,000-token document | out of memory (mlx-lm) | 0.6 s | |
|
|
159
|
+
| 16 coding agents calling tools (Qwen3.5-2B, from the paper) | 75 s (mlx-lm) | 29 s | 2.5x |
|
|
160
|
+
| 40 programming problems from LiveCodeBench, 8 at a time (from the paper) | 20 min (mlx-lm) | 8 min | 2.5x |
|
|
161
|
+
|
|
162
|
+
<picture>
|
|
163
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/macs-dark.svg">
|
|
164
|
+
<img alt="Qwen3.5-4B through the server, 1 to 16 requests at once. M2 Pro · 16 GB: mlx-lm [51, 79, 88, 75, 124], Locals [65, 116, 150, 244, 310]. M2 Max · 96 GB: mlx-lm [91, 121, 142, 152, 267], Locals [104, 177, 244, 403, 530]. M5 Pro · 24 GB: mlx-lm [86, 151, 232, 258, 333], Locals [90, 161, 253, 382, 508]." src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/macs.svg" width="100%">
|
|
165
|
+
</picture>
|
|
166
|
+
|
|
167
|
+
Bigger models gain more on the M2 Max: 3.0x for Qwen3.5-9B and 3.1x for a 27B
|
|
168
|
+
model with eight requests at once. On the M5 Pro the gain is smaller, because
|
|
169
|
+
mlx-lm is much faster there: MLX has its own kernels for the M5's neural
|
|
170
|
+
accelerators, and these numbers were measured before Locals had its own. M1, M3
|
|
171
|
+
and M4 chips have not been measured yet: results from them are welcome as
|
|
172
|
+
[issues](https://github.com/Generated-Computers/Locals/issues), with the output
|
|
173
|
+
of `locals bench` and `locals tune --report`.
|
|
174
|
+
|
|
175
|
+
## Benchmarks
|
|
176
|
+
|
|
177
|
+
Every table, and how each was measured, is in
|
|
178
|
+
[Benchmarks](https://github.com/Generated-Computers/Locals/blob/main/docs/benchmarks/README.md). Unless a chart says otherwise, it was
|
|
179
|
+
measured on a MacBook Pro with an M2 Pro (19-core GPU) and 16 GB, with
|
|
180
|
+
Qwen3.5-4B (`mlx-community/Qwen3.5-4B-MLX-4bit`), MLX 0.32 and mlx-lm 0.32.
|
|
181
|
+
|
|
182
|
+
<picture>
|
|
183
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/models-dark.svg">
|
|
184
|
+
<img alt="M2 Pro · 16 GB: Qwen3.5-2B 3.1x (188 to 576 tokens/s), MiniCPM5-2B 3.0x (160 to 478 tokens/s), LFM2.5-2.6B 2.8x (144 to 404 tokens/s), Qwen3.5-4B 3.1x (87 to 271 tokens/s), Gemma 4 E4B 2.8x (80 to 224 tokens/s). M2 Max · 96 GB: Qwen3.5-4B 2.66x (152 to 403 tokens/s), Qwen3.5-9B 3.03x (72 to 220 tokens/s), Qwen3.8-27B 3.13x (25 to 78 tokens/s). M5 Pro · 24 GB: Qwen3.5-4B 1.48x (258 to 382 tokens/s), Qwen3.5-9B 1.58x (145 to 229 tokens/s)." src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/models.svg" width="100%">
|
|
185
|
+
</picture>
|
|
186
|
+
|
|
187
|
+
Models quantized to 4 bits in the usual way (in groups of 64) gain 2.3x to 3.3x
|
|
188
|
+
with 8 requests at once; other formats run at mlx-lm's speed
|
|
189
|
+
([below](#where-locals-is-not-faster)).
|
|
190
|
+
|
|
191
|
+
### Against other servers
|
|
192
|
+
|
|
193
|
+
<picture>
|
|
194
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/servers-dark.svg">
|
|
195
|
+
<img alt="Qwen3.5-4B, 1,000-token prompts, 8 requests at once on an M2 Pro. Time to the first token: Locals 1.6 s, llama.cpp 2.1 s, Magnitude 16.1 s, Ollama 41.8 s. Tokens per second: Locals 110, llama.cpp 71, Magnitude 42, Ollama 34." src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/charts/servers.svg" width="100%">
|
|
196
|
+
</picture>
|
|
197
|
+
|
|
198
|
+
Ollama 0.40.5, Magnitude 0.2.9 and llama.cpp `b11724`, one at a time on the GPU,
|
|
199
|
+
each with its own 4-bit build of the model, measured with SemiAnalysis's
|
|
200
|
+
InferenceX client (temperature 0, replies of natural length). The tables for
|
|
201
|
+
1,000- and 8,000-token prompts and for Gemma 4 are in
|
|
202
|
+
[Benchmarks](https://github.com/Generated-Computers/Locals/blob/main/docs/benchmarks/README.md#3-against-other-servers).
|
|
203
|
+
|
|
204
|
+
### Long prompts
|
|
205
|
+
|
|
206
|
+
**No pause while a long prompt is read.** When an agent sends an 8,000-token
|
|
207
|
+
prompt while others are getting answers, Locals reads it in the same passes as
|
|
208
|
+
their next tokens, so their replies keep streaming: the longest gap in them went
|
|
209
|
+
from 12 s to 3 s, with the same throughput, against reading the prompt on its
|
|
210
|
+
own. A 3,000-token request that arrives during a 30,000-token one gets its first
|
|
211
|
+
token after 7 s instead of 41.
|
|
212
|
+
|
|
213
|
+
### Where Locals is not faster
|
|
214
|
+
|
|
215
|
+
- **One request alone, with nothing to reuse**: about the same as mlx-lm (64
|
|
216
|
+
against 61 tokens per second on the M2 Pro). It is faster alone when the reply
|
|
217
|
+
repeats the prompt (file rewrites) or the prompt is cached.
|
|
218
|
+
- **Prompt-bound work**: reading a prompt is limited by the GPU's arithmetic.
|
|
219
|
+
With 8,000-token prompts and 8 requests at once the server writes 57 tokens
|
|
220
|
+
per second; most of the time goes into reading.
|
|
221
|
+
- **Formats outside the tuned kernels**: 4-bit affine quantization in groups of
|
|
222
|
+
64 is covered; mxfp4 (a mixture-of-experts model, Mellum) ran at mlx-lm's
|
|
223
|
+
speed.
|
|
224
|
+
- **The M5's neural accelerators**: MLX's own kernels already use them, so the
|
|
225
|
+
gain there is 1.5x, not 3x (before Locals' own `nax` kernel, which is
|
|
226
|
+
experimental).
|
|
227
|
+
|
|
228
|
+
## Works with your agents
|
|
229
|
+
|
|
230
|
+
<p align="center">
|
|
231
|
+
<img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/hermes.png" width="12.4%" alt="Hermes Agent" title="Hermes Agent"><img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/kilo.png" width="12.4%" alt="Kilo Code" title="Kilo Code"><img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/opencode.png" width="12.4%" alt="OpenCode" title="OpenCode"><img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/openhands.png" width="12.4%" alt="OpenHands" title="OpenHands"><img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/cline.png" width="12.4%" alt="Cline" title="Cline"><img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/aider.png" width="12.4%" alt="Aider" title="Aider"><img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/roo.png" width="12.4%" alt="Roo Code" title="Roo Code"><img src="https://raw.githubusercontent.com/Generated-Computers/Locals/main/docs/assets/agents/openclaw.png" width="12.4%" alt="OpenClaw" title="OpenClaw">
|
|
232
|
+
</p>
|
|
233
|
+
|
|
234
|
+
Locals works with the coding agents and assistants people already use, on a
|
|
235
|
+
model running on your Mac. All of these but Roo Code were tested end to end with
|
|
236
|
+
Qwen3.5-4B on a 16 GB Mac (Cline and Kilo Code through their command-line
|
|
237
|
+
versions), on real tasks such as writing a program, running it and reporting
|
|
238
|
+
what it printed. One command starts Locals and connects the tool to it:
|
|
239
|
+
|
|
240
|
+
| Tool | Run |
|
|
241
|
+
|---|---|
|
|
242
|
+
| [Hermes Agent](https://github.com/NousResearch/hermes-agent) | `locals launch hermes` |
|
|
243
|
+
| [Kilo Code](https://github.com/Kilo-Org/kilocode) | `locals launch kilo` |
|
|
244
|
+
| [OpenCode](https://github.com/anomalyco/opencode) | `locals code ~/my-project` |
|
|
245
|
+
| [OpenHands](https://github.com/OpenHands/OpenHands) | `locals launch openhands` |
|
|
246
|
+
| [Cline](https://github.com/cline/cline) | `locals launch cline` |
|
|
247
|
+
| [Aider](https://github.com/Aider-AI/aider) | `locals launch aider` |
|
|
248
|
+
| [Roo Code](https://github.com/RooCodeInc/Roo-Code) | in VS Code, the settings from `locals launch editor` ([how](#use-it-in-apps-and-editors)) |
|
|
249
|
+
| [OpenClaw](https://github.com/openclaw/openclaw) | `locals launch openclaw` |
|
|
250
|
+
| [Claude Code](https://github.com/anthropics/claude-code) | `locals launch claude` (through Anthropic's Messages API, which Locals also answers) |
|
|
251
|
+
|
|
252
|
+
`locals launch list` shows every tool it can open. Locals keeps running in the
|
|
253
|
+
background after you close a tool: `locals status` shows what it is doing and
|
|
254
|
+
`locals stop` stops it.
|
|
255
|
+
|
|
256
|
+
<sub>The logos belong to their projects and are shown only to say that Locals
|
|
257
|
+
works with these tools.</sub>
|
|
258
|
+
|
|
259
|
+
## Getting started
|
|
260
|
+
|
|
261
|
+
You need a Mac with Apple silicon (M1 or newer) and macOS 14 or newer. A Mac
|
|
262
|
+
with 16 GB of memory gives the best results; with 8 GB, use one of the smaller
|
|
263
|
+
models.
|
|
264
|
+
|
|
265
|
+
Open the Terminal app and run:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
curl -LsSf https://raw.githubusercontent.com/Generated-Computers/Locals/main/install.sh | sh
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Then open a new Terminal window (the installer adds Locals to your shell's
|
|
272
|
+
PATH, which only new windows read) and start a coding assistant on one of your
|
|
273
|
+
projects:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
locals code ~/my-project
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
After the first start, which downloads the model, Locals starts in seconds.
|
|
280
|
+
|
|
281
|
+
- **OpenCode** uses Locals as its default model from then on, so plain
|
|
282
|
+
`opencode` uses it too; `locals disconnect opencode` gives OpenCode its own
|
|
283
|
+
settings back.
|
|
284
|
+
- **To update** Locals, run the install command again.
|
|
285
|
+
- **To remove** it, run `locals stop`, `locals disconnect opencode` and
|
|
286
|
+
`uv tool uninstall locals`.
|
|
287
|
+
- **With the uv package manager**, you can install with
|
|
288
|
+
`uv tool install --python 3.12 git+https://github.com/Generated-Computers/Locals`
|
|
289
|
+
instead.
|
|
290
|
+
|
|
291
|
+
### Coming from Ollama, LM Studio, mlx-lm or llama.cpp
|
|
292
|
+
|
|
293
|
+
Locals installs next to them and changes nothing of theirs: it has its own port
|
|
294
|
+
(8321) and its own folders. Only the memory is shared, so quit the other one
|
|
295
|
+
while Locals runs; two models at once rarely fit. Locals remembers the model and
|
|
296
|
+
port you start it with for later commands.
|
|
297
|
+
|
|
298
|
+
**Ollama.** Quit Ollama, then let Locals answer on Ollama's port. Apps set up
|
|
299
|
+
for Ollama (Open WebUI, Raycast, Continue) and the `ollama` command itself keep
|
|
300
|
+
working unchanged, whatever model name they ask for:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
osascript -e 'quit app "Ollama"' # or: brew services stop ollama
|
|
304
|
+
locals launch --model qwen3.5:4b ollama
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Ollama's model names work in Locals, and for a model Locals does not know it
|
|
308
|
+
names the MLX version on Hugging Face to use instead. Ollama's own downloads
|
|
309
|
+
are in its own format (GGUF for most models), so a model is downloaded once
|
|
310
|
+
more, in MLX's. To
|
|
311
|
+
go back, run `locals stop` and start Ollama.
|
|
312
|
+
|
|
313
|
+
**LM Studio.** LM Studio's MLX models run in Locals where they are, with no
|
|
314
|
+
second download. Stop LM Studio's server and start Locals on its port, so apps
|
|
315
|
+
that use it keep working:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
locals start --model ~/.lmstudio/models/mlx-community/Qwen3.5-4B-MLX-4bit --port 1234
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**mlx-lm.** The same models and the same download folder, so nothing downloads
|
|
322
|
+
again. `locals serve` takes the place of `mlx_lm.server`, with the same API:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
locals serve --model mlx-community/Qwen3.5-4B-MLX-4bit --port 8080
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**llama.cpp.** Locals runs MLX models, not GGUF files; give it one and it names
|
|
329
|
+
the MLX version of the same model. Start it on `llama-server`'s port to keep
|
|
330
|
+
your clients:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
locals start --model qwen --port 8080
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Any other server with the OpenAI API** (vLLM, LocalAI): point your client at
|
|
337
|
+
`http://127.0.0.1:8321/v1`, or start Locals on the port the client already uses
|
|
338
|
+
with `--port`.
|
|
339
|
+
|
|
340
|
+
## Examples
|
|
341
|
+
|
|
342
|
+
**Work on a project with an assistant.** This opens OpenCode in your project, where
|
|
343
|
+
you can ask for changes in plain words and watch it read, edit and test your code:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
locals code ~/my-project
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Give it one task and get the result.** The assistant does the task from start
|
|
350
|
+
to finish without opening a window, and prints what it did:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
locals code ~/my-project --run "add a --verbose flag to cli.py and run the tests"
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Let a team of agents do a bigger task.** Several agents work on the parts of
|
|
357
|
+
the task at the same time, each in its own copy of your project, and your tests
|
|
358
|
+
decide when it is done. Your project is changed only when the tests pass:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
locals run "write wordcount.py with a function count_words(text) and tests in test_wordcount.py" \
|
|
362
|
+
--dir ~/my-project --check "python3 -m pytest -q"
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Ask a question about your code.** An agent reads the project and prints the
|
|
366
|
+
answer:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
locals run "Which function parses dates, and which format does it expect?" --dir ~/my-project
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**Chat with the model** in the Terminal, like a private chatbot:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
locals chat
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Turn text into structured data.** Describe the fields you want in a JSON schema,
|
|
379
|
+
for example in a file called `person.json`:
|
|
380
|
+
|
|
381
|
+
```json
|
|
382
|
+
{"type": "object",
|
|
383
|
+
"properties": {"name": {"type": "string"}, "age": {"type": "integer"}, "email": {"type": "string"},
|
|
384
|
+
"status": {"enum": ["pending", "approved", "rejected"]}, "tags": {"type": "array", "items": {"type": "string"}}},
|
|
385
|
+
"required": ["name", "age", "email", "status", "tags"]}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Then the answer always follows it, field by field:
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
locals generate --prompt "Ana Silva, 29, ana@example.com, application approved, tags: vip, early" \
|
|
392
|
+
--schema person.json
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
{"name":"Ana Silva","age":29,"email":"ana@example.com","status":"approved","tags":["vip","early"]}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## Use it in apps and editors
|
|
400
|
+
|
|
401
|
+
Start Locals once with the model you want; it keeps running in the background:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
locals start --model qwen
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**The OpenCode app.** Run `locals setup --model qwen` once, then choose Locals in
|
|
408
|
+
OpenCode's model list. This works in the desktop app, the editor extension and
|
|
409
|
+
the Terminal version alike.
|
|
410
|
+
|
|
411
|
+
**Kilo Code, Cline and Roo Code in VS Code**, and **Continue, Zed and JetBrains.**
|
|
412
|
+
Choose the provider called "OpenAI Compatible" and enter these values. Run
|
|
413
|
+
`locals launch editor` to print them for the model that is running.
|
|
414
|
+
|
|
415
|
+
| Setting | What to enter |
|
|
416
|
+
|---|---|
|
|
417
|
+
| Base URL | `http://127.0.0.1:8321/v1` |
|
|
418
|
+
| API key | any text, for example `local` |
|
|
419
|
+
| Model | the model's name from the table below, for example `locals/qwen3.5-4b` |
|
|
420
|
+
| Context window | the number `locals launch editor` prints, if the extension asks for it |
|
|
421
|
+
|
|
422
|
+
**Apps that work with Ollama**, such as Open WebUI or Raycast, need no settings:
|
|
423
|
+
run `locals launch ollama`.
|
|
424
|
+
|
|
425
|
+
## Models
|
|
426
|
+
|
|
427
|
+
Locals picks a model that fits your Mac's memory, so most people never need to
|
|
428
|
+
change it. To use another one, start Locals with its name, for example
|
|
429
|
+
`locals start --model lfm`. Locals runs one model at a time. The last two
|
|
430
|
+
columns are speeds in tokens per second (tps) with 8 requests at once, on the
|
|
431
|
+
M2 Pro with 16 GB above.
|
|
432
|
+
|
|
433
|
+
| Model | Start it with | Name in your editor | Size | mlx-lm | Locals |
|
|
434
|
+
|---|---|---|---|---|---|
|
|
435
|
+
| Qwen3.5-4B (the default) | `--model qwen` | `locals/qwen3.5-4b` | 2.8 GB | 87 tps | 271 tps |
|
|
436
|
+
| LFM2.5-2.6B | `--model lfm` | `locals/lfm2.5-2.6b` | 1.5 GB | 144 tps | 404 tps |
|
|
437
|
+
| MiniCPM5-2B | `--model minicpm` | `locals/minicpm5-2b` | 1.3 GB | 160 tps | 478 tps |
|
|
438
|
+
| Gemma 4 E4B | `--model gemma` | `locals/gemma-4-e4b-it` | 4.8 GB | 80 tps | 224 tps |
|
|
439
|
+
|
|
440
|
+
On a Mac with less than 12 GB of memory, the default is Qwen3.5-2B instead
|
|
441
|
+
(`--model qwen3.5-2b`; `locals/qwen3.5-2b` in your editor).
|
|
442
|
+
|
|
443
|
+
Each model also has a thinking mode, in which it reasons before it answers: add
|
|
444
|
+
`-thinking` to the name, for example `locals/lfm2.5-2.6b-thinking`. The smaller
|
|
445
|
+
models are good choices for a Mac with 8 GB of memory, and other models made for
|
|
446
|
+
Apple silicon on [Hugging Face](https://huggingface.co/mlx-community) work too.
|
|
447
|
+
|
|
448
|
+
Conversations can be long: up to about 178,000 tokens with the default model
|
|
449
|
+
on a 16 GB Mac, a few hundred pages of text. On the M2 Pro, reading a
|
|
450
|
+
170,000-token document takes about 12 minutes the first time, and follow-up
|
|
451
|
+
questions about it start in 2 seconds. OpenCode is set up for 32,000 tokens,
|
|
452
|
+
and OpenClaw, Hermes Agent and Kilo Code for 64,000, which keeps each of their
|
|
453
|
+
steps quick.
|
|
454
|
+
|
|
455
|
+
## Using it from your own code
|
|
456
|
+
|
|
457
|
+
Locals understands the same requests as the OpenAI and Ollama services, so
|
|
458
|
+
programs written for them work with it unchanged. Start Locals with
|
|
459
|
+
`locals start`, then point your program at `http://127.0.0.1:8321/v1`:
|
|
460
|
+
|
|
461
|
+
```python
|
|
462
|
+
from openai import OpenAI
|
|
463
|
+
|
|
464
|
+
client = OpenAI(base_url="http://127.0.0.1:8321/v1", api_key="local")
|
|
465
|
+
reply = client.chat.completions.create(
|
|
466
|
+
model="locals", # the model the server runs
|
|
467
|
+
messages=[{"role": "user", "content": "Write a haiku about the sea."}],
|
|
468
|
+
)
|
|
469
|
+
print(reply.choices[0].message.content)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Send many requests at once, from threads or with an async client, and Locals
|
|
473
|
+
answers them together; that is where it is fastest. Streaming, answers in a
|
|
474
|
+
fixed JSON format, function calls, the Ollama library and plain `curl` all work
|
|
475
|
+
as well; the [examples](https://github.com/Generated-Computers/Locals/blob/main/examples/README.md) show each of them.
|
|
476
|
+
|
|
477
|
+
## Privacy and safety
|
|
478
|
+
|
|
479
|
+
Everything runs on your Mac. Locals only accepts requests from apps on your own
|
|
480
|
+
computer, so a website you visit cannot use it. When a team of agents works on a
|
|
481
|
+
task (`locals run`, `locals solve`), the commands they run can change files only
|
|
482
|
+
in their own copy of your project, and in the temporary and cache folders that
|
|
483
|
+
tools write to. `locals code` runs OpenCode in your project itself, as OpenCode
|
|
484
|
+
always runs.
|
|
485
|
+
|
|
486
|
+
## If something does not work
|
|
487
|
+
|
|
488
|
+
Run `locals status`, or open http://127.0.0.1:8321 in your browser, to see whether
|
|
489
|
+
Locals is running and what it is doing. On a chip other than the M2 Pro and
|
|
490
|
+
M2 Max, whose tuning ships with Locals, it tunes itself to your chip the first
|
|
491
|
+
time, in the background while it is idle: 10 to 20 minutes of idle time in all.
|
|
492
|
+
You can use it during that time, and it gets faster once it finishes.
|
|
493
|
+
|
|
494
|
+
Questions and problems are welcome as
|
|
495
|
+
[issues on GitHub](https://github.com/Generated-Computers/Locals/issues).
|
|
496
|
+
|
|
497
|
+
## Documentation
|
|
498
|
+
|
|
499
|
+
| Topic | Page |
|
|
500
|
+
|---|---|
|
|
501
|
+
| How Locals works: the server, the batch engine, the prompt cache, the team of agents behind `locals run`, and every setting | [How Locals works](https://github.com/Generated-Computers/Locals/blob/main/docs/README.md) |
|
|
502
|
+
| Every benchmark, and how it was measured | [Benchmarks](https://github.com/Generated-Computers/Locals/blob/main/docs/benchmarks/README.md) |
|
|
503
|
+
| Every table with its date, commit and command; the M2 Max | [Measurements](https://github.com/Generated-Computers/Locals/blob/main/docs/measurements/README.md), [M2 Max](https://github.com/Generated-Computers/Locals/blob/main/docs/measurements/m2-max.md) |
|
|
504
|
+
| Why Locals is faster than mlx-lm, part by part | [Why Locals is faster](https://github.com/Generated-Computers/Locals/blob/main/docs/why-faster/README.md) |
|
|
505
|
+
| Streaming, JSON, function calls, the Ollama library and `curl` | [Examples](https://github.com/Generated-Computers/Locals/blob/main/examples/README.md) |
|
|
506
|
+
| The tests, and the end-to-end suite with real agent tools | [Tests](https://github.com/Generated-Computers/Locals/blob/main/tests/README.md), [End to end](https://github.com/Generated-Computers/Locals/blob/main/tests/e2e/README.md) |
|
|
507
|
+
| Working on Locals itself | [CONTRIBUTING.md](https://github.com/Generated-Computers/Locals/blob/main/CONTRIBUTING.md) |
|
|
508
|
+
|
|
509
|
+
To work on Locals:
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
git clone https://github.com/Generated-Computers/Locals
|
|
513
|
+
cd Locals
|
|
514
|
+
uv sync --extra dev
|
|
515
|
+
uv run pytest tests -q -m "not model"
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
## Citation
|
|
519
|
+
|
|
520
|
+
If you use Locals in your research, please cite the paper:
|
|
521
|
+
|
|
522
|
+
```bibtex
|
|
523
|
+
@article{asadulaev2026breaking,
|
|
524
|
+
title = {Breaking the Space Barrier and its Application to Language Model Inference},
|
|
525
|
+
author = {Asadulaev, Arip},
|
|
526
|
+
journal = {arXiv preprint arXiv:2610.09139},
|
|
527
|
+
year = {2026}
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
## License
|
|
532
|
+
|
|
533
|
+
Locals is released under the MIT license. It is made by
|
|
534
|
+
[Generated Computers](https://github.com/Generated-Computers).
|