Look - Keyboard-First Launcher#

Look Github Repository

Look is a keyboard-first, local-first launcher for macOS, Windows, and Linux. It gives you instant access to apps, files, folders, and system settings without leaving the keyboard.

Try it live#

Type in the launcher below - fuzzy search, a"/f"/d"/r" prefixes, and inline calc all work, right in your browser. Press Cmd/Ctrl+/ for command mode or Cmd/Ctrl+Shift+, for Appearance settings. This is a simplified offline playground; the real Look is faster and does more. Open the full-screen demo for more room.

Why Look?#

If you're tired of slow launchers or expensive tools like Raycast, Look is a free, lightweight alternative that stays out of your way.

  • Local-first - all indexing happens on your machine
  • Fast - typical search under 1 ms on a 2000-item index, with bounded query-time scoring
  • Usage-aware - results improve as you use them
  • Minimal permissions - no Accessibility, Full Disk Access, or Screen Recording
  • Private - no account, no telemetry; network only on explicit or opt-out actions
  • Native shells - SwiftUI on macOS, Tauri v2 on Windows/Linux, both over one Rust engine

Highlights#

  • Scoped search - a" apps, f" files, d" folders, r" regex, rc" recent, c" clipboard, t"/tw" translate
  • Inline calculator - type 2^10, 4!, 200*15%, sqrt(2); no mode switch
  • Web answers (optional) - an answer card for questions and unindexed entities, plus search suggestions
  • Command mode - pomodoro, daily todo with streaks, speed test, port-based kill, shell, system info
  • Super actions - Bluetooth, Wi-Fi, battery, theme, and more from the empty home screen
  • AI conversation (macOS, beta) - > for calendar actions, file recall, and text operations on a local model
  • Themeable - 8 presets including Kindle (light) and Liquid (glass), plus floating tile layout

Where to go next#

PageWhat's there
InstallationInstall, first launch, uninstall
Getting StartedBasic usage, query prefixes, quick math
Keyboard ShortcutsEvery key, in one place
Search ModesWhat the main input does beyond apps and files
Result ActionsWhat you can do to the selected row
Home ScreenRunning apps and the super-actions strip
Command Mode/calc, /todo, /speed and the rest
AIThe > conversation mode (macOS, beta)
Declared SourcesAdd your own rows from folders, files and commands
Settings PanelThe in-app settings, tab by tab
ConfigurationEvery ~/.look/config key
TroubleshootingWhen something doesn't work

Installation#

macOS#

Requirements: macOS 15.0+

bash
brew tap kunkka19xx/tap
brew install --cask look

Then bind Cmd+Space to Look - disable Spotlight's shortcut in System SettingsKeyboardKeyboard Shortcuts...Spotlight.

Spotlight

Update:

bash
brew upgrade --cask kunkka19xx/tap/look
Other macOS install options (curl, pin version)
bash
curl -fsSL https://raw.githubusercontent.com/kunkka19xx/look/main/scripts/install-look.sh | bash

Pin a version or fork:

bash
curl -fsSL https://raw.githubusercontent.com/kunkka19xx/look/main/scripts/install-look.sh | bash -s -- --version <version> --repo kunkka19xx/look

Linux#

Arch Linux (AUR):

bash
yay -S look-bin
# or
paru -S look-bin

Or without an AUR helper:

bash
git clone https://aur.archlinux.org/look-bin.git
cd look-bin
makepkg -si

Ubuntu/Debian:

bash
curl -fsSL https://raw.githubusercontent.com/kunkka19xx/look/main/scripts/linux/install-look.sh | bash

Or download the .deb manually from Releases and run sudo dpkg -i Look_*.deb.

Any distro (AppImage):

bash
chmod +x Look_*.AppImage
./Look_*.AppImage

NixOS (flake):

bash
nix run github:kunkka19xx/look?dir=apps/linows
# or install to profile
nix profile install github:kunkka19xx/look?dir=apps/linows

Pre-built binaries are served via Cachix. For declarative NixOS install, see the README.

Windows#

powershell
iex "& { $(irm https://raw.githubusercontent.com/kunkka19xx/look/main/scripts/windows/install-look.ps1) }"

SmartScreen may warn on first run - click "More info → Run anyway". The launcher's global hotkey is Alt+Space (not user-configurable yet; if it conflicts with another app, remap that app instead).

First Launch#

After installing, launch with lookapp from a terminal, or search "Look" in your app launcher / Start menu. On first run, Look indexes your apps, files, and folders in the background - results appear as indexing completes.

PlatformToggle hotkeyNotes
macOSCmd+SpaceDisable Spotlight's shortcut first
Windows / LinuxAlt+SpaceAutostarts on login (on full DEs like GNOME/KDE)

Window manager users (i3, sway, Hyprland, niri): Autostart via .desktop files only works on full desktop environments, so add Look to your WM config manually. On i3, sway, and Hyprland the Alt+Space hotkey and float rules register themselves at runtime, so the autostart line is all you need. niri has no runtime bind API, so its Alt+Space goes in config.kdl by hand; Look shows the exact stanza on first run. See the README for examples.

GNOME desktops: Log out and log back in after the first install so the GNOME Shell extension (for window focusing on Wayland) can load.

Uninstall#

bash
# macOS
brew uninstall --cask look

# Arch
yay -R look-bin

# Ubuntu/Debian
sudo dpkg -r lookapp

# Windows
iex "& { $(irm https://raw.githubusercontent.com/kunkka19xx/look/main/scripts/windows/install-look.ps1) } -Uninstall"

Remove local state (optional):

bash
# macOS
rm -rf ~/.look ~/Library/Application\ Support/look && rm -f ~/.look.config

# Linux
rm -rf ~/.look ~/.local/share/look && rm -f ~/.look.config

Permissions#

Look is designed to need as few permissions as possible:

  • No Accessibility permission required (macOS)
  • No Full Disk Access required - Look indexes standard user directories. Add extras via file_scan_extra_roots in ~/.look/config.
  • No Screen Recording required (macOS)
  • Network access is used only for explicit actions (t" translation, tw" dictionary lookup, Cmd/Ctrl+Enter web search) and the optional web answers feature, which you can turn off with ai_enabled=false

Getting Started#

Basic Usage#

  1. Open Look - Cmd+Space (macOS) or Alt+Space (Windows/Linux)
  2. Type to search - apps, files, folders, and settings
  3. Navigate - Tab/Shift+Tab or arrow keys
  4. Open - Enter

Path-like queries work too: git/project/readme biases toward path matches.

Query Prefixes#

Prefixes narrow the search scope. Type a single " to browse them all in a menu, then pick one to drop it into the field.

PrefixModeExample
"Browse all prefixes"
a"Apps onlya"term
f"Files onlyf"term
d"Folders onlyd"term
r"Regex search (case-insensitive)r"pattern
rc"Recent files/foldersrc"report
c"Clipboard historyc"term
t"Quick translationt"hello
tw"Dictionary lookuptw"word
>AI conversation (macOS, beta)>add lunch @ 1pm

Each one is detailed under Search Modes, and > has its own AI page.

Apps only#

a

Directories only#

d

Quick Math#

Type an expression and Look pins a Calculator row above the results. Enter copies the value and hides the launcher.

  • 2^101,024
  • 200*15%30
  • sqrt(2)1.4142135624

Dates and resolutions (20-05-2026, 1920x1080) stay ordinary searches. Full grammar under Inline Calculator.

Ask a Question#

With web answers on (the default), a question or an unindexed entity like sir alex ferguson shows an inline answer card. Prefix queries never trigger web lookups. See Web Answers.

Query Aliases#

Map a search term to related apps, e.g. alias_note=Notion|Obsidian|Apple Notes. Syntax under Search Aliases.

Search Modes#

What the main input does beyond app and file search. Prefixes are typed at the start of the query.

Quick Folders#

Type a folder's name to pin it to the top of results (Enter opens it, Cmd+F reveals it) - even when it isn't part of the indexed file roots:

  • Home folders - Desktop, Documents, Downloads, Pictures, Movies, Music.
  • `Applications` - pins the /Applications folder (macOS). The indexer only walks Desktop/Documents/Downloads, so this is how you jump to /Applications; the apps inside it stay searchable as apps (a").
  • `Trash` - pins the Trash; Cmd+D on it empties the Trash (see Move to Trash above).

Open a URL#

Type something that looks like a URL and Look offers to open it in your browser - no prefix needed.

  • A structural URL (with a scheme, port, path, or localhost/IP - e.g. http://localhost:3000 or example.com/docs) shows an Open in browser row at the top of the results.
  • A bare host.tld (e.g. github.com) shows the row after your local results, so it never displaces a real file or app match.
  • URLs you open this way are remembered and resurface as Recently opened rows, ranked by frecency and filtered as you type.

Shared between the macOS and Windows/Linux apps.

Recent Files & Folders (`rc"`)#

Type rc" to browse what you most recently opened and what recently landed on disk (downloads, screenshots), newest first. Add a term to filter: rc"report.

  • Enter opens an entry, Cmd/Ctrl+F reveals it
  • Cmd/Ctrl+D moves the entry's file to trash

Clipboard History (`c"`)#

Access recently copied text items:

  • Type c" to enter clipboard mode
  • Browse recent text clips
  • Press Enter to copy an item back to clipboard
  • Press Delete to remove the selected entry from history

On macOS the history is kept in memory and clears on restart; on Windows/Linux it is saved to disk and persists between launches. File and folder copies (Cmd+C, Cmd+P) are never recorded.

Size is clipboard_history_limit in Configuration.

Clipboard histories search example#

c

Translation (`t"` / `tw"`)#

Quick translation without leaving the launcher:

  • t"hello → Translate "hello" to Vietnamese/English/Japanese
  • tw"word → Dictionary lookup with definitions and examples

Translate sentences, words via web#

t

Search words by MacOS's built-in LookUp#

t

Translation requires network connectivity.

Inline Calculator#

Type an expression in the main input and Look pins a Calculator row above every other result. No prefix, no mode switch.

  • Enter or a click copies the value and hides the launcher.
  • Clipboard history keeps the worked expression (2+2 = 4) so you can find it again later, but pasting still gives you just the value.
  • Shape decides what counts as math, not spacing, so a date, a resolution, or a ratio (20-05-2026, 1920x1080, 16:9) is left alone and stays a normal search.

Grammar: exponent (^), factorial (!), constants pi/e, functions sqrt/abs/round/floor/ceil, % as both percent shorthand and modulo, implicit multiplication (2pi, 3sqrt(9)), and comma-grouped or scientific input (1,500, 1e6).

  • 2^101,024
  • 4!24
  • 200*15%30
  • 10%31
  • 2*pi6.2831853072
  • 1,500 + 11,501

The same shared engine backs the calc command panel. Results are limited only by what a 64-bit float can represent.

Web Answers (optional)#

With web answers enabled (default), Look answers question-like queries inline:

  • Knowledge lookups: a question or a multi-word entity that isn't indexed locally (e.g. sir alex ferguson) shows an answer card sourced from DuckDuckGo/Wikipedia, with clickable source labels.
  • Instant converters: currency (100 usd to eur), weather, and crypto queries match their own narrow grammar and answer immediately.
  • Not arithmetic: math no longer answers in the card. It gets its own pinned Calculator row above the results (see Inline Calculator).
  • Web search suggestions: autocomplete rows appear below local results; Enter opens the suggestion in your browser.
  • Layout: the answer card renders full-width when there are no local results, side-by-side with suggestions, or stacked above local results, depending on what the query returns.
  • On macOS, Look can additionally fall back to the on-device Apple Intelligence model when local and web sources have no answer. Linux/Windows use web sources only.

The > conversation mode, calendar and reminder actions, file recall, and text operations are a separate macOS-only feature set with its own page: see AI.

Privacy notes:

  • Prefix queries (a", f", d", r", c", rc", t", tw", :cmd) never trigger web lookups - they are launcher scopes, not questions.
  • Turn the whole feature off in Settings → Advanced, or set ai_enabled=false in ~/.look/config to run fully offline.

Result Actions#

Actions on the currently selected result.

Action Menu (`Cmd/Ctrl+K`)#

Every action the selected row offers, each listed with its chord. This is the discovery surface: the menu teaches the shortcuts and then gets out of the way.

EntryChordNotes
OpenEnterThe system default action
EditCmd/Ctrl+ENeeds a preferred editor
Open terminal hereCmd/Ctrl+TNeeds a preferred terminal
RevealCmd/Ctrl+FFile manager
Copy pathCmd/Ctrl+CThe path as text

Once a tool resolves, the entry names it: Edit reads Edit in Zed, so the menu tells you what the chord is about to open. An action with no tool declared is still listed and explains what to set when you press it, rather than silently doing nothing.

Cmd+J / Cmd+K or the arrows move, Enter runs, Esc closes.

A row from a declared source whose block names then targets shows those instead - the block author already chose that row's vocabulary. The chords above keep working on it either way.

Edit (`Cmd/Ctrl+E`)#

Open the selected file or folder in your own editor.

  • On a file row, text_editor; on a folder row, code_editor. Declare only one and it covers both.
  • A terminal editor (nvim, helix, micro, …) is run inside your declared terminal, at the right path.
  • Apps are not eligible - see Preferred Tools for why, and for the keys themselves.

Open Terminal Here (`Cmd/Ctrl+T`)#

Open your declared terminal at the selected row's directory: the folder itself for a folder, the parent for a file. The new window starts in an interactive login shell, so closing it closes the window once.

Copy File or Folder (`Cmd/Ctrl+C`)#

With a file or folder selected, press Cmd+C (macOS) or Ctrl+C (Windows/Linux) to copy it to the clipboard.

  • Paste into a file manager, Mail, Slack, or any app that accepts files → pastes the actual file/folder
  • Paste into a text editor or terminal → pastes the path as a string
  • Works on results of kind file and folder; apps use Enter or Cmd/Ctrl+F instead

Multi-Pick Files/Folders (`Cmd/Ctrl+P`)#

Build up a set of files/folders, then paste or open them anywhere in one go.

  • Cmd+P on a focused file or folder toggles it in or out of the picked set; every toggle rewrites the system pasteboard with all picked items.
  • The right panel switches to a Picked (N) list while the set is non-empty: each row has an X to remove a single item, plus a Clear all button.
  • Shift+Enter (or the Open all button) opens every picked item at once.
  • Cmd+Shift+P clears the entire picked set and the pasteboard.
  • Paste behavior matches Cmd+C - into Finder/Mail/etc. you get the actual files; into a text field you get the paths.

Move to Trash (`Cmd/Ctrl+D`)#

Delete files without leaving the launcher:

  • Cmd+D moves the selected file/folder (or the whole picked set, if any) to the system trash and refreshes the index.
  • With the Trash quick-folder selected, Cmd+D offers to empty the trash instead (with a confirmation showing the item count).

Hide an App (`Cmd/Ctrl+Shift+H`)#

With an app result selected, press Cmd+Shift+H (macOS) or Ctrl+Shift+H (Windows/Linux) to hide it from Look so it stops appearing in results - handy for apps you never launch from the launcher.

Run as Administrator (`Ctrl+Shift+Enter`, Windows)#

On Windows, press Ctrl+Shift+Enter on a selected app to launch it elevated; Windows shows the standard UAC prompt. The preview panel shows the shortcut on apps that support it.

Home Screen#

What fills the launcher before you type anything.

Running Apps Switcher#

Available on macOS, Linux, and Windows. Modifier is Cmd on macOS and Alt on Linux/Windows.

When enabled, running-app icons fill the right half of the search bar (the search field takes the left half), right-aligned and growing leftward as more apps open. Each icon has a corner number badge; press Cmd/Alt+the badge digit on the home screen to activate that app. The launcher window stays the same size whether the row is shown or hidden.

  • Stable order - icons sit in alphabetical order and don't shuffle when you switch apps. The badge digit for "Discord" stays the same until you launch or quit something.
  • Ergonomic badge keys - keys are assigned from 1, 2, 3, 9, 8, 4, 7, 6, 5 in that order, then sorted ascending for display, so the awkward middle keys only show up once you have many apps open. With 5 running apps the badges are 1, 2, 3, 8, 9.
  • Windowless apps (macOS only - Finder with no Finder windows, App Store, etc.) get a fresh window via a Dock-style "reopen" instead of an empty flash. Hidden apps (Cmd+H) are unhidden first. On Linux/Windows the switcher only lists apps that currently own a visible window, so this case doesn't arise.
  • Linux compositor support - focus dispatches via X11 _NET_ACTIVE_WINDOW (GNOME/KDE/i3), i3-msg (i3), swaymsg + wlr-foreign-toplevel (sway/wlroots), hyprctl (Hyprland), niri's own IPC socket (which also scrolls the view to the window's workspace), a KWin script on KDE, and a bundled GNOME Shell extension on GNOME Wayland.
  • Show/hide via Settings → Appearance → Running Apps (on/off toggle).
  • In command mode, the digit shortcuts switch command panels instead (see Command Mode); the running-apps switcher only fires on the home screen. Suspended modes (translate, command) also ignore the digit keys so the hidden strip can't fire from a stale cache.

Persisted as running_apps_placement in ~/.look/config - see Configuration.

Super Actions#

On the empty home screen (no query typed), Look shows a strip of system toggles, one-shot actions, and read-only info tiles - a fast way to flip Bluetooth or Wi-Fi, switch theme, or check the battery without opening system settings.

sa
  • Tiles come from a shared catalog, so macOS, Windows, and Linux render the same strip; only the native control paths differ. On Linux the strip works across GNOME, KDE, and tiling WMs including i3.
  • Tiles: an L slot (active Pomodoro session > remaining todos > clock), Bluetooth, Wi-Fi, Battery, Theme, Keep Awake, Screensaver, Weather, Mic, Restart, Shut Down, and Now Playing.
  • Activate a tile by clicking it, or press the platform modifier plus its highlighted letter - Cmd on macOS, Alt on Windows/Linux (e.g. Cmd/Alt+B for Bluetooth, P for Now Playing play/pause).
  • Restart and Shut Down arm on the first press and fire on the second; Esc or a timeout cancels.
  • Battery, Weather, and the L slot are read-only. Battery shows a charging icon while the machine is plugged in, and falls back to system uptime on a desktop with no battery.
  • Toggle the whole strip via Settings → Appearance → Super Actions. Persisted as super_actions_enabled in ~/.look/config.

Command Mode#

Two ways in:

  • Cmd/Ctrl+/ enters command mode and resumes the last command panel you visited (defaults to calc on first run); use Tab or Cmd+1..Cmd+7 to switch.
  • From the home screen, type : followed by a known command id:
    • :calc 2+2 - the space after the command id is the live trigger; you switch with 2+2 already typed and can keep typing without pressing Enter.
    • :calc then Enter - switch with empty input.
    • The : shortcut only triggers when the word right after it is an exact known command id (calc, pomo, todo, speed, kill, shell, sys); anything else (:foo, :Users/me/...) stays in normal search.
    • :kill chrome and :shell ... switch into command mode but never auto-execute - the existing kill confirmation and shell input gate still apply.

Built-in quick commands:

CommandDescription
calcCalculator
pomoPomodoro focus timer
todoDaily tasks & progress
speedInternet speed test
killForce quit app or port owner
shellExecute shell commands
sysSystem information

Jump keys are in Keyboard Shortcuts.

calc#

The full grammar from Inline Calculator, in a dedicated panel.

Inside /calc the aliases x, : and a leading v are honored wherever they land, as multiply, divide, and sqrt:

  • 1920x10802,073,600
  • 16:91.7777777778
  • v 164 (the v alias needs a separator or parentheses: v(16) also works)

Those same strings stay ordinary searches in the main input, where shape gating leaves resolutions and ratios alone.

pomo#

A pomodoro focus timer that lives inside command mode.

  • Editable session list - plan a sequence of focus + break blocks, each with its own duration and name (e.g. Deep Work 30m → Short Break 5m → Review 30m → Long Break 15m). The timer auto-advances through the list and loops the music folder while a session runs.
  • Three timer styles (switchable via the gear icon): Modern Ring, Vintage Dial, Minimal Text.
  • Background music: pick any folder of audio files (mp3, m4a, wav, aac, flac, ogg, aiff, alac). Tracks are streamed one at a time (no full-folder load), shuffled per launch, and looped at the end of the list.
  • Standby fade - after 5s of no input the panel collapses to clock-only (the sidebar hides too); any key/mouse input restores it.
  • "Ending soon" alert - at 10s remaining, a chime + a popover from the menu-bar timer (and a system notification, if granted) fires once per session.
  • Menu-bar mini-timer - visible whenever a session is active, even when the launcher window is hidden. Click it to jump straight back into /pomo.
  • Keyboard: Space start/pause • R reset • P toggle music play/pause.
  • Persistence: the session list, selected timer style, and music folder path are saved to ~/.look/config and survive restarts.

todo#

A daily task tracker (:todo or Cmd/Ctrl+3).

  • Day-grouped tasks - tasks live under their date; overdue days get a badge, and a done-today stat sits in the footer.
  • Stats page - streak counter, 30-day trend chart, and a year heatmap of completed tasks.
  • Keyboard: Ctrl+N adds a task, Ctrl+S saves, Enter/Escape confirm or cancel an edit. Double-click a task to edit it.
  • Home-screen quick view - when today has tasks, the hint bar shows a clickable Todo done/total stat with an "Unfinished today" hover bubble.
  • Shared storage - tasks persist in the local look.db and are shared between the macOS and Windows/Linux apps.

speed#

Measures the connection on a live dial: download and upload orbit as counter-rotating comets on a log scale (1 Mbps to 1 Gbps), and latency sits at the centre, pulsing once per round trip.

  • The test starts when the panel opens, unless the last reading is under a minute old. R runs a fresh one. A run takes about 15 seconds and saturates the link while it does, so expect other downloads to slow briefly.
  • Under the numbers sits a plain-language read of the result, e.g. FAST BROADBAND / LATENCY EXCELLENT.
  • LAN is this machine's address, WAN is what the far end sees. WAN is masked until you press E. Clicking either address copies it, and WAN copies in full even while masked.
  • The footer names your ISP, rough location, and which server answered. via Cloudflare is the primary; a fallback mirror reads conservatively low.
  • Latency is one TCP handshake against an already-resolved address, so it sits a little above what ping reports.

shell#

Run a shell command from the launcher. Input containing sudo shows an orange warning cue.

kill#

Force-kill a running app or process with explicit confirmation. Supports port-based targeting:

  • kill :3000 - kills whatever owns port 3000
  • kill port 3000 - same, verbose form
  • Use Up/Down to navigate process results, Y/N to confirm or cancel

sys#

Displays system information at a glance.

Declared Sources#

Look indexes apps, files, and System Settings out of the box. Sources are how you add your own rows: your repos, your SSH hosts, your morning routine, your deploy script.

You declare them in a small TOML file. They show up in the same list as everything else, rank by how often you use them, and act like every other row.

Needs Look v0.6.12 or newer. Earlier builds do not read ~/.look/sources/.

Want something working straight away? lookbook is a collection of ready-made sources for git, tmux, ssh, docker and more. Copy one in, reload, done.

Quick start#

  1. Make the directory:
bash
mkdir -p ~/.look/sources
  1. Put a file in it. Any name ending in .toml, and as many files as you like:
toml
# ~/.look/sources/mine.toml

[projects]
name = "Projects"
dir  = "~/dev"
only = "dirs"

[work]
name = "Work setup"
do = [
  "open -a Slack",
  "open -a Safari https://github.com",
]
  1. Reload: Cmd+Shift+; (macOS) or Ctrl+Shift+; (Linux, Windows).

Type projects and your repos are there. Type work setup and one Enter opens both apps.

Look reads every .toml in the directory and merges them, so you can split by topic (work.toml, git.toml) and delete one when you are done with it. Block ids must be unique across all of them.

The four kinds of block#

Every [header] in a file is one block, and every block needs exactly one producer key. That key is what says what the block is.

ProducerWhat it makesUse it for
doone row, and Enter performs its stepsroutines, bundles, a command you run often
dirone row per child of a directoryprojects, notes, screenshots
fileone row per line of a text filea list you maintain by hand
runone row per line a command printsanything that changes: branches, containers

do#

toml
[work]
name = "Work setup"
icon = "🚀"
do = [
  "open -a Slack",
  "open -a Ghostty",
]

One row. Enter runs every step in order, and a step that fails does not stop the rest.

dir#

toml
[projects]
name  = "Projects"
dir   = "~/dev"          # or: dirs = ["~/dev", "~/work"]
depth = 1                # 1 = immediate children
only  = "dirs"           # dirs | files | all

The rows are real files and folders, so preview, reveal, copy and the file shortcuts all keep working on them. Hidden entries are always skipped. match and exclude take globs, tested against the entry name.

file#

toml
[hosts]
name = "SSH hosts"
file = "~/.look/hosts.txt"
open = "ssh {id}"

One row per line. See Row formats.

run#

toml
[branches]
name = "Git branches"
run  = "git -C ~/dev/look branch --format='%(refname:short)'"
open = "git -C ~/dev/look switch {id}"

The command runs on reload, not on every keystroke, and its rows are cached until the next reload. Search stays instant no matter how slow the command is.

If it fails, times out, or prints nothing, the rows from last time are kept. Losing them would also lose the ranking those rows had earned.

A script with no TOML at all#

Drop an executable straight into ~/.look/sources/ and Look treats it as a run block whose id and name are the file name. The fastest way to try an idea. On Windows the extension decides: .exe, .cmd, .bat, .com and .ps1.

Key reference#

Every block can carry these:

KeyTypeDefaultWhat it does
namestringthe block idWhat you type to find the rows
aliaseslistnoneExtra words that also find them
biasinteger0Score offset. Negative sits below apps and files
iconstringnoneEmoji, SF Symbol name, or an image path
enabledbooltruefalse keeps the file, stops loading the block
previewstringnoneCommand run for the selected row; output fills the right panel
confirmstringnoneYes/no question asked before the block acts
thenlistnoneOther blocks a picked row can reach
open edit terminal revealstringnoneSee What Enter does

Producer-specific:

KeyBelongs toNotes
dir / dirsdirOne root, or several. They combine
depthdirDefault 1
onlydirdirs, files or all
match / excludedirGlobs against the entry name
cwdrunWorking directory. Default: the filesystem root
timeoutrun30s, 5m, 1h. Default 5s, capped at 30s
formatfile, runlines or json

A leading ~ in any path key is your home directory.

Placeholders#

Every command a block declares expands against the selected row:

PlaceholderExpands to
{id}The row's id
{title}What the row displays
{path}Its filesystem path, when it has one
{dir}The row itself when it is a folder, its parent when it is a file
{query}What you had typed when you picked it
{parent.id} {parent.title} {parent.path}The same, for the row above. Repeat parent. to go further out

Two rules worth internalising:

  • Never quote a placeholder yourself. Every value is shell-escaped on substitution, so open {path} handles a folder called My Project and a row titled ; rm -rf ~ is inert. Writing open "{path}" gives you a doubly quoted path that resolves to nothing.
  • A block whose producer mentions a placeholder is not a top-level row. do = ["make -C {path} deploy"] only means something against a selected project, so Look keeps it out of the main list and reaches it only through another block's then.

Steps also see LOOK_ID, LOOK_TITLE and LOOK_PATH in their environment, for a script that would rather read a variable than take an argument.

Actions on a row#

What Enter does#

Four verbs have one shortcut each across the whole app:

VerbKeyMeaning
openEnterThe main action
editCmd/Ctrl+EOpen in your editor
terminalCmd/Ctrl+TOpen a terminal there
revealCmd/Ctrl+FShow in Finder / Explorer / Files

Declare only what differs from your global preferred tools. The rule for Enter: the block's open if it declares one, otherwise the row's path is opened the way any file in Look is opened. That is why most dir blocks declare no verbs at all.

A do block cannot declare verbs. It already is the action.

Drill-downs and actions#

then lists other blocks a picked row can reach. Press Cmd/Ctrl+K on a row to open the action menu, Cmd+J / Cmd+K or the arrows to move, Enter to run, Esc to close.

The target's own producer decides what happens:

  • a target that performs steps (do) is an action on the selected row;
  • a target that produces rows is a drill-down: you descend into its rows, and Esc comes back.
toml
[projects]
dir  = "~/dev"
only = "dirs"
then = ["branches"]

[branches]
name = "Branches"
run  = "git -C {path} branch --format='%(refname:short)'"
open = "git -C {parent.path} switch {id}"

Look at [branches] twice, because this is the one thing that trips people up. run is the producer: it is asked for rows while the project is still the selected row, so the project is {path}. open acts on a branch row that run produced, whose parent is the project, so there the project is {parent.path}.

Levels stack five deep. A then target may live in another file.

Asking before acting#

toml
[drop-branch]
name    = "Delete local branch"
confirm = "Delete local branch {id}?"
do      = ["git -C ~/dev/look branch -d {id}"]

The question is expanded against the row, so it names what is about to happen. Anything destructive should have one. A launcher makes Enter on the wrong row very cheap, and this is the one line that makes it expensive again.

Row formats#

`lines` (the default) is one row per line, tab separated: id, then title, then subtitle. A bare line with no tabs is a row whose id and title are the same text. The id is what actions receive and what usage is recorded against, so a row can show one thing and act on another.

`json` carries the two fields tabs cannot: path, which makes a row a real filesystem object, and a per-row icon.

json
[{"id": "look", "title": "Look", "subtitle": "3 uncommitted", "path": "~/dev/look"}]
FieldRequiredNotes
idyesWhat actions receive
titlenoDefaults to the id
subtitlenoDefaults to the block name
pathnoMakes the row a filesystem object
iconnoEmoji, SF Symbol name, or image path. Beats the block's icon

One top-level array, one object per line, or pretty-printed objects run together: whichever your tool already prints.

Your shell#

Every command a block declares is shell text, run by your login shell, so &&, |, > and your PATH all work. That matters more than it sounds: a launcher is started by the window server, not a terminal, so without the login shell it would inherit an environment with no Homebrew, no nvm and no $EDITOR.

A login, non-interactive shell reads ~/.zshenv, ~/.zprofile and ~/.zlogin, but not ~/.zshrc, and for bash the profile chain but not ~/.bashrc unless your profile sources it. If a PATH entry or a shell function lives in your rc file and a block cannot find it, that is why. Move the export to ~/.zprofile, or name the binary by full path.

If your shell is fish or nushell, commands fall back to /bin/sh, because those shells accept the flags and then reject the script. Write POSIX shell, or call fish -c '...' explicitly.

Refresh and limits#

Reload with Cmd+Shift+; (macOS) or Ctrl+Shift+; (Linux, Windows). It re-reads every file, re-runs every enabled run block, and re-indexes. Editing a block and reloading is the whole development loop.

Removing a block, or a row, removes its record and its ranking history at the next reload. Renaming a block id therefore counts as a delete plus an add.

LimitValue
Rows per block2,000
Default command timeout5s, up to 30s
Whole reload spent running commands60s
Drill-down depth5 levels

When something does not work#

  • The block does not appear. Check it declares exactly one of do, dir, file, run. Zero or two is an error. Check its producer does not mention a placeholder, which makes it a then target by design.
  • A `run` block shows nothing or stale rows. Run the command in a terminal first. A failing command keeps the previous rows on purpose.
  • A command works in your terminal but not in Look. Usually the login shell not reading your rc file, an alias rather than a function, or a placeholder you quoted yourself.

Problems are printed to stderr, one line each, prefixed look sources:. Launch Look from a terminal to read them.

Going further#

  • lookbook collects ready-made sources, one folder per tool, each with its own README.
  • The full format reference in the repo covers every key, every limit, and a longer troubleshooting list.
  • core/sources/example.toml is the whole format in one annotated file, kept honest by a test.

AI#

macOS only, and still beta. Look's conversational mode runs on a model you choose and point at yourself. Everything here is separate from the cross-platform answer card and web suggestions, which need no model and are documented under Web Answers.

Linux and Windows have no on-device model and no > session yet. The ai_enabled key is shared across platforms, so on those two it gates web answers only.

Setup#

Pick a provider in Settings → Advanced → AI:

ProviderWhat it does
Apple Intelligence (on-device)Answers questions. Too small to plan actions, so calendar and reminder phrasings won't work through it
Ollama (local)The full feature set. Needs a pulled model

Ollama defaults to http://localhost:11434 with model qwen3.5:4b. Both are editable in the same panel, or in ~/.look/config:

KeyDefaultMeaning
ai_enabledtrueMaster switch. false turns off the AI mode, the answer card, and web suggestions
ollama_hosthttp://localhost:11434Where inference runs. A non-loopback address sends prompts over the network
ollama_modelqwen3.5:4bModel tag to use
ai_allow_remote_contextfalseWhether your calendar, clipboard, and remembered facts may be attached to prompts when inference is not on this machine

Calendar, Reminders, and Contacts access is granted from the Permissions row in the same panel. Look reads those through the OS, never over a network.

The `>` Session#

Type > to turn the panel into a conversation. Actions, questions, and streamed answers stack together in one thread.

ShortcutAction
EscapeLeave the session
Cmd+ZUndo the last action
Cmd+.Stop the current generation without ending the session
Shift+EnterNew line instead of sending. The box grows to six lines and stops
Option+Up / Option+DownWalk your recent prompts, like a shell history
Shift+Up / Shift+DownSelect text in the message instead
Cmd+1..Cmd+9, Cmd+0Open the conversation carrying that chip (Cmd+0 is the tenth)
Cmd+D / Cmd+DeleteDelete the highlighted conversation. Undo from the banner with Cmd+Z
Cmd+HOpen the help screen on its AI topic without leaving the conversation

Conversations persist, and they are listed, searchable, and resumable. The chip list stops at ten because a Cmd chord is a single keypress; older conversations are found by typing, then Tab/arrows and Enter.

The running-apps row is hidden on the AI screen, which is what frees the digits for conversations.

Calendar and Reminders#

Add, move, cancel, complete, remove, snooze, and block focus time in plain language:

  • >move my dentist to friday
  • >remind me to renew the domain next tuesday
  • >block two hours for deep work tomorrow morning

Every change previews first and commits on Enter, then Cmd+Z undoes it. Nothing is written to your calendar without that confirmation. Adding an event that already sits on that day says so rather than quietly duplicating it. Multi-step requests become an ordered plan that runs in sequence.

`@` for exact times#

>add lunch @ 1pm skips the model entirely. It is instant, deterministic, and works with no capable model configured at all, which makes it the reliable path when you already know the time.

Join a Meeting#

join, join meeting, join my next meeting, or join <name>.

Pins the next Teams, Zoom, Google Meet, Webex, Jitsi, GoToMeeting, or Whereby meeting on your calendar; Enter opens the link. Works in > and in the main bar.

  • Name one to skip past a sooner meeting: join standup, join design review
  • A name matching nothing shows no row, which is what keeps join two pdfs an ordinary file search
  • Looks two days ahead, so a meeting tomorrow reads "tomorrow 14:30" rather than counting minutes
  • A meeting already under way beats one starting sooner
  • Deterministic and model-free: the invite already carries its join link, so Look reads it out of the event rather than calling any API

Online accounts work through macOS Calendar (System Settings → Internet Accounts).

Call and Message#

call mom, facetime sarah, message alex, call mom on iphone.

Matches the name against Contacts and opens FaceTime or Messages by URL scheme, with no API and no network. Look always lists what it found before anything rings, so a wrong pick never calls the wrong person: the row you read is the confirmation. A bare call means FaceTime audio, the one that works with no iPhone nearby.

Works in > and in the main bar, where each way to reach someone is its own row.

File Recall#

Ask for files by description instead of name: pdfs from last week, files added to desktop. Look searches your index by type, time, and place.

Results say when they were interpreted, or when the search had to be relaxed to find near-misses. The model produces a structured query, never a rewritten query string, and never overrides results already on screen.

Text Operations#

summarize, translate to german, make this shorter transform whatever you copied. To work on a file instead:

  • Pick it first with Cmd+P, or
  • @-mention it while typing, which opens a two-column picker with previews

Text files, source code, and PDFs are supported. An oversized file reports how much of it was read rather than quietly summarizing only the first part. A PDF that is a scan, is password-protected, or decodes to junk is refused by name, because summarizing garbage would read exactly like a real answer.

Remembered Facts#

remember I prefer metric stores a durable fact the assistant sees on every turn. Only you can write these; the model never can.

No Prefix Needed#

Typing an instruction in the main bar works too, without >. The plan appears as the first result row and one Enter runs it.

Clipboard History#

Clipboard history lives in the database, so it is searchable and available to the AI as context. Browse it with the c" prefix; Cmd+D or Delete removes the selected entry.

Privacy#

Prompts go to whichever provider you select. Apple Intelligence is on-device and Ollama defaults to localhost, so by default no prompt leaves your machine.

Two things change that:

  • Setting ollama_host to a non-loopback address
  • Selecting a cloud-routed Ollama model (a -cloud tag, which the local daemon proxies to Ollama's service)

Your calendar, clipboard, and remembered facts are held to a stricter rule than the prompt itself. They are attached only when inference is on this machine. For anything remote they are withheld until you turn on ai_allow_remote_context.

Set ai_enabled = false to turn all of it off, including the answer card and web suggestions. Local search and indexing never make network calls either way.

Keyboard Shortcuts#

On Windows/Linux, read Cmd as Ctrl throughout, except the launcher toggle.

Global#

ActionmacOSWindows / Linux
Toggle launcherCmd+SpaceAlt+Space
Open/close settingsCmd+Shift+,Ctrl+Shift+,
Reload configurationCmd+Shift+;Ctrl+Shift+;
Quit LookCmd+Option+QAlt+Shift+Q

Navigation#

ShortcutAction
Tab / Shift+TabNext / previous result
/ Move selection
EnterOpen selected result
EscapeGo back / close (context dependent)
Cmd+HToggle help/shortcuts screen
Cmd+QHide launcher (macOS)

On the Selected Result#

ShortcutAction
Cmd+KOpen the action menu for the row
Cmd+EEdit: text_editor on a file, code_editor on a folder
Cmd+TOpen a terminal at the row's directory
Cmd+FReveal in file manager
Cmd+CCopy file/folder
Cmd+PToggle pick (multi-select)
Cmd+Shift+PClear all picked items
Shift+EnterOpen all picked items
Cmd+DMove to trash; empties the Trash on the Trash quick-folder
Cmd+Shift+HHide the app from Look
Ctrl+Shift+EnterRun as administrator (Windows)
DeleteRemove the entry, in c" clipboard mode

See Result Actions for what each one does, and Preferred Tools for the editor, terminal and file manager Cmd+E / Cmd+T / Cmd+F use.

Entering Modes#

ShortcutAction
Cmd+EnterWeb search the current query
Cmd+/Command mode (resumes the last panel; calc on first run)
:cmdJump straight to a command, e.g. :calc 2+2, :todo, :kill chrome
"Browse query prefixes
>AI conversation (macOS)

Command Mode#

Cmd+1..Cmd+7 switch panels only while command mode is open. On the home screen those keys drive the running-apps switcher instead.

ShortcutPanel
Cmd+1calc
Cmd+2pomo
Cmd+3todo
Cmd+4speed
Cmd+5kill
Cmd+6shell
Cmd+7sys

Within a panel:

ShortcutAction
Y / NConfirm / cancel a kill prompt
Space / R / PIn pomo: start-pause • reset • music play-pause
Ctrl+N / Ctrl+SIn todo: new task • save
R / EIn speed: run again • reveal the public address

Running Apps Switcher#

On the home screen, the platform modifier plus an icon's badge digit activates that app: Cmd+1..Cmd+9 on macOS, Alt+1..Alt+9 on Linux/Windows. Badges are assigned ergonomically rather than sequentially - see Running Apps Switcher.

AI Mode (`>`, macOS)#

The > session rebinds several keys, including the digits, which open conversations there instead of running apps. Full table on the AI page.

Settings Panel Zoom#

ShortcutAction
Cmd+- / Cmd+=Zoom out / in (temporary)
Cmd+0Reset zoom

Settings Panel#

Settings Panel#

Open with Cmd/Ctrl+Shift+,. Contains three tabs:

Appearance#

  • Theme: 8 built-in presets (Catppuccin, Tokyo Night, Rose Pine, Gruvbox, Dracula, Kanagawa, Kindle, Liquid) plus Custom. Kindle is the one light preset: warm paper, near-black ink. Liquid renders on macOS 26's Liquid Glass, and ships as clear glass elsewhere: near-transparent fills, wider corners, a bright rim along the top edge.
  • Tint Color, Blur, Font, Font Color, Border - colors and type. Behind-window blur is the compositor's to grant: Look asks for it on KDE, Hyprland 0.56+ and Niri, and Blur Opacity thins the tint wherever there is frost - real blur, or a background image - to let more of it through.
  • Inner Gap - see Floating Layout
  • Running Apps and Super Actions - show or hide the two Home Screen strips

Advanced#

  • Background image (path, layout mode, opacity, blur) - keys in Configuration
  • Indexing settings (File Scan Depth 1-12, File Scan Limit 500-50000)
  • AI / Web answers on/off, provider choice, Ollama host and model, and Calendar/Reminders/Contacts permissions - see AI
  • Backend log level
  • Launch at login
  • Config reset: Create Fresh Config button with confirmation popup

Shortcuts#

  • In-app keyboard shortcut documentation
  • Toggle help screen with Cmd/Ctrl+H

Floating Layout (Inner Gap)#

Split the launcher into floating tiles, tiling-WM style, with the Inner Gap slider in Settings → Appearance (0-24 px, default 0):

  • 0 keeps the classic single framed panel.
  • Above 0, the search bar, results list, and preview panel become separate frosted tiles separated by transparent gaps, floating directly on the desktop.
  • Each tile keeps the theme border, so the Border thickness/color settings apply per tile.
  • With an empty query, only the search bar shows (resting state) - the columns appear as you type.
  • A background image continues seamlessly across the tiles, as if the gaps were cut out of one picture.

Persisted as inner_gap in ~/.look/config and shared between the macOS and Windows/Linux apps.

On environments that can't composite the floating look faithfully (bare X11 WMs without a compositor, VMs with software rendering, blur-disabled stacks), Look keeps the classic framed panel with both columns visible and disables the Inner Gap slider. The saved value is untouched and applies again on a capable setup.

Lazy Indexing#

On by default. Look reindexes only when file or app changes are detected, when you reload with Cmd/Ctrl+Shift+;, or on restart. Turn lazy_indexing_enabled off to reindex on every launch: fresher, slower.

Configuration#

Look uses a configuration file at ~/.look/config. Changes take effect immediately after saving, or you can press Cmd/Ctrl+Shift+; to reload.

That file holds settings. To add your own rows to Look, from a folder, a list, or a command, see Declared Sources.

Configuration File Location#

  • Default: ~/.look/config
  • Custom: Set LOOK_CONFIG_PATH environment variable
  • Reload: Cmd/Ctrl+Shift+;
  • Reset: Settings → Advanced → "Create Fresh Config"

Format#

  • One key=value per line
  • # starts a comment
  • Unknown keys ignored
  • Invalid values fall back to defaults

Backend Settings#

App Scanning#

ini
app_scan_roots=/Applications,/System/Applications,/System/Applications/Utilities,/System/Library/CoreServices/Applications
app_scan_depth=3
app_exclude_paths=
app_exclude_names=

File Scanning#

ini
file_scan_roots=Desktop,Documents,Downloads,Pictures,Videos
file_scan_extra_roots=
file_scan_depth=4
file_scan_limit=8000
file_exclude_paths=

Use file_scan_extra_roots to add user-specific directories on top of the defaults (overlap and risky-root validation is enforced).

Other Backend Options#

ini
lazy_indexing_enabled=true
skip_dir_names=node_modules,target,build,dist,.git,vendor,out,coverage,tmp,cache,venv
backend_log_level=info
launch_at_login=false

Backend Keys Reference#

KeyDescriptionDefault
app_scan_rootsDirectories to scan for apps(see above)
app_scan_depthMax depth for app scanning3
file_scan_rootsDirectories to scan for filesDesktop,Documents,Downloads,Pictures,Videos
file_scan_extra_rootsExtra user-specific directories to index(empty)
file_scan_depthMax depth for file scanning (1-12)4
file_scan_limitMax files to index (500-50000)8000
lazy_indexing_enabledEnable lazy indexingtrue
skip_dir_namesDirectories to skip(see above)
backend_log_levelLog verbosityinfo
launch_at_loginStart at loginfalse

Preferred Tools#

Name the editor, terminal, and file manager Look should hand a row to. Four optional keys:

ini
text_editor=nvim
code_editor=zed
terminal=ghostty
file_manager=nautilus
KeyUsed forExample values
text_editorEditing one file (Cmd/Ctrl+E on a file row)nvim, hx, micro, vim, zed
code_editorOpening a project folder (Cmd/Ctrl+E on a folder row)zed, code, cursor, xcode
terminalCmd/Ctrl+T, and the host for any terminal editorghostty, iterm, kitty, wezterm, gnome-terminal
file_managerThe Cmd/Ctrl+F reveal targetnautilus, dolphin, thunar, finder

Declare nothing and nothing changes. An undeclared key means the system default, which is what Look did before these keys existed. They are config-file only - there is no Settings control - so edit ~/.look/config and reload with Cmd/Ctrl+Shift+;.

See Result Actions for what the actions do and where the menu is.

Name the tool, not a command#

A value is a tool name, never a command with its own arguments. Look already knows how to drive each one, including running a terminal editor inside your terminal, which is the whole reason you name a tool instead of writing a command. text_editor=nvim -u NONE is not a name and will not work.

Case, a trailing .app, and a leading directory are all forgiven: Zed, Zed.app and /opt/homebrew/bin/zed all mean zed. Spelling out a full path pins that exact build instead of whatever PATH finds first.

Which key an action uses#

  • Edit takes text_editor for a file row and code_editor for a folder row - a file is a thing to edit, a folder is a project to open. Declaring only one of the two covers both.
  • Open terminal here on a folder opens that folder; on a file it opens the file's parent, because "here" never means the file.
  • An app row gets neither. Both actions are about a place you work in, and the folder holding an app is /Applications. Reveal still works on an app.
  • A source block that declares its own edit / terminal / reveal beats these keys, for that block's rows only.
  • file_manager opens the containing folder. Leave it undeclared if you want the file itself selected on arrival: only the platform's own manager can do that.

Terminal editors#

Naming a terminal editor (nvim, helix, kakoune, micro, nano, …) as text_editor needs terminal declared too. Look then opens the terminal and runs the editor inside it, at the right path - so terminal=ghostty plus text_editor=nvim gives you all three of edit-a-file, edit-a-folder, and terminal-here from two words of config.

A value that cannot work says so instead of doing nothing:

What you setWhat Look tells you
A terminal editor, no terminalnvim runs in a terminal; set terminal in your Look config
A terminal as text_editorghostty is a terminal; set text_editor to the editor it should run
terminal=warp or terminal=hyperwarp cannot be told to run a command
Nothing at allSet text_editor in your Look config

Warp and Hyper are named because neither offers a way to run a command in a new window. Every other terminal is either known or driven with the -e convention, and one nobody has listed simply works if it honors -e.

Commands run through your login shell, so PATH, Homebrew, nvm and asdf shims resolve the way they do in a real terminal - a launcher started by the window server would otherwise see none of them. Paths are shell-quoted on substitution, so a folder called My Project stays one argument.

Web Answers#

ini
ai_enabled=true

Gates all network answer features: the answer card (Wikipedia, DuckDuckGo), currency/weather/crypto converters, and web search suggestions. Set to false to run fully offline. On macOS the same key also gates the on-device Apple Intelligence fallback; there is no on-device model on Linux/Windows, but the key keeps the same name so both apps share config storage.

AI Mode (macOS)#

ini
ollama_host=http://localhost:11434
ollama_model=qwen3.5:4b
ai_allow_remote_context=false

Provider settings for the > conversation mode. ai_enabled above is the master switch for these too.

KeyDescriptionDefault
ollama_hostWhere inference runs. A non-loopback address sends prompts over the networkhttp://localhost:11434
ollama_modelModel tag to useqwen3.5:4b
ai_allow_remote_contextWhether calendar, clipboard, and remembered facts may be attached to prompts when inference is not on this machinefalse

Ignored on Linux and Windows, which have no on-device model. Full behavior on the AI page.

UI Theme Settings#

Theme Preset#

ini
ui_theme=catppuccin
Theme

Available: catppuccin, tokyoNight, rosePine, gruvbox, dracula, kanagawa, kindle, liquid, custom

On Windows and Linux, ui_surface records how surfaces are drawn rather than what colour they are - empty for the classic panel, liquid for glass. It is stored separately from ui_theme because tweaking any slider rewrites that key to custom, and a customised Liquid keeps its glass.

Appearance#

ini
ui_tint_red=0.08
ui_tint_green=0.10
ui_tint_blue=0.12
ui_tint_opacity=0.55
ui_blur_material=hudWindow
ui_blur_opacity=0.95
ui_font_name=SF Pro Text
ui_font_size=14
ui_font_red=0.96
ui_font_green=0.96
ui_font_blue=0.98
ui_font_opacity=0.96
ui_border_thickness=1.0
ui_border_red=1.0
ui_border_green=1.0
ui_border_blue=1.0
ui_border_opacity=0.12

Floating Layout#

ini
inner_gap=0

Home-screen inner gap in px (0-24). 0 keeps the classic framed panel; above 0 the home screen splits into floating tiles separated by this gap, each with its own theme border. Shared between the macOS and Windows/Linux apps.

Background Image#

ini
ui_background_image=~/look_bg.png
ui_background_image_mode=fill
ui_background_image_opacity=0.5
ui_background_image_blur=10
KeyOptions
ui_background_image_modefill, fit, tile, stretch

Settings Panel#

ini
settings_blur_multiplier=0.8

Running Apps Switcher#

ini
running_apps_placement=right
KeyOptionsDefault
running_apps_placementnone (off), right (on)right

When none, the running-apps row in the search bar is hidden and the Cmd/Alt+1..9 switching shortcut is disabled; any other value shows it. Legacy top/bottom values from older releases still load as "on" and normalize to right on next save. The key is auto-appended to existing ~/.look/config files on first Save Config, so upgrading from an older Look install doesn't reset other settings. See Home Screen → Running Apps Switcher for the badge-key behavior.

Platform Workarounds (Linux)#

ini
arch_disable_gpu=false
arch_disable_blur=false

Workarounds for WebKitGTK ghost rendering seen on Arch and similar stacks. arch_disable_gpu=true disables webview hardware acceleration (requires restart); arch_disable_blur=true drops the backdrop blur and forces an opaque tint. Both default off - flip them only if you see slider trails or overlapping popovers.

File-Only Settings (No Settings UI)#

These keys have no control in the Settings screens - edit ~/.look/config directly, then reload with Cmd/Ctrl+Shift+;, or restart Look. Out-of-range or unparseable values fall back to the listed default. More keys will be added here over time.

ini
clipboard_history_limit=10
KeyDescriptionDefault
clipboard_history_limitClipboard history size for c" mode (range 10-100)10

Ignored File Patterns#

Exclude noisy files from the index with gitignore-style path globs:

ini
# ignored_patterns_<group>=Pattern1|Pattern2
ignored_patterns_browser=~/AppData/Local/BraveSoftware/**/*.log|~/AppData/Local/Google/Chrome/**/*.tmp
ignored_patterns_sqlite=~/Documents/git/project/**/*.db-wal|~/Documents/git/project/**/*.db-shm

Group patterns under any ignored_patterns_<group> key (the <group> label is free-form); all ignored_patterns_* entries are merged together.

  • Glob syntax: *, **, ?, [abc]; separate patterns within a key with |
  • macOS/Linux use / paths (~/Library/...); Windows uses native absolute paths. ~ expands to your home directory before matching
  • Patterns match files only - they do not exclude folders from traversal

Search Aliases#

Define aliases to map search terms to related apps:

ini
alias_note=Notion|Obsidian|Notes|Apple Notes|Bear|Logseq
alias_code=Visual Studio Code|VSCode|Cursor|Windsurf|IntelliJ IDEA|PyCharm|WebStorm|Neovim|Xcode|Zed
alias_term=Terminal|iTerm|iTerm2|Ghostty|WezTerm|Alacritty|Kitty|Warp
alias_chat=Slack|Discord|Telegram|Messages
alias_music=Spotify|Apple Music|Music
alias_brow=Safari|Arc|Google Chrome|Chrome|Firefox|Brave

Alias behavior:

  • Aliases apply to app + System Settings search only
  • Aliases boost matching apps but don't create synthetic results
  • If an aliased app is not installed, no error is shown
  • Keep lists short (5-10 targets) for best results

Troubleshooting#

Look Won't Open#

Hotkey Doesn't Open Launcher#

  1. Check Spotlight shortcut conflict (macOS):
    • System SettingsKeyboardKeyboard Shortcuts...Spotlight
    • Disable or rebind "Show Spotlight search"
  2. Relaunch Look and try again
  3. Check if app is running:
bash
ps aux | grep -i look

Launcher Opens Behind Another Window#

This is usually a focus-handoff timing issue. Hide the launcher (Escape) and reopen. If it reproduces consistently, please file an issue with your OS version.

First Launch Issues (macOS)#

Current releases are signed and notarized. If you still encounter Gatekeeper issues:

  1. Confirm you installed a recent release
  2. Check System Settings → Privacy & Security for any blocks
  3. Legacy workaround (older builds only):
    • Right-click app → Open → confirm
    • Or use Privacy & SecurityOpen Anyway

App Crashed#

Crashes on Windows/Linux show a native dialog and append to a crash log:

  • Linux: ~/.local/state/look/crash.log
  • Windows: %LOCALAPPDATA%\look\crash.log

Please attach the last lines of that file when filing an issue.

Results Are Wrong or Missing#

Results Seem Stale or Incomplete#

  1. Reload configuration: Cmd/Ctrl+Shift+;
  2. Check scan settings in ~/.look/config:
    • file_scan_roots
    • file_scan_depth (range: 1-12)
    • file_scan_limit (range: 500-50000)
  3. Verify exclude rules aren't too broad
  4. Keep lazy_indexing_enabled=true and use Cmd/Ctrl+Shift+; to force refresh
  1. Check app_scan_roots includes the app's location
  2. Verify app_exclude_names doesn't exclude it
  3. Reload config: Cmd/Ctrl+Shift+;

No Answer Card for Questions#

  • Web answers may be turned off - check Settings → Advanced, or ai_enabled in ~/.look/config
  • Prefix queries (a", f", :cmd, ...) intentionally never trigger web lookups

Translation Returns Warnings/No Result#

  • Confirm network connectivity
  • Check that translation service is accessible

Warning Banners#

Look surfaces setup problems instead of failing silently. A sticky banner appears when, for example, the global hotkey could not be registered or the GNOME Shell extension needs a re-login to load. Dismissing a notice is remembered, so the same issue won't nag on every launch. The crash log location is under App Crashed.

Look Shows a Warning Banner#

Look surfaces setup problems in a sticky banner inside the launcher instead of failing silently. The two common ones:

  • Global hotkey could not be registered - another app owns the shortcut. On GNOME Wayland, Look frees the default Alt+Space window-menu binding automatically; on other setups, rebind or close the conflicting app.
  • GNOME extension needs a re-login (Linux) - the bundled GNOME Shell extension loads only after logging out and back in once after install.

Dismissing a banner is remembered, so the same issue won't reappear on every launch.

Settings Didn't Apply#

A Config Change Was Ignored#

  • Look reads ~/.look/config at launch; after editing manually, reload with Cmd/Ctrl+Shift+; or restart Look.
  • Confirm you edited the active config path. LOOK_CONFIG_PATH overrides ~/.look/config when set.

Reset Configuration#

To reset to default configuration:

  1. Open Settings (Cmd/Ctrl+Shift+,)
  2. Go to Advanced → "Create Fresh Config"
  3. Confirm the action (press Y)

This replaces your current ~/.look/config with the latest default template.

Performance and Display#

High CPU or Slow First Launch#

The initial index scan is a one-time cost; subsequent launches use the cached SQLite index. If you have very large user directories, lower file_scan_depth and file_scan_limit in ~/.look/config.

Visual Glitches on Linux (slider trails, overlapping popovers)#

Some WebKitGTK + GPU stacks (seen on Arch) ghost-render. Two opt-in workarounds, arch_disable_gpu and arch_disable_blur - see Platform Workarounds.

Inspecting Local State#

Need to Inspect Local DB#

Query the local SQLite database to inspect indexed candidates:

bash
# macOS
sqlite3 "$HOME/Library/Application Support/look/look.db" \
  "SELECT id,title,use_count FROM candidates ORDER BY use_count DESC LIMIT 20;"

# Linux
sqlite3 "$HOME/.local/share/look/look.db" \
  "SELECT id,title,use_count FROM candidates ORDER BY use_count DESC LIMIT 20;"

Development#

Building from Source#

Requirements#

  • macOS: macOS 15.0+, Xcode
  • Windows/Linux: system deps (see BUILDING.md)
  • All platforms: Rust stable toolchain (for the core engine)

Repository Structure#

look/
├── apps/macos/LauncherApp/    # SwiftUI shell (macOS)
├── apps/linows/               # Tauri v2 app (Windows + Linux)
│   └── src-tauri/             # Rust backend
├── core/                      # Rust workspace (shared)
│   ├── engine/                # Search & indexing
│   ├── matching/              # Fuzzy matching
│   ├── ranking/               # Result ranking
│   ├── storage/               # SQLite storage
│   ├── answers/               # Web answer sources (Wikipedia, currency, ...)
│   └── todo/                  # Shared todo backend
├── bridge/ffi/                # Swift-Rust FFI (macOS)
└── docs/                      # Documentation

Build Commands#

bash
# Check Rust core workspace
cd core
cargo check --workspace

# Check FFI bridge (macOS)
cd bridge/ffi
cargo check

# Run macOS dev app
make app-run

# Run Tauri dev (Windows/Linux)
cd apps/linows
cargo tauri dev

Dev App Behavior#

make app-run:

  • Builds local app bundle with Xcode (Debug)
  • Stops any running Look process (including a Homebrew-installed instance)
  • Launches with LOOK_CONFIG_PATH=$HOME/.look.dev.config
  • Shows red TEST APP badge for visual distinction

Side-by-Side Dev Build#

make app-run-dev installs /Applications/Look Dev.app with a separate bundle id (noah-code.Look.Dev), so the Homebrew-installed Look.app stays untouched:

bash
make app-run-dev

Override the dev config path when needed:

bash
make app-run DEV_CONFIG_PATH="$HOME/.look.qa.config"
make app-run-dev DEV_CONFIG_PATH="$HOME/.look.qa.config"

Running Tests#

bash
# Rust tests
cd core
cargo test --workspace

# FFI bridge tests
cd bridge/ffi
cargo test

Benchmarks#

Benchmarks live in a separate tools/perf crate (never bundled into a shipped binary):

bash
cd tools/perf
cargo run --release --bin query_engine_bench     # query throughput + fuzzy scoring
cargo run --release --bin scoped_refresh_bench   # per-call refresh latency
cargo run --release --bin watcher_stress         # simulated event streams

Snapshots land under docs/bench-notes/ - add a new snapshot when scoring, matching, or indexing changes.

Architecture Overview#

Look uses a shared Rust core with platform-specific UI shells:

  • macOS: SwiftUI shell communicating with Rust engine via FFI
  • Windows + Linux: Tauri v2 shell (vanilla HTML/CSS/JS frontend) calling Rust engine directly as crate deps
  • Rust Engine: Fast search and indexing, shared across all platforms
  • SQLite Storage: Local database for candidates, usage data, and todo tasks

Core Components#

  1. Search Engine: Handles fuzzy matching and ranking
  2. Index Manager: Manages file/app indexing
  3. Storage Layer: SQLite for persistence
  4. Answers: Shared web answer sources (DuckDuckGo, Wikipedia, currency/weather/crypto)
  5. FFI Bridge: Swift-Rust communication (macOS)
  6. Tauri Commands: Direct Rust calls (Windows/Linux)

Contributing#

Contribution flow:

  1. Branch from main - it is the only long-lived branch
  2. Open PRs into main, and keep branches short-lived so they stay easy to rebase
  3. Run local checks before opening a PR: bash cargo test --workspace --manifest-path core/Cargo.toml cargo test --manifest-path bridge/ffi/Cargo.toml
  4. Update docs when user-visible behavior changes

See CONTRIBUTING.md and DEVELOPMENT.md for details.