Inside LOCY

The whole app, in the open.

No model in the installer. No account. Nothing measured about you. Below is every part of LOCY — what it does, which file it lives in, and what happens when something goes wrong. Read it, then take it with you.

Start the walk
LOCY running on a Windows desktop, chatting in Arabic
180 MBStore package, no model inside
0Telemetry, accounts, sign-ins
2Platforms: Windows and Android
23Parts, all written down here

Before you read anything

Will it run on this computer?

Reading this machine…

Read by your browser, on your machine, and never sent anywhere. Chrome caps memory at 8 GB, so a large machine may read smaller here than it really is.

—

Measuring…

In the app, LOCY also reads your graphics card and free disk, then picks a model that fits — not one that thrashes.

01

Does it come with a model?

No. Nothing is downloaded until you choose one, and every model is a plain GGUF file on your own disk.

1.1

What models can I get?

A search of Hugging Face, filtered to the models that can actually run on the machine you are using.

The machinery

What it is

A list of downloadable chat and vision models with size, quantization, and a note when a model is gated and needs a Hugging Face account.

How it is made

The main process talks to the public Hugging Face API: /api/models for the search and /api/models/<id>/tree/main for the file list, plus the model README for the description. No key for public models; a personal token only for gated ones.

How it works

You type in the catalog screen; the query goes to the main process, and the renderer never touches the network itself. The page is sandboxed and its content security policy allows connections only to 127.0.0.1. Every cursor the API returns is checked to be on huggingface.co before it is followed, so a hostile response cannot redirect you elsewhere.

1.2

Which one fits my computer?

Two picks made for your machine, not for the average machine.

The machinery

What it is

A “best for this computer” pick and one bigger option, shown on the first-run screen and in the catalog.

How it is made

The same tier logic the desktop app uses, src/lib/device-fit.ts, ranks the machine by usable video memory and system memory; the catalog filters by what fits.

How it works

Your hardware is read once at startup: processor, memory, graphics card, free disk. The result is a tier from tiny to ultra, and the recommendation asks for a model that fits inside it. A machine with 8 GB of RAM gets a 2 GB model, not a 30 GB one.

1.3

Can it inspect a model without loading it?

Yes — name, architecture, context length and whether the file is complete, without touching the weights.

The machinery

What it is

Metadata about a .gguf file: real model name, architecture, context length, quantization, and whether the file is whole.

How it is made

The GGUF metadata block is parsed directly. Only the header is read — a 24 MB window — never the whole file, so a 30 GB model costs kilobytes to inspect.

How it works

A download that stopped early still has a valid header, so it would look fine. LOCY compares the last tensor offset against the end of the file and labels the model incomplete instead of letting you wait for a two-minute timeout later.

1.4

Can it see pictures?

With a vision model, yes — and it takes two files instead of one.

The machinery

What it is

Support for sending an image to a model that can read pictures.

How it is made

A vision model is paired with a separate mmproj projector file. The two run in a second, independent engine on its own port.

How it works

The projector is never loaded as a model — passing it to llama.cpp as -m is fatal, so LOCY keeps them apart. Attach a picture to a model that cannot see and the app says so plainly. Projectors never show as “running” either: they are an encoder, not a chat model.

1.5

Is there a model in the installer?

No. Not on Windows, not in the Store package, not on Android. That rule is why the Store download is 180 MB instead of 877.

The machinery

What it is

No installer contains a model. The first launch does nothing to your models folder.

How it is made

What used to seed a starter model was removed from electron/lib/firstrun.js, from the Android application class, and from the packaging configuration.

How it works

On first run the app only checks whether a model already exists on the computer and points at it. Everything else is your choice — from the catalog, or from a file you already had.

02

Where does the thinking happen?

On your machine. A real llama.cpp server, sized to your hardware, streaming tokens back to the interface.

2.1

What actually runs the model?

llama.cpp, packaged with the app so it works on a machine with nothing installed.

The machinery

What it is

llama-server from llama.cpp, shipped inside the app under resources/llama.

How it is made

A pinned llama.cpp release is fetched by scripts/fetch-llama.mjs and unpacked into a tier folder: win-vulkan-x64, win-cuda-12_4-x64, win-cpu-x64, macos-arm64, linux-x64.

How it works

The Vulkan build accelerates NVIDIA, AMD and Intel from one binary and ships CPU libraries so it still runs where no supported driver exists. LOCY prefers a path you configured, then the bundled copy, then anything on your system.

2.2

How does it fit in my memory?

Before anything starts, the machine gets a plan: how much context, how many layers, how big a batch.

The machinery

What it is

A set of numbers that decides how the engine launches, so it fits in your memory instead of thrashing.

How it is made

electron/lib/tuning.js holds one table per tier: batch and micro-batch sizes, the KV cache type (q8_0 for smaller tiers, f16 for big ones), context length, threads, and how many layers go on the graphics card.

How it works

The tier comes from usable video memory and system memory, and the plan is handed to the server as flags: --ctx-size, --n-gpu-layers, --threads, --threads-batch, --batch-size, --ubatch-size, --parallel 1. You can turn automatic tuning off and set the numbers yourself.

2.3

Why does the answer arrive word by word?

Because the interface never waits for the whole answer to exist.

The machinery

What it is

A live stream: start, reasoning, deltas, and a final done, stopped or error.

How it is made

electron/lib/inference.js posts to the local llama.cpp endpoint and parses the server-sent events. The renderer subscribes through the preload bridge and re-dispatches them as application events.

How it works

Every event carries a request id, so a stopped or replaced reply cannot bleed into the next one. The reasoning budget is kept small on purpose — a 1.7B model spends more tokens thinking than answering. Stopping is a first-class event, not a timeout, and the final payload carries token counts and speed.

2.4

What is different on a phone?

There is no server process. The phone runs llama.cpp inside its own process, through a native library.

The machinery

What it is

The same engine, linked directly instead of started as a process.

How it is made

android/app/src/main/java/com/locy/app/LlamaEngine.java calls native methods — nativeLoad, nativeChat, nativeStop — inside liblocyllama.so, built from llama.cpp with the NDK.

How it works

The interface is the same web build the desktop uses, served by a small Java HTTP server bound to 127.0.0.1:8731. The bridge between the page and the phone is a JavaScript interface object, so the page never touches the file system itself.

03

Will it fit my computer?

The readout at the top of this page was your browser guessing. Here is what the app does for real.

3.1

How does it know what I have?

Processor, memory, graphics card, disks — and how much of the graphics memory is really usable.

The machinery

What it is

A snapshot of the machine, shown in the settings and used to size the engine and the recommendations.

How it is made

Node's os module for the processor and memory; on Windows a short PowerShell script (Get-CimInstance Win32_VideoController, Win32_PhysicalMemory, Win32_OperatingSystem) for the graphics card, memory modules and OS name; nvidia-smi for NVIDIA details.

How it works

The interesting part is filtering out integrated graphics. An Intel UHD or Iris card is shared memory, not video memory, so counting it would promise models that cannot fit. Only a dedicated card counts toward the tier — except Intel Arc, which is dedicated and is kept.

04

What does it feel like?

The same interface on both platforms, in Arabic, right to left.

4.1

What am I actually looking at?

No browser chrome, no web page framing — an app, with its own title bar and buttons.

The machinery

What it is

A frameless desktop window with its own title bar and window buttons, and an interface that reads right to left in Arabic by default.

How it is made

Electron with the frame hidden and the controls drawn by the app itself. Direction is set on the document root and the CSS mirrors with logical properties, so one stylesheet serves both directions.

How it works

The renderer is sandboxed, context isolation is on, node integration is off. It reaches the system only through a fixed list of channels in electron/preload.cjs, and a parity test checks that the bridge and the preload never drift apart.

4.2

Can I find things fast?

A command palette, a search box in the sidebar, and a first paint that does not wait for everything.

The machinery

What it is

A command palette on Ctrl/Cmd+K, a search box in the sidebar, and a build that splits on demand.

How it is made

The sidebar search calls conversations:search, which walks the conversation index and matches both titles and message text. Routes load when you open them, and the Markdown renderer (KaTeX and the highlighter) is a separate chunk that arrives with the first message.

How it works

Typing is debounced and stale responses are dropped, so results can never arrive out of order. Splitting the bundle took the first chunk from about 1 MB down to roughly 340 KB, and the heavy Markdown chunk only loads when a reply is actually on screen.

The LOCY model catalog
The catalog, filtered to what fits
Searching inside conversations
Search inside every message
LOCY settings
Tuning, theme and storage
05

Can it touch my files?

Only inside the folder you chose, and only when you allow it.

5.1

What can it read and write?

Attachments, dropped files, and a project folder the assistant may read and edit.

The machinery

What it is

Attaching a picture or a text file, dropping files onto the chat, and a project folder the assistant may work in.

How it is made

electron/lib/files.js keeps a list of allowed roots — the folder you picked and your data folder — and every path is resolved and checked against that list before it is opened.

How it works

Attached files are copied into the conversation, so the chat still works after you move or delete the original. Pictures travel to a model as a base64 data URL inside the request. Nothing outside the allowed roots can be read, even by a path that tries to climb out of them.

Halfway through, and nothing has asked you to sign in. That is the point.

Get Locy
06

Where are my chats?

Plain files on your disk. No account, no server, no sync.

6.1

Where does a chat live?

One JSON file per conversation, plus an index — readable, copyable, deletable by you.

The machinery

What it is

Your chats as files you can open, copy or delete yourself.

How it is made

electron/lib/conversations.js writes one file per conversation into a conversations folder next to your settings, plus an index.json for fast listing.

How it works

Writes are atomic: the file goes to a temporary name and is renamed into place, so a crash mid-save can never leave a half-written conversation. The index is rebuilt if it ever goes missing.

6.2

Can I take them with me?

Everything, in one file you can keep.

The machinery

What it is

