Skip to content

About

Skyrim SE/AE SKSE plugin starter template (CommonLibSSE-NG, CMake, vcpkg, Linux cross-compile)

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

ExampleMod

A starter template for Skyrim Special Edition / Anniversary Edition SKSE plugins using CommonLibSSE-NG, CMake, and vcpkg.

Supports building on Linux (cross-compilation via clang-cl + xwin) and Windows (MSVC).


Requirements

Installation

Mod manager (recommended):

  1. Install the requirements above.
  2. Install ExampleMod via your mod manager.
  3. Launch Skyrim via SKSE.

Manual:

  1. Install the requirements above.
  2. Copy ExampleMod.dll to Data\SKSE\Plugins\.
  3. Launch Skyrim via SKSE.

Compatibility

  • Compatible with Skyrim SE, AE, and VR.
  • No ESP/ESL required.

What the Starter Plugin Does

When loaded by Skyrim the plugin:

  1. Writes a log to Data/SKSE/Plugins/ExampleMod.log via spdlog.
  2. Hooks kDataLoaded (fires once all game data is loaded).
  3. Prints to the in-game console (~ key): [ExampleMod] Loaded successfully!

Development

Prerequisites

All platforms

Linux

  • LLVM/Clang (provides clang-cl, lld-link, llvm-lib, llvm-rc, llvm-mt)
  • xwin — downloads the real Windows SDK and MSVC CRT headers/libs
  • Ninja
# Arch / CachyOS
sudo pacman -S clang lld llvm ninja

# Install xwin (requires Rust/cargo)
cargo install xwin

# Fetch Windows SDK + MSVC CRT headers to ~/.xwin  (one-time, ~700 MB)
xwin splat --output ~/.xwin

Note: On first configure, cmake/toolchains/clang-cl-cross.cmake creates TitleCase symlinks inside your xwin installation, e.g.:

~/.xwin/sdk/lib/um/x86_64/Advapi32.lib  ->  advapi32.lib

lld-link is case-sensitive but CommonLibSSE-NG references libs with mixed-case names. The originals are untouched.

Windows


Getting Started

1. Create your repo from the template

With the GitHub CLI, create your own repo from the template and clone it with submodules:

# Pick visibility: --public (free GitHub Actions) or --private
gh repo create your-org/your-mod --template codepuncher/CommonLibSSE-NG-template --public
gh repo clone your-org/your-mod -- --recurse-submodules
cd your-mod

Or click "Use this template" on GitHub, then clone your new repo with submodules:

git clone --recurse-submodules https://github.com/your-org/your-mod.git
cd your-mod

The --recurse-submodules flag (or -- --recurse-submodules for gh repo clone) is required: the build needs the vcpkg and CommonLibSSE-NG submodules. If you cloned without it, run git submodule update --init --recursive.

2. Set your mod name and author

For a repo created from the template, the Template Setup workflow (setup.yml) renames the ExampleMod and Author placeholders, deriving them from the repo name and owner, commits the result, and removes itself. It can run automatically when the repo is created; if it hasn't, trigger it from the Actions tab ("Template Setup" > "Run workflow"). Once it has run, git pull to get the renamed sources.

Prefer to rename locally, or cloned the template directly? Run the init script instead. It replaces the placeholders, initialises the submodules (CommonLibSSE-NG + vcpkg), bootstraps vcpkg, and copies .env.example to .env.

Linux — run interactively or pass arguments directly:

./scripts/init.sh
# or:
./scripts/init.sh "AuthorName" "ModName"

Windows (PowerShell):

.\scripts\init.ps1
# or:
.\scripts\init.ps1 "AuthorName" "ModName"

3. Configure deploy path

Copy .env.example to .env if you don't have one yet (the init script does this for you), then set SKYRIM_MODS_FOLDER to your mod manager's staging folder:

# Vortex (Linux, Steam):
SKYRIM_MODS_FOLDER=$HOME/.local/share/Steam/steamapps/common/Vortex Mods/skyrimse

# MO2 (Linux):
# SKYRIM_MODS_FOLDER=$HOME/MO2/mods

4. Build

./scripts/build.sh
# or directly:
cmake --preset release-linux
cmake --build --preset release-linux

The DLL lands in build/release-linux/ExampleMod.dll.

Deploy to mod manager
./scripts/deploy.sh
# or directly (deploy.sh sources .env for you; cmake does not):
source .env && cmake --workflow --preset deploy

This configures, builds, and copies ExampleMod.dll + ExampleMod.pdb directly into:

$SKYRIM_MODS_FOLDER/ExampleMod/SKSE/Plugins/

Vortex will detect the new mod folder automatically. Enable it in Vortex, then launch Skyrim.

