Add the LaTeX Workshop extension to Visual Studio Code and a general-purpose code editor becomes a serious LaTeX environment: it compiles on every save, shows the PDF in a side-by-side tab, and lets you jump between source and PDF in both directions. This page walks through setup, how builds work (recipes and tools), and SyncTeX integration.
What LaTeX Workshop is
VS Code does not typeset TeX itself. The actual compiling is done by a distribution you install on your machine — TeX Live (or MiKTeX / MacTeX). LaTeX Workshop, by James Yu, is the bridge between the editor and that distribution: it launches builds, previews the PDF, and adds completion, syntax highlighting, jump-to-definition for \ref/\cite, an outline view, and more. Its Marketplace ID is James-Yu.latex-workshop, with over 5 million installs — effectively the default LaTeX extension in the VS Code ecosystem.
The one prerequisite is that the TeX commands are reachable on your PATH. The extension simply spawns executables such as latexmk or pdflatex as child processes, so if latexmk --version works in a terminal, the extension will almost certainly work too. Conversely, choosing an engine or configuring Japanese fonts is a matter for the distribution, not for the extension.
Compile once in the terminal first
Before tuning VS Code settings, build the same project once in a terminal. If latexmk cannot run there, LaTeX Workshop cannot launch it either. For a first document, try one of these from the project folder:
latexmk -pdf main.tex
# 日本語 upLaTeX を .latexmkrc に書いた場合 / if .latexmkrc selects upLaTeX
latexmk main.texOnce PATH and missing-package errors are resolved there, any VS Code-side failure is narrowed to recipes, root-file detection, or the PDF viewer. If the terminal build works but the extension fails, inspect settings.json: output directory, recipe name, and placeholders are the usual suspects.
Setup
The steps are simple. Install VS Code, install a distribution such as TeX Live (in 2026, TeX Live 2026) and make sure it is on your PATH. Then open the Extensions view (Ctrl/Cmd+Shift+X), search for “LaTeX Workshop,” and install it. Right after changing the PATH, restart VS Code — ideally the whole OS — so the new environment is picked up. Open a .tex file and the TeX activity-bar icon on the left gives you build and preview commands.
Settings live in settings.json (from the Ctrl/Cmd+, Settings UI, use “Open Settings (JSON)” in the top-right; you can edit either the global user file or a per-project .vscode/settings.json). The three keys worth knowing first are:
latex-workshop.latex.outDir— where intermediate files and the PDF go. Default%DIR%(next to the.tex). Setting it to e.g.outkeeps your source folder uncluttered.latex-workshop.latex.autoBuild.run— what triggers an automatic build:onFileChange(default; watches dependencies),onSave(on save), ornever(manual only). If you want predictable behavior,onSaveis a safe pick.latex-workshop.view.pdf.viewer— where the PDF appears:tab(default; a tab inside VS Code),browser, orexternal. For frictionless SyncTeX,tabis the best choice.
A minimal starting point is just this — collect output in out/, build on save, and show the PDF in the built-in tab:
{
"latex-workshop.latex.outDir": "%DIR%/out",
"latex-workshop.latex.autoBuild.run": "onSave",
"latex-workshop.view.pdf.viewer": "tab"
}%DIR% is a placeholder that expands to the directory of the root file being processed; it reappears in recipes below. After a build the extension can also tidy up or keep intermediate files (.aux, .log, …) via latex-workshop.latex.autoClean.run, but settling the output directory and the trigger is enough to get a feel for it.
Build recipes and tools
Builds in LaTeX Workshop have two layers: “tools” and “recipes.” A tool (latex-workshop.latex.tools) defines a single command to run — name, command (the executable), and args. A recipe (latex-workshop.latex.recipes) is an ordered sequence of tools, with a name and a tools array listing tool names. A flow like “pdflatex → bibtex → pdflatex → pdflatex” — running the bibliography pass and then re-running — is expressed as one recipe.
With no configuration, the extension uses its built-in default recipes. The first is a lone latexmk, and that is the intended default (when latex-workshop.latex.recipe.default is "first", the top recipe in the list is chosen; set it to "lastUsed" to remember the recipe you last picked). Because latexmk inspects dependencies and re-runs exactly as many times as needed, you never have to count passes for cross-references, the table of contents, or the bibliography. The default latexmk tool is defined roughly like this:
{
"name": "latexmk",
"command": "latexmk",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"-pdf",
"-outdir=%OUTDIR%",
"%DOC%"
],
"env": {}
}Reading the arguments: -synctex=1 emits the SyncTeX data discussed below; -interaction=nonstopmode runs straight through instead of halting for input on an error; -file-line-error prints errors as “file:line: message,” making it easy to jump to the offending spot. -pdf tells latexmk to produce PDF directly via pdfLaTeX. %OUTDIR% expands to your outDir, and %DOC% to the root file’s path without its extension (other placeholders include %DOCFILE% = filename without extension and %DIR% = the root’s directory).
The default recipes also include engine variants latexmk (lualatex) and latexmk (xelatex), plus latexmk (latexmkrc), which runs latexmk %DOC% with no extra arguments and defers everything to a .latexmkrc. For Japanese, that “put it all in .latexmkrc” approach is the cleanest. Drop a .latexmkrc at the project root and name the engine and converter. Here is an upLaTeX + dvipdfmx setup — the classic combination for Japanese papers in the sciences:
$latex = 'uplatex -synctex=1 -interaction=nonstopmode -file-line-error %O %S';
$bibtex = 'upbibtex %O %B';
$biber = 'biber --bblencoding=utf8 -u -U --output_safechars %O %S';
$makeindex = 'upmendex %O -o %D %S';
$dvipdf = 'dvipdfmx %O -o %D %S';
$pdf_mode = 3;
$max_repeat = 5;In essence you assign uplatex to $latex, dvipdfmx to $dvipdf, and set $pdf_mode = 3 to choose the “build a DVI, then convert to PDF with dvipdfmx” path ($pdf_mode = 1 is pdfLaTeX directly, 4 is LuaLaTeX). The index goes through upmendex and the bibliography through upbibtex, which handles Japanese well. %S, %O, and %D are latexmk’s placeholders for the source, options, and output file. Now, on the VS Code side, you simply pick the latexmk (latexmkrc) recipe and never encode the engine choice in settings.json.
If you would rather keep everything in settings.json without a .latexmkrc, define your own tool and recipe and put the Japanese recipe first. Here is a self-contained example for typesetting Japanese with LuaLaTeX (which sets Japanese via luatexja/ltjsclasses, needing neither a .latexmkrc nor dvipdfmx):
{
"latex-workshop.latex.tools": [
{
"name": "lualatexmk",
"command": "latexmk",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"-lualatex",
"-outdir=%OUTDIR%",
"%DOC%"
],
"env": {}
}
],
"latex-workshop.latex.recipes": [
{
"name": "lualatexmk",
"tools": ["lualatexmk"]
}
],
"latex-workshop.latex.outDir": "%DIR%/out",
"latex-workshop.latex.autoBuild.run": "onSave"
}You can also put magic comments like % !TEX program = ... or % !TEX root = ... at the top of a file, and LaTeX Workshop honors them (disable via latex-workshop.latex.build.enableMagicComments). The recipe system is the recommended path today; % !TEX root earns its keep in multi-file projects, when you want to compile the main document while editing an included sub-file.
Pinning the root file
In a multi-file project, if LaTeX Workshop guesses wrong, it may try to compile the child file you are editing directly. The extension infers the root by looking for \documentclass, \begin{document}, and \input/\include relationships, but for thesis-sized projects with many chapter files, explicit direction is steadier.
% !TEX root = ../main.tex
\section{実験方法}
この章だけを編集中でも、ビルドは main.tex から始めます。- Put
% !TEX root = ...at the top of child files so the entry file is explicit. - Open the workspace at the project root containing
main.tex, not at an isolated chapter folder. - Manual recipe selection can override magic comments, so keep the everyday recipe name consistent across the team.
- If root selection keeps prompting, pin the policy in the project’s
.vscode/settings.json.
SyncTeX integration
SyncTeX records the correspondence between source lines and positions in the PDF (the -synctex=1 above writes that mapping into a .synctex.gz). It lets you keep your writing spot and the PDF view in sync, both ways. Using the built-in PDF viewer (viewer set to tab) is the smoothest, no-configuration path.
Forward search (source → PDF) jumps from your editing position to the matching spot in the PDF. The shortcut is Ctrl+Alt+J (on Mac, Cmd+Option+J); from the Command Palette it is “LaTeX Workshop: SyncTeX from cursor.” To run forward search automatically right after a build, set latex-workshop.synctex.afterBuild.enabled to true.
Inverse search (PDF → source) goes the other way, from a place in the PDF back to the matching source line. In the built-in tab viewer, Ctrl-click (Cmd-click on Mac) in the PDF moves the cursor to that line. The click style is set by latex-workshop.view.pdf.internal.synctex.keybinding, either ctrl-click (default) or double-click. Learn the forward/inverse pair together and you can hop to the right place instantly, even in a long document.
For SyncTeX in Japanese, two things suffice: pass -synctex=1 to $latex in your .latexmkrc (already done in the example above), and know that even via DVI ($pdf_mode = 3), upLaTeX + dvipdfmx carries the SyncTeX data through. SyncTeX with an external viewer (latex-workshop.view.pdf.external.synctex.*) needs more configuration, so the built-in tab is the recommended place to start.