An export of your conversations, settings and model list, and an import that puts it back.

How it is made

electron/lib/backup.js collects the data folder and writes it as an archive; the import reads the archive back and merges it in.

How it works

Backups can be taken by hand or on a schedule, and the list is kept in the data folder so you can restore the one you want. Model files are never included — they are large, and you already have them.

07

What if the download drops?

A model is hundreds of megabytes, so the transfer has to survive reality.

7.1

Does it resume?

Wi-Fi drops, sleep, a closed lid — the download continues from where it stopped.

The machinery

What it is

A queue of transfers with progress, speed and an estimate, that resumes after an interruption and knows the difference between slow and dead.

How it is made

electron/lib/downloads.js writes to a .part file and asks the server for the rest with a Range header. Android has its own copy in Downloader.java.

How it works

If the server ignores the range request, the transfer restarts from zero rather than corrupting the file. If no bytes arrive for a minute it is marked interrupted instead of hanging. When it finishes, the file is checked: a size that does not match the length the server promised means the download failed, and a file that does not start with the GGUF signature is rejected rather than handed to the engine.

7.2

Does it keep going on a phone?

Yes — a foreground service, so the phone does not kill the transfer when you lock the screen.

The machinery

What it is

The transfer continues with the app in the background, with a progress notification in the shade.

How it is made

android/app/src/main/java/com/locy/app/DownloadService.java is a foreground service of type dataSync that holds a partial wake lock while bytes are moving.

How it works

The queue mirrors itself into the service on every status change. When nothing is queued or downloading, the service stops itself and releases the wake lock. On Android 13 and later the notification permission is requested when the first download starts.

08

Can I talk to it?

Optional, and local when you point it at something local.

8.1

Speaking and transcribing

Read a reply aloud, or turn your voice into a message.

The machinery

What it is

Speech to text for your messages, text to speech for the replies, and a list of the recordings you made.

How it is made

electron/lib/audio.js talks to whichever endpoint you configured — a local Whisper or TTS server, or a hosted one if you point it there. Recordings are written into the data folder.

How it works

Nothing is sent anywhere unless you have configured a remote endpoint. On Android the audio tools are not available, and the app says so instead of hiding the buttons.

09

What leaves my machine?

Almost nothing, and here is the whole list.

9.1

The whole list

Model downloads from Hugging Face, and the catalog searches that find them. That is it.

The machinery

What it is

Two kinds of request, and no third.

How it is made

The page's content security policy allows connections only to itself and to 127.0.0.1 — your own machine. Everything else is a deliberate call in the main process.

How it works

Chats are written to your disk and never uploaded. There is no telemetry, no analytics and no account. The privacy policy on this site is the same text published on the Microsoft Store listing.

9.2

What stops the dangerous parts?

Sandboxing, path checks, and a strict list of allowed channels.

The machinery

What it is

The guards that would matter if they were missing.

How it is made

electron/main.js sets sandbox: true, contextIsolation: true and nodeIntegration: false, and installs a content security policy with no unsafe-eval. File access goes through the allowed-roots check.

How it works

The renderer can only reach the system through the preload bridge, and a parity test compares the bridge interface with the preload file so a capability cannot appear in one and not the other. A script checks every Arabic string has a translation, so a half-translated interface cannot ship by accident.

10

How do I get it?

Two builds from one source, with the same rules.

10.1

On Windows

The Microsoft Store installs it and keeps it updated. There is also a plain installer.

The machinery

What it is

An NSIS installer, and an MSIX built with Microsoft's own packaging tool for the Store.

How it is made

electron-builder produces the installer; scripts/package-msix.ps1 stages the payload and packs it with makeappx. The package identity is the one reserved in Partner Center.

How it works

The package carries no model — the rule from section 01. The version in the manifest is rewritten for each Store update while the app keeps its own version, so a release can reuse the same payload.

10.2

On Android

One APK, about 5 MB: the interface, the engine and a small bridge.

The machinery

What it is

A single APK with the web interface, the native engine and the Java bridge that connects them.

How it is made

The web build is copied into the app's assets, the native library is built with the NDK, and the shell is plain Java — no Kotlin, no Compose. The package is com.locy.app, arm64 only, signed with a local key so it installs by sideloading.

How it works

The app starts a local server on 127.0.0.1:8731 and loads the interface from it. The bridge exposes a fixed set of methods, and the engine runs inside the process instead of as a server.

10.3

How do updates work?

Store builds update themselves. A sideloaded installer has to be told.

The machinery

What it is

One quiet check per launch that tells a packaged app when a newer version exists.

How it is made

electron/lib/update.js reads the public Store catalog and compares the published package version with the running one.

How it works

Nothing happens unless the Store serves something newer, and any failure is a silent no-op — a slow network must never turn into an error dialog. When there is a newer build the app shows one quiet notice with a link to the Store.

That is the whole thing.

Every part, in the open, with nothing hidden behind a sign-in. If it fits your machine, you can be talking to a model of your own in about two minutes.

No accountNo telemetryNo model in the installer
لوسي