Skip to content

mei28/nvim-overleaf

Repository files navigation

nvim-overleaf

CI

Japanese / 日本語

Neovim plugin for real-time bidirectional sync with Overleaf.

Edit your LaTeX projects locally in Neovim. Changes sync to Overleaf on save, and collaborators' edits appear on your disk in real-time.

Features

  • Bidirectional sync: local :w pushes to Overleaf, remote edits write to your files
  • Real-time collaboration via Operational Transformation (OT)
  • Local files on disk — use any tool (LSP, git, grep, etc.)
  • Automatic reconnection on network failure
  • Statusline integration

Requirements

Installation

lazy.nvim

{
  'mei28/nvim-overleaf',
  dependencies = {
    'vim-denops/denops.vim',
  },
  cmd = { 'OverleafInit', 'OverleafSync', 'OverleafStatus' },
  opts = {},
}

If you don't have Deno:

# macOS
brew install deno

# or curl (Linux/macOS)
curl -fsSL https://deno.land/install.sh | sh

Setup

1. Get your session cookie

  1. Open overleaf.com in your browser and log in
  2. Open Developer Tools (F12)
  3. Go to Application > Cookies > https://www.overleaf.com
  4. Find overleaf_session2 and copy the value (starts with s%3A)

The cookie expires after about 5 days. Recopy it when it expires.

2. Get your project ID

Copy it from your Overleaf URL:

https://www.overleaf.com/project/64a1b2c3d4e5f6g7h8i9j0
                                   ^^^^^^^^^^^^^^^^^^^^^^^^

3. Initialize the project

mkdir my-thesis && cd my-thesis
nvim
:OverleafInit

You'll be prompted for the cookie and project ID. The plugin will:

  1. Connect to Overleaf
  2. Download all files to the current directory
  3. Save connection info to .overleaf/config.json (including cookie)
my-thesis/
├── .overleaf/
│   └── config.json
├── main.tex
├── chapters/
│   └── intro.tex
└── references.bib

Usage

Daily workflow

:OverleafSync       " connect and sync (reads saved cookie from .overleaf/)

Then just edit files and :w. Changes push to Overleaf automatically. Collaborators' edits appear in your local files in real-time.

Commands

Command Description
:OverleafInit First-time setup. Prompts for cookie and project ID.
:OverleafSync Connect and sync. Uses saved cookie from .overleaf/.
:OverleafOpen Pick a document to open in a buffer with real-time OT sync.
:OverleafStatus Show connection state and project info.
:OverleafMessages Show activity log (connection, sync, errors).
:OverleafDisconnect Disconnect from Overleaf.
:OverleafLogLevel {level} Set log verbosity (debug info warn error).

Configuration

require('overleaf').setup({
  autoread = true, -- silently reload buffers on remote changes (default: true)
})

When using Lazy.nvim, pass options via opts:

{
  'mei28/nvim-overleaf',
  dependencies = { 'vim-denops/denops.vim' },
  opts = {
    autoread = true,
  },
}

Statusline

The plugin exposes a Lua API that returns raw state, so you can format it however you like.

Lua API

require('overleaf').get_state()
-- => "connected" | "connecting" | "authenticating" | "reconnecting" | "disconnected"

require('overleaf').get_status()
-- => { state = "connected", projectName = "my-thesis", openDocs = 2, syncedFiles = 5, ... }

lualine.nvim examples

Minimal:

{
  function()
    return 'OL'
  end,
  cond = function()
    return require('overleaf').get_state() == 'connected'
  end,
}

With connection state:

{
  function()
    local state = require('overleaf').get_state()
    if state == 'connected' then return 'OL' end
    if state == 'reconnecting' then return 'OL …' end
    if state == 'connecting' or state == 'authenticating' then return 'OL …' end
    return ''
  end,
  cond = function()
    return require('overleaf').get_state() ~= 'disconnected'
  end,
}

With project name:

{
  function()
    local status = require('overleaf').get_status()
    if status.state == 'connected' then
      return 'OL: ' .. (status.projectName or '?')
    end
    if status.state ~= 'disconnected' then
      return 'OL: ' .. status.state
    end
    return ''
  end,
  cond = function()
    return require('overleaf').get_state() ~= 'disconnected'
  end,
}

The legacy overleaf#statusline() VimScript function is still available; it returns the raw state string.

How it works

 Local files                        Overleaf
 +----------+    :w (save)          +----------------+
 | main.tex | ──────────────────>   |                |
 |          |    OT operations      | real-time      |
 | (disk)   | <──────────────────   | collaboration  |
 +----------+    remote changes     +----------------+
      |                                    |
      | file watcher                       | Socket.IO v0.9
      | Deno.watchFs                       | WebSocket
      v                                    v
 +---------------------------------------------+
 |              Deno (denops)                   |
 |  OT engine | Document state | Socket.IO     |
 +---------------------------------------------+
  • :w triggers file watcher -> diff against server state -> OT ops -> send to Overleaf
  • Remote edits arrive as OT updates -> transform against local state -> write to disk
  • All documents stay joined for the duration of the session
  • Custom Socket.IO v0.9 client (Overleaf's server requires this protocol version)
  • Automatic reconnection with exponential backoff

Architecture

denops/overleaf/
├── main.ts              -- Denops entry point
├── app.ts               -- Orchestrator
├── auth/                -- Cookie auth, CSRF extraction
├── document/            -- OT state machine (inflight/pending/version)
├── ot/                  -- OT engine (apply, transform, unicode)
├── protocol/            -- Socket.IO v0.9 client, Overleaf events
├── project/             -- File tree, entity ID mapping, .overleaf/ config
├── sync/                -- File watcher, remote applier, echo guard
└── util/                -- EventEmitter, logger, debounce

Development

just ci          # fmt + lint + check + test
deno task test   # run tests only
deno task check  # type check only

Limitations

  • www.overleaf.com only (self-hosted Overleaf support planned)
  • Requires manual cookie from browser DevTools
  • No PDF preview (use VimTeX or an external viewer)
  • No LaTeX compilation trigger yet

Related projects

License

MIT

About

Neovim plugin for real-time bidirectional sync with Overleaf. Edit your LaTeX projects locally in Neovim. Changes sync to Overleaf on save, and collaborators' edits appear on your disk in real-time.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors