| Age | Commit message (Collapse) | Author |
|
Main document: the app never called Overleaf's official settings endpoint,
so "Set as main document" only changed renderer state and agents had no way
to switch at all — compiles kept using the old root. Now:
- Right-click Set as main and the new set_main_file MCP tool both POST
/project/:id/settings {rootDocId} (web parity, persists project-wide)
- Handle the rootDocUpdated broadcast: update the project snapshot, the
renderer state, and rewrite CLAUDE.md/AGENTS.md — the guide's stale
"Main file" line was teaching agents to compile the old root via
main_file overrides
- Compile root resolution uses the sync bridge's live maps, so docs
created mid-session resolve correctly (agent guide too)
MCP server location: Codex stores its MCP registration globally, and the
per-project path went stale when the project temp dir was cleaned up
("connection closed" on handshake). The bundled server now installs to
~/.lattex/lattex-mcp.mjs (project-independent, refreshed on connect; the
esbuild bundle since the raw source can't resolve node_modules from there)
and resolves the project at runtime: $LATTEX_PROJECT_DIR, cwd + ancestors,
legacy script location, then single live project in tmpdir. Register once,
works for every project.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
The project list is now a persistent home tab; each opened project runs
in its own WebContentsView tab below a 38px tab strip (hidden when only
home is open). Background tabs stay fully live (sync, collab, terminals).
Main process: per-project singletons (socket, sync bridge, compilation
manager, MCP state, compile watcher) become per-tab ProjectSession
objects keyed by webContents.id; PTYs are scoped per webContents.
Hardened against races found in review: concurrent ot:connect dedupe,
teardown/reopen serialization on the shared sync dir, destroyed-window
guards on all bridge sends, real logout that closes project tabs.
Renderer: tabs strip in the home renderer (wt-* classes, distinct from
the editor's .tab-bar file tabs), project tabs boot from ?projectId= and
connect straight into the editor; Back closes the tab.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
- Normalize watcher paths to forward slashes (Windows events use
backslashes; all sync maps are '/'-keyed), path.delimiter for
PATH/TEXINPUTS, dirname() instead of '/'-substring splits, bridge log
in os.tmpdir()
- Platform-aware TeX search paths (TeX Live / MiKTeX on Windows),
terminal shell default (COMSPEC/powershell), native window frame off
macOS
- electron-builder: NSIS target + win icon + GitHub publish provider
- GitHub Actions workflow builds the Windows installer on tag push
(node-pty needs MSVC — cannot cross-compile from macOS) and attaches
it to the release
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
- Write AGENTS.md (the cross-tool agent-instructions standard) at the
project root alongside .claude/CLAUDE.md, generated from one guide;
includes an Agent Setup section with the project-specific Codex MCP
registration command. AGENTS.md is excluded from Overleaf sync.
- MCP server resolves the project directory from its own script location
when cwd doesn't contain the state file, so clients that launch MCP
servers from a global config (Codex) work without special setup
- Terminal: swallow the duplicate compositionend commit when switching
input sources mid-composition (xterm finalizes on the keydown and then
again on compositionend, sending pinyin text twice)
- Don't render our own colored overlay cursor — the native caret already
marks our position; overlay cursors are collaborators-only (web parity)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Uses the Overleaf open-source code as golden reference throughout.
Project dashboard (official /tag + /project endpoints):
- Sidebar filters (all/yours/shared/archived/trashed) with the web
client's exact filtering predicates
- Tags: create/edit/delete with the official preset palette, per-row
chips, bulk add/remove, uncategorized view
- Archive/trash/restore/delete-forever/leave, rename, copy, zip download,
multi-select bulk actions (parallelized)
Editor:
- Remote cursors rewritten as a layer() overlay ported from Overleaf's
cursor-highlights — no more inline widgets disturbing line wrapping,
cursor motion, or IME composition
- Autocomplete ported from Overleaf's completion system: official
top-hundred snippet data, environment templates, package/class/bib
style data (verbatim, AGPL), project-wide \ref and \cite completion,
package commands via the official /project/:id/metadata endpoint,
brace-aware apply behavior, official keymap precedence
- Fixed completion popup keybindings (Enter/arrows previously fell
through to the default keymap) and dead Enter/Backspace handlers in
latexClosing
File sync reliability:
- Two-tier compile-artifact detection: pure build noise is ignored,
while pdf/docx/gz/bbl sync unless there is concrete local-compile
evidence — agent-generated figure PDFs now sync (previously all PDFs
were blanket-ignored)
- Local compile outputs are registered with the bridge so nested-root
projects don't upload the root PDF as junk
- Upload retry with exponential backoff and permanent-failure parking,
CSRF refresh with session validation and single-flight guard,
periodic orphan rescan, sync status surfaced in the status bar
- Official textExtensions list (plus legacy extras) for doc-vs-file
classification
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
|
|
The server broadcasts otUpdateApplied (with ops) to ALL clients including
the sender. Our bridge was treating its own echoed ops as remote ops and
re-applying them, causing text duplication (e.g. "simulatorimulator").
Rewrite OT handling to match Overleaf's ShareJS _onMessage pattern:
- ACK = no ops OR meta.source matches our publicId (own echo)
- REMOTE = ops from a different source
- ACK path calls onAck() without re-applying ops
- OtClient silently drops duplicate acks in synchronized state
- OtClient drops stale remote ops (version < current)
- Remove pendingEchos counter in favor of meta.source detection
Also: refresh MCP comment contexts on new-comment/delete-thread events,
add Overleaf reference repo to .gitignore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
When addEditorDoc is called while the bridge has in-flight OT ops
(awaitingConfirm), the ack/error response was ignored because
handleOtUpdate/handleOtError skipped editor docs entirely. This left
the bridge's OtClient stuck and the edit appeared lost until
removeEditorDoc re-discovered the discrepancy.
Fix: always process acks regardless of editor doc status, and only
skip OT errors for editor docs when the bridge has no OtClient.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
CLAUDE.md
- Online users: click "N online" badge to see user names with cursor colors
- MCP get_online_users tool: main process tracks users in .lattex-online-users.json
- CLAUDE.md: show current user's Overleaf name (fetched from /user/settings)
- CLAUDE.md: mandatory first steps with MUST/NEVER language at top of file
- claude-workspace/ directory: untracked scratch space for Claude Code experiments
- chokidar + bridge skip claude-workspace/ to prevent syncing to Overleaf
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
- Fix .bib (and other non-active tab) edits disappearing: call otLeaveDoc
on tab switch so bridge takes back OT ownership; release .bib pre-loads
immediately after reading content for citation autocomplete
- Always update lastKnownContent in processDocChange for editor docs to
prevent stale state accumulation
- Flush pending OT ops in OverleafDocSync.destroy() before tab switch
- Add three-way merge in replaceContent to preserve concurrent remote edits
- Wire MCP compile to UI: file-based signal between MCP server and Electron
main process, with compile animation and PDF refresh in renderer
- Add CLSI flush before compile to prevent stale cached results
- Add OT error recovery: re-join doc and re-apply disk changes on otUpdateError
- Add bridge reconnect handling: reset OtClient on docRejoined for non-editor docs
- Add compile concurrency lock to prevent duplicate compiles
- removeEditorDoc compares disk vs server content to catch in-flight ops
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
When Claude Code writes to disk, a debounce timer is set. If a remote
Overleaf op arrives during the debounce, onEditorContentChanged would
write the remote content back to disk, overwriting Claude Code's edit.
Fix: skip disk write and lastKnownContent update in onEditorContentChanged
when a debounce is pending (external disk change waiting to be processed).
Also increase writesInProgress guard to 800ms to exceed chokidar's 500ms
polling interval.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
- Exclude CLAUDE.md from sync (move to .claude/ dotfile dir, clean up root copy)
- Add Ctrl+wheel font zoom for editor (capture phase, disable Electron built-in zoom)
- Load cached PDF on project connect (avoid recompile to see last PDF)
- Add synctex debug logging for PDF↔source navigation troubleshooting
- Fix .claude/ dir creation order (mkdir before write)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Overleaf
The root cause of server compile failures was that output.pdf was being
saved into the synced project directory, causing FileSyncBridge to upload
it back to Overleaf as a project file. CLSI then failed because it found
an existing output.pdf blocking its compilation output.
Changes:
- Save compile artifacts (PDF, synctex.gz) to .build/ subdirectory instead
of the synced project root — .build is a dotfile dir ignored by chokidar
- Add pdf/pdfxref/stderr/stdout/chktex to FileSyncBridge ignore patterns
- Add rootResourcePath to compile request body (matches Overleaf web client)
- Implement PDF download with fallback via direct build ID URL construction
- Add server compile handler, compile dropdown menu, PDF save button
- Fix resolved comment highlight flash on startup (null initial state)
- Fix EPIPE crash on startup when stdout/stderr is closed
- Fix synctex inverse search to use relative paths via OT doc join
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
- Sync new local files (created by Claude Code etc.) to Overleaf via REST API
- Create intermediate folders as needed, handle both text docs and binaries
- Scan for orphaned files on startup that weren't synced previously
- Add "Copy Comments" quick action: copies unresolved comments for current file
to clipboard with line numbers, context, author names, and timestamps
- Filter comments to active file only, exclude resolved threads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Root cause: SHA-1 hash sent with applyOtUpdate didn't match Overleaf's
server-side computation, causing "Invalid hash" error, disconnect, and
rollback of all synced changes.
- Remove hash field from applyOtUpdate to skip server-side hash check
- Switch applyOtUpdate from fire-and-forget to emitWithAck for reliable ack
- Fix getOldDoc bug: save base doc when changes start accumulating instead
of incorrectly using current doc (caused wrong delete ops)
- Fix ack handler: only ack when no 'op' field (was acking remote ops too)
- Await fileSyncBridge.start() instead of fire-and-forget
- Add joinDoc retry logic for transient joinLeaveEpoch mismatch errors
- Clear pending ack callbacks on WebSocket close to prevent timeout errors
- Add otUpdateError logging for server-side rejections
- Add file-based bridge logging for debugging sync issues
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
chokidar FSEvents is unreliable in macOS temp dirs and misses atomic
writes (write temp + rename) used by Claude Code and other editors.
Switch to usePolling with 500ms interval and atomic: true.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
FileSyncBridge now handles binary fileRefs in addition to text docs:
- Downloads all binary files to temp dir on project connect
- Watches for binary file changes on disk and uploads via REST API
- Listens for Overleaf socket events (reciveNewFile, reciveNewDoc,
removeEntity, reciveEntityRename) to sync remote changes to disk
- Tracks binary files by SHA1 hash to avoid redundant uploads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Implement full Overleaf integration with Socket.IO v0.9 real-time sync:
- FileSyncBridge for bidirectional temp dir ↔ Overleaf sync via chokidar + diff-match-patch
- OT state machine, transform functions, and CM6 adapter for collaborative editing
- Comment system with highlights, tooltips, and review panel
- Project list, file tree management, and socket-based compilation
- 3-layer loop prevention (write guards, content equality, debounce)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|