# LlamaPen is a static bundle that talks to whatever model you already run

> An AGPL-3.0 web front end for Ollama and other local providers, with chats kept in your own browser and a container that is nothing but nginx serving a dist directory. The hosted version of the same product was shut down and its accounts deleted.

**ImDarkTom/LlamaPen** — A no-install needed GUI for Ollama and other local LLM providers.

- Repository: https://github.com/ImDarkTom/LlamaPen
- Website: https://llamapen.app
- Stars: 449 · Forks: 39
- Language: Vue
- License: AGPL-3.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/imdarktom-llamapen

## The published image is nginx and a dist directory

The Docker route is the recommended one, and the image it pulls is smaller than the feature list suggests. The build stage uses a slim Bun image, installs from the lockfile, copies the source and runs the Vite build. The serving stage is nginx:

```bash
docker pull ghcr.io/imdarktom/llamapen:latest
```

```bash
docker run -d -p 8080:80 --name llamapen --restart unless-stopped ghcr.io/imdarktom/llamapen:latest
```

What gets copied into that nginx image is the `dist` directory and a custom nginx configuration. There is no application server, no runtime and no database in the image.

That is not a simplification for marketing; it is the architecture. Everything the interface does happens in your browser, and the provider calls go from that browser to whatever you configured. The container is a file server, which is also why the port argument is presented as freely swappable: nothing inside it cares which host port you pick.

The repository carries a `vercel.json` next to the `nginx.conf`, which suggests the same static bundle is also laid out for a static hosting platform.

## Chat history is IndexedDB in one browser profile

The privacy claim in the setup section is specific: chats are stored locally in the browser, which the README pairs with near-instant chat load times. Nothing is sent to a LlamaPen server because there is no LlamaPen server.

The dependency list confirms the mechanism. Dexie is present as the IndexedDB wrapper, and Pinia carries a persisted-state plugin, so conversation state is written to the browser's own database rather than fetched. Fake IndexedDB appears among the development dependencies, which is what lets the component tests run without a real browser database.

That design has a consequence worth stating plainly. Local storage means your history is bound to one browser, one profile and one origin. Clearing site data deletes it, and the same history is not visible on your phone unless you install the PWA on the same device and profile.

Offline and PWA support are listed as features, which is the other half of keeping state client-side: the interface can load and read history without a network round trip, even though sending a message obviously still needs the provider.

## The Ollama address is baked in at build time

There is exactly one environment variable in the example file:

```
VITE_DEFAULT_OLLAMA=http://127.0.0.1:11434
```

Ollama is preconfigured, which is why the setup guide says that if Ollama is what you are running there is nothing to configure. The default points at the standard Ollama port on the loopback interface.

Here is where the Docker instructions and that default meet. The published container runs nginx and holds no application process, so there is nothing inside it listening on 11434. From the browser on your machine, `127.0.0.1` resolves to your own machine, so the default works for the manual setup and for a browser reaching a host Ollama directly. Inside the container the same address would point at the container itself, so anyone running the image against a host Ollama needs a reachable hostname or address configured in the providers section rather than relying on the default.

The variable name carries the Vite prefix, which means it is read at build time. Changing it in a `.env` file after the image is built does nothing, so it belongs to the manual route, not the container one.

## Two SDKs for the providers, one sanitiser for the output

Both provider protocols are wired in at the dependency level. The Ollama client is there, and the OpenAI client is there as well, which is what lets the same interface talk to Ollama, llama.cpp, LM Studio, Jan and vLLM: the first four speak one protocol or the other, and anything else speaking the OpenAI-compatible API can be added by hand from the providers section. Hosted APIs can be added the same way, and the README states that requests only ever go to the providers you configure.

Rendering is the part with more moving pieces than the provider layer. Markdown is handled by marked, LaTeX by katex with an extension for marked, and syntax highlighting by highlight.js. Reasoning output, which the feature list calls think text, is handled separately from the answer.

DomPurify sits next to those. The README does not mention sanitisation anywhere, so the safest reading is that it is there because a renderer that injects model output into the page needs it. If you fork this, that line of defence is the one you would want to keep rather than trim.

The rest of the stack is a Vue 3 application with Pinia for state, Vue Router, Reka UI components, VueUse, an event bus, Mustache templates for prompt handling, and Tailwind 4 for styling.

## Two runtimes, and one warns about version drift

The manual route is a clone, an install and a run, and it needs Git plus Bun, with Bun 1.3 the tested version:

```bash
git clone https://github.com/ImDarkTom/LlamaPen.git
cd LlamaPen
```

```bash
bun install
```

```bash
bun run local
```

What that last script does is worth knowing. It builds the application, prints where the result will be served, and then serves the `dist` directory on port 8080 in single-page mode. So the manual route produces exactly the same artefact the container serves, and the only difference is which file server puts in front of it.

The README calls this route slightly less preferable and warns that you might hit issues from differences in package and tool versions. That warning is consistent with the script definitions: development runs through `bunx --bun vite` and tests through `bunx --bun vitest`, so Bun is not only the package manager here but the JavaScript runtime, and pinning it matters.

The formatting and type gates are separate. `oxfmt` handles formatting and `vue-tsc` does the type check, with the build script running the Vite build and the type check together.

## The cloud service was switched off, accounts and all

One section of the README is a piece of history that any evaluation should account for. LlamaPen previously offered a cloud service for running larger models. That service has been discontinued. All user accounts have been deleted, and refunds issued.

The replacement path is worth knowing if you depended on it: built-in presets for OpenRouter and for Ollama's own cloud models in the providers section. So the route back to hosted inference is a provider preset rather than a LlamaPen subscription.

This is also why the no-backend architecture reads as a decision rather than an omission. The project moved from running models for you to running models next to you, and the repository now contains a file server, a static bundle and a set of provider clients.

Funding is handled through GitHub Sponsors and a coffee link, and the project describes itself as free and open source with no paid tier in the code.

## AGPL-3.0, plus four attributions and a font

The licence is AGPL-3.0, which is the single most consequential line in this README for anyone planning to modify or embed the project. It is a copyleft licence with a network use clause, and it is a different obligation from the permissive licences common in this category.

The attribution section is specific about what is not covered by it. Ollama is credited as the project the name draws on. Lobe Icons supplies the icon set and Nebula Sans supplies the font. A picture used in the preview image is credited to a Wikimedia Commons file by its identifier.

That list is useful in a second way. It tells you what the interface is assembled from, and the font and icon choices are the kind of detail that a fork has to keep or replace deliberately.

The default branch is `main`, the current release is v1.4.0 tagged on 2026-09-09, and the last push landed the same day. Earlier releases are v1.3.0 in June 2026 and v1.2.0 in May 2026, so the project moves in roughly quarterly steps.

## Conclusion

Adopt LlamaPen if you run models locally and want one interface that talks to Ollama, llama.cpp, LM Studio, Jan or vLLM, and you are content for chat history to live in one browser profile. Do not adopt it expecting a hosted service, since LlamaPen Cloud was discontinued with accounts deleted and refunds issued. Verify two things first. Decide how Ollama will be reached: the build-time default points at 127.0.0.1:11434, which inside the published container is the container itself rather than your machine. Then read the AGPL-3.0 terms, because they are the licence the project ships under and they carry obligations that MIT would not.

## FAQ

### What is LlamaPen and what is it for?

It is a no-install web interface for models running on your own hardware, with Ollama preconfigured and one-click presets for llama.cpp, LM Studio, Jan and vLLM. Anything speaking the OpenAI-compatible API can be added by hand, and hosted APIs can be added the same way.

### Where does LlamaPen store my conversations?

Locally in your browser. The dependency list includes Dexie and a Pinia persistence plugin, which points to IndexedDB, and the README states that chats are stored locally for privacy and fast loading. Clearing site data removes that history.

### How do I run LlamaPen with Docker?

Pull ghcr.io/imdarktom/llamapen:latest and run the container with port 8080 mapped to 80. The image builds with Bun and serves the built dist directory from nginx, so there is no application server inside the container.

### Can I run LlamaPen without Docker?

Yes. Clone the repository, run bun install and then bun run local, which builds the app and serves dist on port 8080 in single-page mode. You need Git and Bun, with Bun 1.3 the tested version.

### What happened to LlamaPen Cloud?

It has been discontinued. The README states that all user accounts have been deleted and any refunds issued. For hosted models it points to built-in presets for OpenRouter and for Ollama's native cloud models.

## Sources

- [ImDarkTom/LlamaPen on GitHub](https://github.com/ImDarkTom/LlamaPen)
- [License: AGPL-3.0](https://github.com/ImDarkTom/LlamaPen/blob/main/LICENSE)
- [Project website](https://llamapen.app)
- [README](https://github.com/ImDarkTom/LlamaPen/blob/main/README.md)
- [Releases](https://github.com/ImDarkTom/LlamaPen/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/imdarktom-llamapen
