Documentation

Last Updated on August 15, 2026

Contents

Getting Started · Workspace · Editor · Outline, Labels & BibTeX · Building · PDF & SyncTeX · AI Assistant · Tabs & Sessions · Preferences · Shortcuts · Trial & License · Updates

Guides

Step-by-step walkthroughs for common tasks. We’re working on these — they’ll be linked here as they’re published:

↑ Back to top


Getting Started

texspark is a LaTeX editor for macOS.

Install — drag texspark.app into Applications. The app itself does not bundle a TeX distribution; you need MacTeX or BasicTeX installed and reachable on your shell’s $PATH. If which xelatex in Terminal returns a path, you’re set.

First build:

  1. ⌘N for a new document, paste or write your source, ⌘S to give it a path on disk
  2. ⌘B kicks off the configured build command. The compile log streams into the Terminal at the bottom; the rendered PDF appears on the right

If the build fails, the bottom panel automatically switches to Issues so you land on the first error rather than the raw log. Once a clean build wipes them out, it switches back to Terminal.

You get a 14-day full trial with no signup. Past the trial the editor stays usable read-only until a license is entered — see Trial & License.

↑ Back to top


Workspace

The window splits into four resizable areas. Each splitter ratio is remembered per launch.

  • Left — Sidebar. Tabbed between Outline, Labels, and BibTeX, each with a filter input. Collapsible — a toggle in the editor’s status bar (beside the bottom-panel toggle) hides it so the editor gets the full width. Both toggles keep an edge-specific icon whether open or closed, and dim when their panel is hidden; the state is remembered across launches
  • Center — Editor. Tabs on top, status bar with word count on the bottom
  • Right — Companion panel. Tabbed between the PDF viewer and the AI Assistant chat. ⌘T toggles between them
  • Bottom — Output panel. Tabbed between the embedded Terminal (with an editable build/custom command header), the parsed Issues list, and the raw compile Log. Collapsible — ⇧⌘Y or the toggle button in the editor’s status bar hides it so the editor fills the height; a build that produces errors reopens it automatically

Every panel header uses the same caption + segmented-control pattern, so switching context never moves the click target. Themes (Light / Dark / System) flip the editor, gutter, terminal, and chat colors together.

↑ Back to top


Editor

Built on a native NSTextView (TextKit 2), which means every macOS text input feature works as you’d expect — IME (including 한글 / 中文 / 日本語), the Services menu, dictation, the system Find bar, accessibility, and so on. The editor also disables AppKit’s smart-quote and dash substitution by default; LaTeX source needs the literal characters.

Highlighting & folding

  • LaTeX syntax, math, environment names, and comments are highlighted in colors that follow the active theme
  • .bib syntax highlighting — open a .bib file and entry types, field names, citation keys, and braces are colored to match the active theme, just like .tex
  • Bracket and environment matching — when the caret sits next to {, [, (, $, or inside \begin{…} / \end{…}, both halves get a soft background highlight
  • Code folding for sectioning commands (\section, \subsection, …) and for \begin{…} … \end{…} blocks. A chevron in the gutter toggles each region; a small chip appears to the right of the folded header as a click target. Folding collapses cleanly even on large or deeply-nested sections
  • The gutter shows line numbers at a fixed line height, so soft-wrapped lines and taller CJK / IME-composition fallbacks never shift the baselines or drift the numbering

Minimap

A slim overview of the whole file down the right edge of the editor. It renders your actual text — syntax colors and all — scaled way down, so you can see a document’s shape at a glance and jump around quickly. Glyph size stays fixed regardless of the document’s length: a long file slides within the strip to follow your position rather than squashing the whole thing to fit. Click or drag anywhere on it to scroll straight there, and a translucent box marks the region currently on screen. It mirrors the editor’s soft-wrapping, so a long paragraph reads as a tall block just as it does in the editor. Toggle it in Preferences → Editor → Minimap.

Autocompletion

One popup that knows four contexts. Navigate with ↑↓, accept with Tab or Enter, dismiss with Esc. Matching is case-sensitive: \t shows theta, tau, textbf… while \T shows Theta, Tau. The popup never re-opens from caret movement alone — moving the cursor through existing text with arrow keys won’t grab the next keystroke as a selection.

  • \command — the canonical command set (math, Greek, structure, fonts, references, common environments)
  • \begin{… / \end{… — environment names. Picking one inside \begin{…} also scaffolds the matching \end{name} on the next line, with the cursor parked on the blank line in between
  • \ref{… / \eqref{… / \cref{… (and friends) — labels discovered from the active document and recursively from every \input / \include in the project
  • \cite{… / \citep{… / \citet{… (and friends) — citation keys drawn from the project’s .bib files, the same set that populates the BibTeX sidebar tab

Bracket and environment helpers

  • Auto-pair — typing { [ ( $ drops the closing half in and parks the caret between
  • Escaped pairs\{ emits \{\}, \[ emits \[\], \( emits \(\). \$ is treated as a literal dollar (no pairing)
  • Skip-over — typing the closing character when the cursor sits right before it just moves past, never duplicates. Works for }, ], ), and a closing $
  • Pair Backspace — pressing Backspace inside an empty pair ({|}, \{|\}, …) removes both halves in one keystroke
  • \begin{x} + Enter — auto-inserts a blank line and the matching \end{x}, caret on the blank line

Every one of these is gated by Preferences → Editor → Auto-complete, so turning it off restores plain typing behavior across the board.

Smart Enter, comments, indentation

  • Enter carries the current line’s leading whitespace; double-Enter on a line that only looks blank trims the dangling whitespace so LaTeX sees a real paragraph break
  • Tab on a selection block-indents; Shift+Tab outdents. Both use 4 spaces
  • ⌘/ toggles a % line comment over the selection (or the current line). It detects whether the block is already commented and either adds or removes the prefix uniformly, and the caret rides along with the inserted/removed % instead of staying put

Pasting from elsewhere

Paste is run through a small sanitizer first. Invisible look-alikes that sneak in from PDFs, Office docs, and the web get fixed in place: non-breaking spaces (U+00A0) become regular spaces; zero-width space / non-joiner / joiner / word-joiner, BOMs (U+FEFF), and soft hyphens (U+00AD) are dropped. Everything else passes through untouched, so plain-ASCII paste is unchanged.

Find & Replace

The native AppKit Find bar lives inside the editor’s scroll view. After dismissing it, keyboard focus is forced back to the editor so subsequent typing lands on the selection instead of drifting to the terminal.

  • ⌘F — open Find
  • ⌘R — open Find and Replace
  • ⌘G / ⇧⌘G — next / previous match
  • ⌘E — use selection as the find string

Saving

texspark saves when you ask: ⌘S writes the active tab, and File → Save All (⌥⌘S) writes every open document in one pass — no per-file prompt. Save All writes everything that’s safe and, if a file changed on disk outside texspark, leaves it untouched and lists the skipped files at the end so you can resolve each one deliberately. Untitled tabs are skipped — texspark doesn’t pick a path for you. (Background auto-save is currently disabled while texspark is in active development, so nothing is written behind your back.)

Reloading & external changes

Every open file is watched. When one changes on disk outside texspark — a git checkout, another editor, a build script — the tab shows an orange badge so you know the on-disk copy has moved on. texspark never reloads it out from under you.

  • Reload on demand — the button in the editor header, or right-click a tab → Reload from Disk. If the tab has unsaved edits, texspark confirms before discarding them.
  • Conflict-aware save & build — saving or building over a file that changed on disk stops to ask (overwrite with your version, discard your edits and reload, or cancel) rather than silently losing either side.

↑ Back to top


The left sidebar has three tabs, picked from a segmented control at the top. Each comes with a live filter input — start typing and the list narrows in place (hierarchy temporarily flattens so every match is visible).

Outline

A live section tree of the build-target document if one is set, otherwise the active tab. Built from your unsaved buffer — no save needed.

  • Click an entry → editor cursor jumps and the PDF forward-searches
  • The section that contains your cursor — and its full ancestor chain (section → subsection → paragraph) — is highlighted live as you move around, and a forward search (⌘⇧↩) scrolls the outline to that item. On relaunch, the outline also scrolls to the section holding your restored cursor, so a long document reopens in context
  • The parser follows \input / \include into sub-files, preferring live in-editor content over disk so unsaved edits in an open sub-file still appear in the outline
  • Recognizes \newcommand aliases for sectioning macros — if you wrap \section in a custom command, the outline still picks up the headings
  • Starred sectioning commands (\chapter*, \section*, …) appear without a number and don’t advance the numbering, so a starred preface doesn’t push your first real chapter to “2”
  • Lines starting with % are ignored, so commented-out \sections don’t pollute the tree
  • Right-click anywhere in the panel for Collapse all / Chapters / Sections / Subsections / Expand all. Same set, same ordering, same wording as Preferences → Editor → Outline → Initial expansion

Expand / collapse state is sticky per item and survives relaunches — but only once you’ve actually customized it. If you never touch the tree, the Preferences default is reapplied on every launch, so changing that preference takes effect immediately on the next start.

Labels

Every \label{…} in the project, also discovered recursively across \input / \include. Click a row to open the file that defines the label and jump to its line. Each row shows the line number on the right; full path + line are in the tooltip.

This list also feeds the editor’s \ref{…} / \eqref{…} / \cref{…} autocompletion — there is one source of truth.

BibTeX

Every entry from the .bib files your project references — discovered by walking \addbibresource{…} and \bibliography{…}, and recursively across every \input / \include, just like Outline and Labels. Each row shows the citation key and its entry type (@article, @book, …); the source file and line are in the tooltip. The same live filter narrows the list as you type.

  • Click a row → inserts \cite{key} at the editor’s cursor, right where you’re writing
  • Double-click a row → opens the .bib file that defines the entry and jumps to its line

This list also feeds the editor’s citation autocompletion: typing \cite{, \citep{, \citet{ (and friends) suggests your BibTeX keys the same way \ref{ offers labels — one source of truth, drawn from the same parsed entries.

↑ Back to top


Building

⌘B runs the configured build command in the embedded terminal. ⌘⇧⌫ sweeps the build directory clean of TeX aux artifacts (.aux, .log, .toc, .out, .synctex.gz, .bbl, .fdb_latexmk, and the rest of the usual suspects) while leaving your .tex sources and the rendered .pdf untouched.

Build target & flushing

The build target is the tab you’ve explicitly marked with the 🔨 icon; if none is marked, texspark uses the active tab. Before running, the editor flushes both the build target and the active tab to disk so the command never operates on a stale file — and it bypasses the binding debounce by reading the live NSTextView content, so even keystrokes from a few milliseconds ago make it into the saved file. If a file changed on disk outside texspark, the build stops to ask first rather than clobbering it.

For a multi-file project, set the project root (typically main.tex) as the build target. Now ⌘B from any sub-file still builds the right thing, and the PDF / SyncTeX flow follows the project root.

Command templates & tokens

Preferences → Compile ships templates for xelatex, pdflatex, lualatex, latexmk, bibtex, and makeindex. The command box is editable; chain steps with && so any non-zero exit aborts the rest.

Each project remembers its own build command, keyed by its build target (🔨) — or the active file when none is marked. Switch projects and the command follows, so you can keep latexmk for one and xelatex && makeindex && xelatex for another without swapping by hand. Edit it inline from the Terminal panel’s command header (below) or in Preferences → Compile.

Two tokens are substituted into the command before it’s handed to the shell:

  • {file}main.tex (build target’s filename with extension)
  • {filename}main (without extension)

Both are properly shell-escaped, so spaces or quotes in the path don’t break the command. The command runs in the build target’s directory (a cd is prepended for you).

Command header

The top of the Terminal panel carries two always-visible, editable command rows, so you never leave your work to tweak a flag:

  • Build command — this project’s command (remembered per project), with a to build (⌘B). The 🔨 beside it opens Preferences → Compile for the templates and options.
  • Custom command — a one-off command with its own to run it (⌃⌘B).

Custom command

Alongside the build command, you can define one custom command to run in the embedded terminal — handy for a one-off bibtex, makeindex, latexmk -c, or any project script you don’t want folded into every ⌘B. Edit it in the Terminal panel’s command header, or in Preferences → Compile → Custom command.

Run it from the next to the custom-command field in the Terminal panel’s command header, from Build → Run Custom Command, or with ⌃⌘B. It behaves like the build command: it runs in the build target’s directory (a cd is prepended), expands the same {file} / {filename} tokens, and reveals the Terminal tab first so you see the output. The ▶ button is disabled until you’ve set a command.

Issues panel

The log parser collects every ! error and every … Warning: block, joining TeX’s 79-character wrapped lines back together so on input line N isn’t lost. Each issue carries a severity, line number, message, and — crucially — the originating file, tracked through TeX’s (./subfile.tex … ) paren stack.

  • Segmented filter at the top: All / Errors / Warnings, each with a count
  • Click a row → opens the file the issue came from (not just the build target) and scrolls to the right line. Errors in an \input{chapters/intro.tex} open chapters/intro.tex, not main.tex
  • Rows are text-selectable, draggable to other apps, and have Copy Message / Copy Line and Message / Jump to Source in the right-click menu

The bottom panel auto-switches to Issues whenever a build produces errors and back to Terminal the moment a clean build wipes them. You always land where the next action is — and if you’d collapsed the panel, an error reopens it for you.

Raw log

Next to Terminal and Issues sits a Log tab showing the compiler’s raw, unparsed output, decoded even when TeX wraps multi-byte (CJK) characters across its 79-column line breaks. It auto-scrolls to the end as the build streams — handy when a failure doesn’t surface as a clean ! error the Issues parser can catch.

After-build behavior

Toggleable in Preferences → Compile:

  • Switch to PDF panel — if you were chatting with the AI Assistant, the right panel automatically flips back to PDF so the freshly rebuilt document is in front of you
  • Jump to cursor — once the PDF reloads, forward-search to the line the cursor was on at build time

The PDF’s scroll position survives multi-pass builds. When latexmk rewrites the file mid-build (xelatex → makeindex → xelatex), the viewer keeps your position instead of bouncing back to page 1.

↑ Back to top


PDF & SyncTeX

Built on PDFKit. Continuous vertical scroll, auto-scaling page width.

  • Auto-reload — a file-system watcher catches the moment latexmk finishes and reloads, with rapid events coalesced so a half-written PDF is never displayed
  • Scroll preservation — even during a reload, your scroll position holds steady, tracked per document so switching tabs restores each PDF’s own position. Same for a forward-jump being queued in the same tick
  • Hand tool — right-click the PDF and pick Hand Tool to grab and drag the page around (the cursor turns into a hand); Select Tool switches back to text selection. ⌘-click inverse search works in either mode
  • Scroll to zoom — hold or and scroll to zoom in and out toward the cursor. Right-click → Automatically Resize snaps back to fit-width, where the page no longer drifts sideways
  • in the header — manual reload, in case you launched a build from outside texspark

Forward Search (editor → PDF)

⌘⇧↩ — texspark calls SyncTeX with the cursor’s line, scrolls the viewer to the matching position, and flashes a yellow highlight there for about 1.5 s.

Clicking an Outline entry, a Labels row, or an Issues row also triggers a forward search to the destination. Anything that triggers a forward jump while the right panel is showing the AI Assistant will automatically switch the right panel back to PDF — you never end up jumping behind the chat.

Inverse Search (PDF → editor)

⌘-click anywhere in the PDF. SyncTeX maps the click to a file and line; texspark opens that file (if it’s not already a tab) and scrolls to it. If the destination is a sub-file, its parent is automatically set as the build target so the next ⌘B still builds the project root.

Restoring on launch

On relaunch, after the session restores your tabs and cursor, texspark issues a forward search for the active tab’s cursor line. The PDF lands at the right place automatically.

SyncTeX requires -synctex=1 in the build command (the default templates include it, and the resulting .synctex.gz sits next to the PDF). If a project has no .synctex.gz yet, every jump degrades gracefully — the PDF stays where it is.

↑ Back to top


AI Assistant

Chat with an LLM in the right panel (⌘T toggles between PDF and AI Assistant). Three providers, each with their own current model lineup.

  • Claude (Anthropic) — Opus, Sonnet, Haiku
  • ChatGPT (OpenAI) — GPT-4.1, GPT-4o, GPT-4o-mini
  • Gemini (Google) — 2.5 Flash, 2.5 Pro, 2.0 Flash

The provider and model pickers sit in the panel header; the same settings are also in Preferences → AI. The panel shares the editor’s background so the two read as one workspace, with assistant replies in cards.

API keys

Paste a key into Preferences → AI for any provider, then click Verify. texspark round-trips the provider once with a small validation request before saving — if the key is wrong or the network is blocked, you find out immediately instead of next time you try to chat. Keys live in your Keychain, not in plist or JSON files.

System prompt & document context

  • System prompt is editable in Preferences → AI, with Reset to Default and Clear buttons. The default is tuned for LaTeX assistance — concise replies, math-notation aware, no unsolicited rewrites. Clear blanks it entirely (sent as “no system instructions”). Edits apply to the next message automatically — no restart — and a brief ✓ Applied badge confirms the save
  • Attach activated document toggle (in the panel itself) appends the current file’s source to the system prompt, capped at 60 KB so the request stays sendable
  • Max tokens (1024 – 32000) caps the response length

Attachments

The 📎 button next to the input attaches files (multi-select supported):

  • Text files (.tex, .bib, .cls, .sty, .txt, …) are read and inserted inline into your prompt as fenced code blocks — provider-agnostic and searchable in the draft
  • Images and PDFs are sent as real attachments to the vision-capable model (Claude, ChatGPT, or Gemini). Staged files appear as removable chips above the input before you send

Sending messages

  • Enter sends; Shift+Enter inserts a newline, so you can compose multi-line prompts
  • The input grows with your text up to 6 lines, then scrolls — a long draft (e.g. several quoted blocks) never pushes the chat log or the Send button off-screen
  • The response streams in token by token. While streaming, the send button becomes a red Stop — pressing it cancels the stream and keeps whatever was already received
  • Replies render markdown, with fenced code blocks in monospace, a one-click Copy button, and long lines wrapped to the panel width
  • While you’re at the bottom, the view auto-follows the streaming reply; scroll up and it stays put. A “jump to latest” button appears at the bottom-center to bring you back in one tap
  • If a request fails (bad key, no API credit, network), the error appears inline as a distinct red bubble with a readable message — right where the reply would have been — instead of a banner that scrolls away
  • The trash button at the top wipes the chat — both on screen and in the persisted history file

Send Selection & focus shuttle

The fastest way to ask about a specific block:

  • Select text in the editor
  • Right-click → Send Selection to AI Assistant, or press ⌘⇧A
  • The right panel flips to the AI Assistant, the input gets prefilled with the selection wrapped in a fenced latex code block, and the input takes focus with the caret parked at the end

Type your question above or below the block, then hit Enter. Repeated ⌘⇧A from the editor appends additional snippets to the same draft, so you can stack a few related blocks before asking.

⌘⇧A also shuttles your keyboard focus. With focus in the editor and no selection, it jumps to the AI input; with a selection it sends that selection first. With focus already in the AI input, ⌘⇧A sends you straight back to the editor — so one key round-trips between writing and asking without touching the mouse.

History & privacy

  • Chat history persists at ~/Library/Application Support/io.texspark.app/chatHistory.json. The retention cap is configurable in Preferences → AI → Chat history limit (0 = unlimited, the default). Attachment data (images/PDFs) is stripped before saving, so a reloaded old conversation shows the file chip but doesn’t re-upload the file
  • Requests go directly to the provider you picked, with the key from your Keychain. texspark itself doesn’t have an analytics endpoint, doesn’t proxy traffic, and doesn’t keep server-side logs of anything you ask
  • When the trial expires and no license is entered, the AI Assistant is disabled along with builds

↑ Back to top


Tabs & Sessions

Tabs

  • Drag horizontally to reorder, or drop .tex files from Finder onto the editor to open them as tabs
  • × or ⌘W closes; ⌥⌘W closes all (with a Save / Discard / Cancel prompt for each dirty tab). ⌥⌘S saves every open tab at once
  • ⌘⇧] / ⌘⇧[ rotates through tabs, wrapping at the ends
  • ⌘⇧P, double-click a tab, or right-click → Set as Build Target. The build target shows a small 🔨 icon; only one tab can be the build target at a time. ⌘B stays with that tab until you Clear Build Target
  • Right-click a tab → Reload from Disk to pull in an external change. A tab whose file changed on disk outside texspark shows an orange badge
  • The + menu opens new documents and lists recent files (with a Clear Menu at the bottom)
  • A dot ● on the close icon marks an unsaved tab

Switching tabs is instant — each tab keeps its own laid-out editor, and restored tabs are quietly pre-warmed in the background after launch (a small progress bar appears in the status bar while that runs), so the first switch to each is immediate too.

Session restore

Quitting texspark stamps a snapshot into NSUserDefaults; launching reads it back. Restoring is optional — turn off Restore last session on launch (Preferences → Editor) to start empty instead. Your tabs are still saved on quit either way, so flipping it back on reopens them. What gets restored:

  • Every open tab — file path, name, dirty content (if any), and the file gets re-read from disk so external edits are picked up while still flagging the in-editor content as unsaved if it diverges
  • Tab order and the previously active tab
  • The build target
  • Each tab’s cursor position — reopening a tab returns you to where your caret was, revealed into view (texspark restores the cursor rather than a raw scroll offset, so you land exactly where you were editing)
  • Sidebar tab (Outline / Labels / BibTeX), right-panel tab (PDF vs AI), bottom-panel tab (Terminal / Issues / Log) and whether it’s collapsed
  • Splitter ratios for every panel
  • Outline expansion state, but only when you’ve actually customized it (toggled a node or used the context menu). Otherwise the Preferences default expansion is reapplied — so changing the Preferences setting takes effect on the next launch instead of being overridden by a saved state
  • A forward-search to the active tab’s cursor line is queued for the PDF, and the outline scrolls to the section holding that cursor, so both the viewer and the sidebar land in context on first load

Each project’s build command is remembered too, so reopening a project brings back the command you last built it with.

↑ Back to top


Preferences

Open with ⌘,. Three sections: Compile / Editor / AI.

  • Compile — the build command (remembered per project), ready-made templates (xelatex / pdflatex / lualatex / latexmk / bibtex / makeindex), the custom command, and post-build toggles (switch to PDF, jump to cursor)
  • Editor — theme (Light / Dark / System), font family + size, autocomplete toggle (drives the whole completion stack: command / env / label / citation popups, bracket pairing, escaped pairs, env scaffolding, pair Backspace), code folding toggle, minimap toggle, Restore last session on launch toggle, and the Outline initial expansion level (Collapse all / Chapters / Sections / Subsections / Expand all) that applies to newly seen sections. Two safety options are locked while texspark is in active development: Confirm before overwriting (on) and background auto-save (off)
  • AI — provider, model, max tokens (1024 – 32000), Chat history limit (0 = unlimited), editable system prompt with Reset to Default and Clear, per-provider API key entry with Verify

↑ Back to top


Shortcuts

  • Build / Clean | ⌘B / ⌘⇧⌫
  • Run Custom Command | ⌃⌘B
  • Forward search (PDF) | ⌘⇧↩
  • Toggle PDF / AI panel | ⌘T
  • Toggle Bottom Panel (Terminal / Issues / Log) | ⇧⌘Y
  • Send Selection to AI Assistant / Toggle editor ↔ AI focus | ⌘⇧A
  • Set / Clear Build Target | ⌘⇧P (or double-click a tab)
  • Next / Previous tab | ⌘⇧] / ⌘⇧[
  • Find / Find and Replace | ⌘F / ⌘R
  • Find Next / Previous | ⌘G / ⇧⌘G
  • Use Selection for Find | ⌘E
  • New / Open / Save / Save As / Save All | ⌘N / ⌘O / ⌘S / ⌘⇧S / ⌥⌘S
  • Close / Close All | ⌘W / ⌥⌘W
  • Toggle Line Comment | ⌘/
  • Preferences | ⌘,

↑ Back to top


Trial & License

You get a 14-day full trial from first launch. No signup, no email gate. After the trial, three things turn off until you enter a license: editing (the editor goes read-only), builds, and the AI Assistant.

  • License → Buy License… opens checkout
  • License → Enter License Key… activates this Mac. A single license activates up to 3 machines
  • License → Manage License… lists every machine your key is currently active on; deactivate any of them remotely to free a slot
  • After the first activation, texspark works offline and silently re-validates with the licensing server every 14 days. Brief network outages don’t lock you out

Refunds within 14 days of purchase — email support@texspark.io. Same address for any licensing question.

↑ Back to top


Updates

texspark → Check for Updates… runs an immediate check. A daily background check is on by default.

Every update is signed with an EdDSA key bundled in the app. The updater refuses any download whose signature doesn’t match — so even if the network between you and the update host were tampered with, an update can’t be silently swapped on the way down.

↑ Back to top