Zettlr Setup and Developer Guide (macOS, Windows, Linux)

6月28日 Published inNote-taking tool

Zettlr is a versatile open-source writing toolkit designed for plain-text editing, academic research, and knowledge management. It provides native support for Markdown editing and powerful full-text search as standard features.

The application is built to adapt to diverse writing styles. Its search engine is both fast and precise, while its export options are flexible enough to integrate with the specific publishing pipelines required by academic institutions or professional employers. Zettlr handles the technical complexities so you can focus entirely on your writing.

Installing the application is simple. Users can download the latest release for their specific operating system. Zettlr supports macOS, Windows, and most Linux distributions via Debian and Fedora packages, as well as AppImages. Both 64-bit and ARM installers (including Apple Silicon for macOS) are available on the official website and GitHub. Note that 32-bit systems are no longer supported.

Getting Started

Once the application is installed, the official documentation provides a comprehensive overview of its features. If you prefer to explore the interface manually, the included quick-start guide is an excellent entry point.

Contributing Code

Zettlr is an Electron-based application. Before you begin development, ensure your environment meets the following requirements:

  • Node.js: Version 20 (lts/iron) or higher is required. You can verify your version by running node -v.
  • Yarn: This project uses Yarn for package management. Because the repository does not include a package-lock.json and many internal scripts are Yarn-dependent, you should install it globally using npm install -g yarn or via Homebrew on macOS.

Windows users are encouraged to install the Windows Subsystem for Linux (WSL), as it simplifies many of the development steps.

Several command-line utilities are also necessary for the project's automation scripts:

  • cURL (used for the Pandoc download script)
  • unzip (used for the Pandoc download script)
  • jq (used for i18n processing)

Additionally, you must install the build toolchain specific to your operating system. Zettlr utilizes native C++ modules that must be compiled during the installation process:

  • macOS: Install the Xcode command-line tools via xcode-select --install.
  • Windows: Install the free Visual Studio Build Tools.
  • Linux: Install the standard C++ build tools (e.g., build-essential on Debian-based systems). Check your distribution’s documentation for specifics.

With these prerequisites met, clone the repository and install the project dependencies:

git clone https://github.com/Zettlr/Zettlr.git
cd Zettlr
yarn install --immutable

The --immutable flag ensures that Yarn adheres strictly to the versions defined in yarn.lock, preventing unexpected dependency updates.

The development environment uses Hot Module Replacement (HMR). When you edit the renderer code, wait for electron-forge to finish compiling and then press F5 to refresh. You can monitor HMR progress via the browser DevTools.

Development Commands

All available scripts are defined in package.json. Execute them from the repository root using the yarn prefix.

yarn start

This command is used to test your modifications. It launches Zettlr using a dedicated configuration and data directory, ensuring your primary Zettlr installation remains unaffected.

When running this for the first time, you must include the --clean flag. This flag populates the ./resources directory with test files, generates a test-config.yml in the project root, and initializes a fresh environment. You can modify test-config.yml later to persist your preferred testing settings.

Use the --clean flag whenever you need to reset the test directory, such as after deleting it or recloning the repository. Modifying test-config.yml also requires a reset.

To simulate a first-run experience without creating configuration files, use the --no-config flag. Other command-line switches, such as --clear-cache, are forwarded directly to the child process.

Note: The initial execution requires the --clean flag to set up the necessary directory structure.

yarn package

This bundles the application into a runnable format without creating a full installer. Running the command without arguments will package the app for your current platform and architecture. To target a specific build, use one of the following suffixes:

  • package:mac-x64 (Intel Macs)
  • package:mac-arm (Apple Silicon)
  • package:win-x64 (Intel Windows)
  • package:linux-x64 (Intel Linux)
  • package:linux-arm (ARM Linux)

The compiled app bundle will be located in the ./out directory.

Important: This command skips TypeScript type-checking to improve build speed. It is recommended to run lint first to ensure there are no errors.

yarn release:{platform-arch}

This command packages the application and wraps it in a platform-specific installer. The {platform-arch} must be one of the following:

  • release:mac-x64
  • release:mac-arm
  • release:win-x64
  • release:linux-x64
  • release:linux-arm

Installers are generated in the ./release directory.

Note: While you can use package without a suffix for local testing, generating a release bundle requires an explicit platform target. This ensures electron-builder excludes development dependencies from the app.asar file, preventing unnecessary bloat.

yarn csl:refresh

This script downloads the Citation Style Language (CSL) files included with Zettlr and places them in static/csl-locales and static/csl-styles.

Note: These files are updated via an automated workflow. Do not manually commit updated CSL files to the repository; they are automatically synchronized during git fetch.

yarn lint:code

This runs ESLint across the entire codebase. While editors like VS Code typically lint open files in real-time, this command performs a comprehensive check of all files.

yarn lint:types

This executes the TypeScript type checker via vue-tsc for the entire project.

yarn lint

This combines lint:code and lint:types. It verifies that your code adheres to established style guidelines and is free of type errors. You should always run this command before submitting a pull request.

Note: Automated checks run this command on every PR to maintain code consistency.

yarn lint:po

This parses the translation files in static/lang to ensure they are readable by the application. It utilizes Zettlr’s internal gettext parser, so a system-level gettext installation is not required.

Note: This is triggered automatically on pull requests that modify *.po files.

yarn shortcut:install

This creates a .desktop file on Linux systems, allowing you to launch your source-compiled version of Zettlr conveniently. If you pull new changes, simply run package again to update the build.

Warning: Use caution when running code compiled from the latest develop branch. However, this shortcut is very useful for frequent contributors.

yarn shortcut:uninstall

This removes the .desktop file generated by shortcut:install.

Note: You do not need to reinstall the shortcut after every recompile—just restart the app. Reinstallation is only necessary if the template (scripts/assets/zettlr-dev.desktop) is updated.

yarn test

This executes the unit tests located in ./test. Run this before submitting a pull request to catch regressions. Tests are also run automatically via CI for every commit.

yarn test-gui

Deprecated. This is currently an alias for yarn start. Please use yarn start instead.

Modules vs. Service Providers

Zettlr differentiates between "modules" and "service providers." Service providers run within the main process, operate autonomously, and provide global functionality to the entire application. In contrast, modules—such as importers and exporters—are only initialized when triggered by specific user actions.

Application Lifecycle

Startup sequence:

  1. The process begins by executing source/main.ts.
  2. Environment checks are performed via source/app/lifecycle.ts::bootApplication.
  3. Service providers are initialized in source/app/lifecycle.ts::bootApplication.
  4. The main application is booted via source/main/zettlr.ts.
  5. The file tree and documents are loaded into memory.
  6. The main window is rendered and displayed.

Shutdown sequence:

  1. All secondary windows are closed.
  2. The application attempts to close the main window.
  3. The main application shuts down via source/main/zettlr.ts::shutdown.
  4. Service providers are terminated in source/app/lifecycle.ts::shutdownApplication.
  5. The process exits.

Development mode (yarn start):

  1. Electron Forge compiles the main process and each renderer process independently using TypeScript and webpack.
  2. Compiled code is stored in the webpack directory, with constants updated in the window manager’s creation methods.
  3. Dev servers are launched to support HMR, and the application is initialized.

Building for production:

  1. Electron Forge compiles the code as it does in development mode.
  2. Instead of launching the app, it packages the code into an executable bundle.
  3. Electron Builder takes these bundles and creates platform-specific installers (such as DMG, Windows EXE, or Linux DEB/RPM packages).

Packaged applications are found in ./out, while final installers are located in ./release.

Command-Line Switches

The Zettlr binary supports several optional flags.

--launch-minimized

Launches Zettlr without opening the main window, which is ideal for systems configured to start the app on login. The application remains active in the system tray.

This flag automatically enables the system.leaveAppRunning setting, as the tray icon must remain active for the app to stay open.

Note: This flag has no effect on Linux environments that do not support system trays.

--clear-cache

Clears the cache of the filesystem abstraction layer upon startup. This is useful if the file tree is displaying outdated information or if you suspect the local cache has become corrupted.