Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/release-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- **Windows** (Windows 10 or newer, 64-bit): `Lucid-…-win-x64.exe`. Run it; it installs for you and starts Lucid. Lucid is not signed, so Windows SmartScreen may say "Windows protected your PC": click **More info**, then **Run anyway**. A portable `.zip` is also there.
- **Linux** (64-bit): `Lucid-…-linux-amd64.deb` for Debian and Ubuntu (`sudo apt install ./Lucid-…-linux-amd64.deb`), or `Lucid-…-linux-x86_64.AppImage` for other distributions (make it executable, then run it).

Then start [LM Studio](https://lmstudio.ai) with the model `qwen/qwen3.8-27b`. Details are in the [README](https://github.com/triggeredcode/lucid#install).
Then start [LM Studio](https://lmstudio.ai) with the model `qwen/qwen3.8-27b`. Steps for each system, checksums and troubleshooting are in [docs/install.md](https://github.com/triggeredcode/lucid/blob/main/docs/install.md).

Check a download with `shasum -a 256 --ignore-missing -c SHA256SUMS` (macOS, Linux) or `Get-FileHash` (Windows) against the file `SHA256SUMS`.

14 changes: 13 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ pnpm dev
You do **not** need LM Studio for tests: unit, integration and end-to-end tests use a scripted server
(`packages/mock-lmstudio`). Only `pnpm eval` and `pnpm e2e:real` use a real model.

| Command | |
|---|---|
| `pnpm dev` | the app, with reload |
| `pnpm test` | unit tests (all packages) |
| `pnpm e2e` | Electron end-to-end tests with a fake LM Studio, in a maximized window (written and run on a Mac) |
| `pnpm run ci` | typecheck, lint, formatting and unit tests |
| `pnpm eval` | 74 cases (and their variants) against the real model in LM Studio; see [`docs/evals.md`](docs/evals.md) |
| `pnpm dist` | builds the installers for the system it runs on into `apps/desktop/release/`: a `.dmg` and `.zip` (macOS), an installer and `.zip` (Windows), an `.AppImage` and `.deb` (Linux) |
| `pnpm e2e:packaged` | runs the end-to-end tests against the built app, on any of the three systems (after `pnpm dist:dir`) |

How the code fits together, and what each package does, is in [`docs/architecture.md`](docs/architecture.md).

## Before you open a pull request

```bash
Expand All @@ -29,7 +41,7 @@ pnpm e2e # the Electron tests, in a maximized window (do not touch the key
- End-to-end tests call `maximizeWindow` (see `apps/desktop/e2e/helpers.ts`): Lucid is made for a full-screen window.
- If your change touches the prompts or the pipelines, run `pnpm eval` with the model and say what changed in the pass
rates (see [`docs/evals.md`](docs/evals.md)).
- Update the README, the guide (`docs/guide.html`) and the changelog when something a person sees changes.
- Update the docs (the README, `docs/`, the guide `docs/guide.html`) and the changelog when something a person sees changes.

## Three systems

Expand Down
277 changes: 52 additions & 225 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/desktop/scripts/afterPack.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// - It refuses an app that lacks a file it must carry (for example Electron was never downloaded, so its licence notices were
// not there to copy): a broken build must stop here instead of shipping.
// - On a Mac it signs the app "ad hoc" (no identity): Apple Silicon only runs signed code, and without a developer certificate
// this is what lets it run once the person has allowed it (see README: Install).
// this is what lets it run once the person has allowed it (see docs/install.md).
const { execFileSync } = require("node:child_process");
const { existsSync } = require("node:fs");
const path = require("node:path");
Expand Down
44 changes: 44 additions & 0 deletions docs/accessibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Lucid and accessibility

## Why Lucid exists

Lucid started because its author broke their right hand and still wanted to take notes while learning system design. Typing
with one hand is slow, and a dictation app on its own gives you a wall of text, when what you want is the structure: headings,
the options with the rejected ones crossed out, a table, a diagram. So Lucid takes what you say and builds the structured
document while you talk.

It is not a medical or assistive device, and it has not been audited with screen readers or checked against accessibility
standards. What follows is what it does today, so you can judge whether it helps you.

## Using it by voice

Lucid does no speech recognition itself: a dictation app turns your voice into text and pastes it into Lucid's input box (see
[dictation](dictation.md) for free and open-source choices). From there:

- **Notes without pressing Enter.** A pasted dictation is sent by itself about half a second after the last piece arrives.
- **Commands by voice.** In Command mode, say what to change: *"cross out Memcached, we are choosing the local LRU"*, *"add a
CDN in front of the web server"*, *"undo"*. Say *"command mode"*, *"input mode"* or *"edit mode"* to change mode.
- **One key for one command.** Hold the **right ⌥ key** (right Alt on Windows and Linux) and everything you dictate while it is
held is one command. It is a single key, which you can reach with one hand.
- **Diagrams and tables without a mouse.** Say *"diagram mode"*, then the components, then the connections (*"client to
server"*), then fix them by number (*"rename 3 to Cache"*). *"Done"* inserts it. Tables work the same way.
- **Pointing by number.** Every block has a number in the margin; say *"in block 3, add a row for cost"*.
- **Everything can be taken back.** Every change by the model is one undo step, and the history lists each change, so a
misheard word never costs more than one *"undo"*.

## Using it with one hand

- The three modes and both builders have shortcuts (⌘1 to ⌘5, ⌘/ to switch between Input and Command), and Esc and ⌘L go back to
the input box. Zoom for the page is ⌘+, ⌘− and ⌘0. The full list is in the [guide](guide.html#keys).
- Choose a push-to-talk key for your dictation app that you can press with one hand. Lucid's own command key is the right ⌥,
so pick another for dictation (VoiceNative's default, the right Shift, does not meet it).
- Light and dark themes, three typefaces for the page and a zoom for the page are in Settings and the View menu.

## What it does not do yet

- It does not listen to you itself; it needs a dictation app.
- Speech recognition mistakes (a name, a tool) are kept as heard. Settings → **Words to expect** lists names that should be kept
as written, and *Edit and send again* in the history puts your words back in the box to fix.
- The language model is usually right, not always. Edit mode is there for the rest.
- Buttons and fields have names that a screen reader can read and the app is tested through those names, but nobody has used it
with a screen reader for real work. If you do, please [say what happens](https://github.com/triggeredcode/lucid/issues/new/choose).
98 changes: 98 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# What Lucid does

Engineers think in structure. A system design is an outline of sections and sub-sections, a list of options with the rejected
ones crossed out, a table that compares them and a diagram of how the parts connect. Lucid builds exactly that document while
you think out loud, so you never stop to format.

```mermaid
flowchart LR
say["You say or type<br/>'Options are Redis and Memcached…'"] --> model["A local model<br/>(LM Studio)"]
model --> page
subgraph page["A Lucid page"]
direction TB
H["Heading<br/>## High-level design"] --> SH["Subheading<br/>### Data model"]
H --> D["Diagram<br/>components and connections"]
SH --> L["List<br/>options, rejected ones crossed out"]
SH --> T["Table<br/>option against option"]
end
page --> out["PDF · Markdown<br/>.lucid file · AI agents"]
```

## Typed blocks

Everything on a page is a **typed block**. The model only chooses which block fits what you said and fills it in; Lucid draws
and typesets it, so the result looks the same every time.

| Block | What it holds | How it is drawn |
|---|---|---|
| **Heading, subheading** | the outline: title, sections, sub-sections | numbered sections in the PDF |
| **List** | options, steps, trade-offs; bullets, numbered steps and checklists, each item on its own so one can be crossed out | bullets, struck-through when rejected |
| **Table** | a comparison: properties by options | a typeset table |
| **Diagram** | how parts connect: architecture, request flow, sequence, entities | drawn from components and connections, a database as a cylinder, a queue as a pipe |
| **Callout** | the key takeaway, a decision, a trade-off, a warning, an open question | a highlighted box |
| **Formula** | back-of-the-envelope maths (KV-cache size, FLOPs, bandwidth) | typeset LaTeX maths |
| **Chart** | numbers you dictated: bars or lines | a labelled chart |
| **Code** | an API request, a query, a shell command | a code listing |

What stays true whatever you say:

- **The model never writes LaTeX or drawing code.** It fills blocks; a fixed house style does the typography.
- **You stay in charge.** Every change by the model is exactly one undo step, any earlier change can be reverted on its own, and
your words are never lost: if the model cannot use them, they are kept as written.
- **One view.** The page, one input box under it, an optional history panel. It scales to a full-screen window.

## Three modes, one box

| Mode | Your words are | Switch |
|---|---|---|
| **Input** | notes, written into the page and structured | ⌘1 |
| **Command** | instructions about the page: "add a CDN in front of the web server", "undo" | ⌘2, or hold the right ⌥ key for one command |
| **Edit** | typing in the page itself | ⌘3 |

⌘4 opens the diagram builder and ⌘5 the table builder. Each mode can also be chosen by voice ("command mode"). Changes that
would throw something away wait for a yes; when Lucid is unsure which thing you mean, it asks.

## Diagrams and tables by voice

A diagram of ten parts is hard to say in one breath, so there is a guided builder: say the **components**, then the
**connections** ("client to server"), then fix them **by number** ("rename 3 to Cache", "reverse 2"). A database is drawn as a
cylinder, a queue as a pipe, a CDN as a cloud, a load balancer as a hexagon. Big diagrams stay readable in the page and in the
PDF. Tables have a builder in the same spirit.

![The diagram builder: numbered components and connections beside the drawing](images/diagram-builder.png)

## Say which block you mean

Every block has a light number in the margin (B1, B2, …). Click one to see its parts, then say *"in block 3, add a row for
cost"* or *"cross out item 2 of block 6"*. The numbers can be hidden in Settings.

![Block numbers in the page margin; block 4, a diagram, lists its numbered parts and connections](images/block-numbers.png)

## History you can trust

The panel on the right lists what you said and every change to the page: by Lucid, by a builder, by an AI agent, or a revert.
**Show** scrolls to what a change touched. **Revert** takes back *one earlier* change, not just the last, and leaves later
changes to other blocks alone.

## Export, and how the PDF looks

- **PDF**, typeset with Tectonic in a fixed house style (numbered sections, real tables and figures, formulas). Settings →
**PDF look** changes the paper (A4 or Letter), the text size, the typeface, the margins, an accent colour, whether headings
are numbered and whether the date shows.
- **Markdown** (diagrams as Mermaid blocks).
- **A `.lucid` file**, the whole note with its history, to back up, move to another computer or share.

![A page of the exported PDF: a numbered section, a diagram and a footer](images/pdf-page.png)

Light and dark themes, three typefaces for the page on screen, and a zoom for the page (⌘+, ⌘−, ⌘0) are in the app. Pages are
plain files in `~/Lucid` (one JSON file per page).

## Note formats

A **note format** is the skeleton of a page. See [formats](formats.md).

## Agents, dictation, accessibility

- [Dictation](dictation.md): which apps to speak with, and a ten-minute check-list.
- [Accessibility](accessibility.md): why Lucid exists, and how to use it by voice or with one hand.
- [For AI agents](mcp.md): Lucid is an MCP server.
44 changes: 44 additions & 0 deletions docs/formats.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Note formats

A **note format** is the skeleton of a page: its sections, a hint for each saying what belongs there, and which blocks suit it.
Start a page from one with **New from a format…**; Lucid suggests one from what you say, and you always choose. A page of a
format starts as its section headings, and what you dictate goes under the right one. Sections left empty are not printed.

| Format | For | Sections |
|---|---|---|
| **Concept note** | one computer-science or system-design idea | Definition · Intuition · How it works · Example · Pitfalls and gotchas · Related concepts |
| **System design** | designing a system end to end | Requirements · Capacity estimates · API · High-level design · Data model · Deep dives · Trade-offs and decisions · Open questions |
| **Comparison** | choosing between technologies | Context · Options · Comparison · Pros and cons · Decision |
| **Inference engineering** | KV cache, FLOPs, bandwidth, batching | Intuition · The math · Numbers to remember · Hardware implications · Pitfalls |
| **Benchmark** | recording an experiment | Goal and hypothesis · Setup · Method · Results · Observations · Next experiments |

## What the PDFs look like

Each picture is the PDF of a sample note, made with the real app ([how](format-samples/README.md); the numbers in them are made up).

**Concept note**

![A concept note as a PDF: definition, a diagram, a worked example and pitfalls](format-samples/format-concept-note.png)

**System design**

![A system design note as a PDF](format-samples/format-system-design.png)

**Comparison**

![A comparison note as a PDF](format-samples/format-comparison.png)

**Inference engineering**

![An inference engineering note as a PDF](format-samples/format-inference-math.png)

**Benchmark**

![A benchmark note as a PDF with a table and a chart](format-samples/format-benchmark.png)

## Open to other fields

The formats lean towards engineering because that is what Lucid was made for, but nothing else in Lucid does. A format is a
small data entry in [`packages/kit/src/formats/index.ts`](../packages/kit/src/formats/index.ts): an id, a description, keywords
for the suggestion, the sections and the blocks that suit them. A lab notebook, a reading log or a study plan is one more
entry. New block types (one folder each) work the same way. See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-a-note-format).
92 changes: 92 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Installing Lucid

Lucid runs on **macOS** (Apple Silicon, macOS 13 or newer), **Windows** (Windows 10 or newer, 64-bit) and **Linux** (64-bit).
The [website](https://triggeredcode.github.io/lucid/#download) offers the right download for your computer; all of them are on
the [latest release](https://github.com/triggeredcode/lucid/releases/latest).

| System | Download | Notes |
|---|---|---|
| **macOS** | `Lucid-<version>-mac-arm64.dmg` (or `.zip`) | Apple Silicon, macOS 13 or newer |
| **Windows** | `Lucid-<version>-win-x64.exe` installer (or the portable `.zip`) | Windows 10 or newer, 64-bit |
| **Linux** | `Lucid-<version>-linux-amd64.deb`, or `Lucid-<version>-linux-x86_64.AppImage` | 64-bit; the `.deb` is for Debian and Ubuntu |

## 1. Install the app

**macOS.** Open the `.dmg` and drag **Lucid** to **Applications**. macOS will say it cannot check the app for malicious
software, because Lucid is a free open-source app that is not notarized by Apple. Allow it once: on macOS 15 and newer, open
**System Settings → Privacy & Security**, scroll to the message about Lucid and click **Open Anyway**; on macOS 13 and 14,
right-click Lucid in Applications, choose **Open**, then **Open** again. Or in Terminal:

```bash
xattr -dr com.apple.quarantine /Applications/Lucid.app
```

**Windows.** Run the installer. It installs Lucid for you (no administrator needed) and starts it. Lucid is not signed, so
Windows SmartScreen may say "Windows protected your PC": click **More info**, then **Run anyway**. To remove it: Settings →
Apps → Lucid.

**Linux.** With the `.deb` (Debian, Ubuntu and relatives), then start **Lucid** from the menu, or run `lucid`:

```bash
sudo apt install ./Lucid-<version>-linux-amd64.deb
```

With the AppImage (any distribution):

```bash
chmod +x Lucid-<version>-linux-x86_64.AppImage && ./Lucid-<version>-linux-x86_64.AppImage
```

On Ubuntu 24.04 and newer an AppImage can stop with a sandbox message: use the `.deb`, or start the AppImage with `--no-sandbox`.

## 2. Set up the language model

Install [LM Studio](https://lmstudio.ai) (it runs on all three systems), download the model **`qwen/qwen3.8-27b`**, and start its
local server (Developer tab). Lucid's pill at the top says what is missing and can load the model for you.

Lucid is evaluated with `qwen/qwen3.8-27b` only. Another model can be named in Settings, but expect more misses. A 27B model
needs a lot of memory; Lucid was developed on a Mac with 48 GB.

## Checking a download

Each release lists SHA-256 checksums (`SHA256SUMS`). In the folder with both files, on macOS and Linux:

```bash
shasum -a 256 --ignore-missing -c SHA256SUMS
```

On Windows, in PowerShell, then compare the result with the line for your file:

```powershell
Get-FileHash .\Lucid-<version>-win-x64.exe -Algorithm SHA256
```

## Good to know

- Nothing else needs installing: the PDF engine ([Tectonic](https://tectonic-typesetting.github.io)) and the diagram drawing
come with the app, on every system.
- **The first PDF needs the internet, once.** Tectonic downloads its typesetting files the first time it runs (several hundred
small ones, about five minutes). Lucid does it in the background after the first start and shows the progress next to
*Download PDF*. After that PDFs take a second or two and work offline. A typeface other than the default one (Settings →
PDF look) is fetched the first time it is used.
- Every build is tested on GitHub's own macOS, Windows and Ubuntu machines before a release (it starts, makes a PDF with a
diagram, and connects an AI agent). The Mac version has had the most everyday use: please
[report](https://github.com/triggeredcode/lucid/issues/new/choose) what is off on Windows or Linux.
- On Windows and Linux the shortcuts use **Ctrl** where the docs say ⌘ (⌘1 is Ctrl+1), and **Alt** where they say ⌥.

## Troubleshooting

| You see | Do |
|---|---|
| *LM Studio isn't running* | Start LM Studio and its local server, then click **Check again**. |
| *No model loaded* | Click **Load …** in the pill, or `lms load qwen/qwen3.8-27b --context-length 32768 --parallel 1 -y`. |
| A request takes 10 to 25 seconds | Normal for a 27B model on a laptop; the first request after a change is the slowest. |
| *Getting the PDF engine ready…* | Normal on the first start: wait, it counts the files. A PDF you ask for meanwhile waits for it. |
| Words were kept as *unprocessed* | The model could not use them; they are kept as written. Say them again, or fix them in Edit mode. |
| Dictation does nothing | Is Lucid the focused window? A paste goes to the input box wherever the focus is in the window. See [dictation](dictation.md). |

More in the [guide](guide.html). Something else? [Open an issue](https://github.com/triggeredcode/lucid/issues/new/choose).

## Build it yourself

See [CONTRIBUTING.md](../CONTRIBUTING.md#set-up).
Loading
Loading