On subsequent builds (no config change needed):

./scripts/deploy.sh
Windows (MSVC)
cmake --preset release-windows
cmake --build --preset release-windows

Run these from a Developer Command Prompt for VS (or after sourcing vcvars64.bat) so cl.exe and the Windows SDK are on PATH. The preset uses the Ninja generator, which builds with whatever MSVC toolset the environment provides.

The DLL lands in build/msvc/ExampleMod.dll.

5. Running tests

Unit tests build without CommonLibSSE, so they run as a native executable. Two presets are available:

  • Linux (test-linux) uses the system Catch2 3 package. Install it with sudo pacman -S catch2 on Arch/CachyOS, or your distribution's equivalent.
  • Windows (test-windows) uses Catch2 from vcpkg.
cmake --preset test-linux
cmake --build --preset test-linux
ctest --preset test-linux

Tests live in test/ and use Catch2. Only pure-logic code (no RE::/SKSE:: APIs) can be tested this way. See src/Utils.h and test/ExampleTests.cpp for the pattern.


Git Hooks (Lefthook)

Prerequisites:

  • go install github.com/evilmartians/lefthook@latest
  • clang-format (part of LLVM — already required for development)
  • clang-tidy (part of LLVM — already required for development)
  • cmake-format (sudo pacman -S cmake-format on Arch/CachyOS; pip install cmakelang elsewhere)
  • shellcheck (sudo pacman -S shellcheck on Arch/CachyOS)
lefthook install

Editor Setup (clangd / Neovim)

CMake writes compile_commands.json to the build directory automatically. Copy or symlink it to the project root so clangd picks it up:

# After configuring:
ln -sf build/release-linux/compile_commands.json compile_commands.json

The .clangd file already sets --target=x86_64-pc-windows-msvc so clangd resolves Windows headers correctly on Linux.

Recommended Neovim plugins: nvim-lspconfig with clangd, and clangd_extensions.nvim.


Updating CommonLibSSE-NG

The script pins the submodule to a release tag (v*) on the ng branch and stages it. Without an argument it picks the latest tag:

./scripts/update.sh          # latest release tag
./scripts/update.sh v10.1.0  # a specific tag
git commit -m "chore(deps): update CommonLibSSE-NG to v10.1.0"

Nexus Mods Page

The <!-- nexus:start/end --> block at the top of README.md is the source of truth for Requirements, Installation, and Compatibility. docs/nexus-page.md holds the rest of the BBCode page (overview, tagline, credits).

To update the Nexus page:

  1. Edit Requirements/Installation/Compatibility inside the <!-- nexus:start/end --> block in README.md.
  2. Edit overview, tagline, and credits directly in docs/nexus-page.md.

    Do not edit the <!-- generated:start/end --> block in docs/nexus-page.md — it is overwritten every time the script runs.

  3. Generate the combined BBCode output:
python3 scripts/generate-nexus-page.py

# Or copy straight to the clipboard (wl-copy, xclip, xsel or pbcopy):
python3 scripts/generate-nexus-page.py --copy
  1. Paste the output into the Nexus Mods page editor.

CI

Workflow Trigger What it does
setup.yml First push in a repo created from this template Renames placeholders using the repo name, then self-deletes
ci.yml PRs to main touching src/, test/, cmake/, vcpkg.json, CMakeLists.txt, CMakePresets.json clang-format (ubuntu) → test-linux and build-linux (ubuntu) and test-windows + build-windows + clang-tidy (windows, parallel)
release.yml Push of a v* tag Builds, packages via scripts/package.sh, publishes a GitHub Release with zip + PDB
nexus-upload.yml Auto-triggered via workflow_run once release.yml completes, or manual workflow_dispatch Downloads release zip, generates cliff release notes, uploads to Nexus Mods
lint.yml PRs touching scripts/, README.md, or docs/ Runs shellcheck on shell scripts, plus dprint formatting and Vale prose checks on Markdown
pr-title.yml PR opened/edited/reopened/synchronize Checks PR title follows Conventional Commits (feat, fix, chore, refactor)

Nexus Mods Upload

nexus-upload.yml runs once release.yml completes, after approval in the nexus environment. It can also be run manually via workflow_dispatch with a version input. The one-time setup (environment, secrets, and variables) is in docs/RELEASING.md.


License

Copyright (c) 2026 ExampleMod Contributors. Licensed under the GNU GPL v3.0 or later; see LICENSE. CommonLibSSE-NG is also GPL-3.0-or-later, so mods built from this template are distributed under the same terms.

About

Skyrim SE/AE SKSE plugin starter template (CommonLibSSE-NG, CMake, vcpkg, Linux cross-compile)

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages