A practical guide for authors who want to build, package, list, and support a CHIM server plugin for Skyrim. It covers when you need a plugin at all, how to write a first one, how Plugin Manager finds and installs it, and how to describe it so players can install and report problems.
A CHIM server plugin is PHP code that runs inside HerikaServer from its own folder under HerikaServer/ext/<name>. It extends CHIM without editing the core server. Typical uses are:
This guide is for CHIM with Skyrim and HerikaServer. Stobe and Dialectic have their own servers and are not covered here.
Related references
Maintained example plugins
Many CHIM integrations do not need a server plugin. Pick the smallest route that does the job.
Data/CHIMShip CSV files inside your Skyrim mod. CHIM uploads them to the server automatically when the game starts. See Custom CHIM Data Mods for the format.
_bios.csv: NPC biographies._oghma.csv: lore and knowledge entries._dynamicoghma.csv: knowledge that changes as quests progress._descriptions.csv: descriptions for items and other content._actions.csv: action definitions.
An _actions.csv row defines what the AI can call. It does not, by itself, make anything happen in the game. Gameplay still needs code that performs the action, unless the row uses a simple server-side script proxy.
Use a server plugin when you need to change how HerikaServer behaves: adding prompt context, reacting to requests, storing your own data, serving a plugin page, or talking to another service.
Use game-side code when something must change inside Skyrim, such as moving an NPC, giving an item, or reading another mod's state. A Papyrus script or SKSE plugin carries out the command and reports the result back to CHIM. Many integrations combine this with an actions CSV and, optionally, a server plugin.
HerikaServer/ext folder or inside a HerikaServer checkout.MyPlugin/
README.md what it does, requirements, settings, limits
context_pre.php a hook file (only the hooks you use)
index.php optional plugin page in the CHIM web interface
migrations/ optional ordered .sql files
001_initial.sql
HerikaServer loads a hook file by name from every folder under ext. You only create the hook files your plugin needs. These are the main request hooks:
| File | When it runs | Typical use |
|---|---|---|
|
Early, after core libraries load. |
Shared definitions, settings, and registrations. |
|
Near the start of request handling. |
Normalize or prepare incoming data. |
|
Before non-LLM event handling. |
Inspect the request before most events are processed. |
|
Before the system prompt is assembled. |
Add context or register prompt injections. |
|
After the system prompt is built. |
Adjust context once the main structure exists. |
|
After the response, around core post-request processing. |
Save data or queue follow-up work. |
Other hook files exist for prompt templates, history building, and JSON responses: prompts.php, dialogue_prompt.php, context_building.php, and json_response_custom.php. See Creating Plugins for each caller.
$gameRequest is available; read and write anything else through $GLOBALS.globals.php. Do not rely on a later hook having run.myplugin_, or a namespace.postrequest.php or a background worker.plugins schema for your tables, with ordered, idempotent files in migrations. Never edit a migration after release; add a new one.
This context_pre.php registers a short line at the bottom of the prompt. It does nothing on servers without the prompt injection API, and nothing when there is no state to report.
<?php
// ext/MyPlugin/context_pre.php
if (!function_exists('chimRegisterPromptInjection')) {
return;
}
if (!function_exists('myplugin_weather_line')) {
function myplugin_weather_line(string $slot, array $context): string
{
$weather = $GLOBALS['MYPLUGIN_WEATHER'] ?? '';
if (!is_string($weather) || $weather === '') {
return '';
}
return 'Current weather: ' . $weather . '.';
}
}
chimRegisterPromptInjection('prompt_bottom', 'myplugin.weather', 'myplugin_weather_line', 100);
chimRegisterPromptInjection() supports the character_bottom and prompt_bottom slots. Lower priority values render first, and empty results are skipped.
Lint every PHP file you changed:
php -l context_pre.php
# every PHP file in the plugin folder
find . -name '*.php' -print0 | xargs -0 -n1 php -l
Then test only what you changed, on a disposable server:
Plugin Manager finds plugins on GitHub. You do not need to submit a catalog entry, open a pull request, or write a manifest.
chim-plugin topic in the repository's GitHub About settings. The listing shows the repository owner, name, and description.chim-plugin.tar.gz (or chim-plugin.tar).Put the server files at the root of the archive. Do not wrap them in a folder.
chim-plugin.tar.gz
context_pre.php
index.php (optional plugin page)
lib/...
migrations/... (optional)
For example, from inside a folder that holds only the files to ship (no .git, logs, or development files):
tar -czf ../chim-plugin.tar.gz .
.. paths are rejected.index.php or index.html is at the archive root, Plugin Manager links to it as the plugin page.., _, +, or -. An update is offered whenever the latest tag differs from the installed tag, so semantic versioning is not required.ext/<repository name>. The repository name must be 1–64 letters, digits, _, ., or -, starting with a letter or digit.ext/<name>/manifest.json at install. A manifest.json inside your package is optional and cannot change the name, source, version, channels, branding, or plugin page.A Plugin Manager update replaces the whole plugin folder. Nothing inside it is preserved. Keep user settings and data in the database, or outside the plugin folder, if they must survive updates.
chim-plugin.tar.gz asset or an invalid repository name.
Plugins already published with a root manifest.json and channels keep working. Once a release includes chim-plugin.tar.gz, that asset replaces the old release channel and installed copies switch over in place. Branch channels such as Dev remain available. The HerikaServer documentation describes the legacy manifest fields.
A Skyrim mod can carry its matching server plugin so CHIM installs it on the connected server when the game starts. This uses a different format: a schema 4 ZIP or .dwpkg package with an outer manifest.json, a checksums.sha256 file, and the server files under server/. Its updater can preserve listed mutable_paths.
Do not mix the two formats, and choose one install and update route for each plugin. Follow the package contract and the CHIM-Custom packaging scripts.
If your plugin needs a Skyrim mod, ESP, Papyrus scripts, or SKSE DLL, players install that separately with their mod manager. Never put game DLLs or other game files in the server package.
Players get confused when a release page has several files and no instructions. Offer one route for the server plugin, and add a game-side download only if the plugin really needs one.
| File | Installed by | Notes |
|---|---|---|
|
Plugin Manager, from the GitHub release. |
Server files only. See Archive layout. |
|
CHIM, which sends it to the server when a save loads. |
Players do not unpack it. It goes inside the mod-manager archive under |
Mod-manager ZIP |
Mod Organizer 2, Vortex, or another mod manager. |
Holds game-side files, a bundled |
Source code archive |
Nobody. GitHub adds it automatically. |
Not an installer. Tell players to ignore it. |
.dwpkg in a mod-manager ZIP. A ZIP used only to carry the package needs no ESP, Papyrus scripts, or plugin slot.meta.ini. Including one with your version is helpful, but it only adds metadata. It does not make a wrongly structured archive work.A working action has three parts:
_actions.csv file.funcret message. Report failure as failure, so the AI does not describe something that did not happen.Read Action Editor for the CSV columns, dispatch types, and script proxy limits. The CHIM-NFF example shows a complete action row and Papyrus bridge.
Work to let plugins add their own Interact actions has been merged into the unstable branches of HerikaServer and CHIM. It lets a server plugin declare actions in interact_actions.php, and a Skyrim mod register Papyrus-handled actions.
Use this template for your README or release page so players know what they are installing.
# Plugin name
One-sentence description.
## What it does
- What changes in game or in the CHIM web interface.
## Requirements
- CHIM version:
- HerikaServer version:
- Required dependencies (Skyrim mods, SKSE plugins, services), with tested versions:
- Optional dependencies, and what works without them:
- Mod managers tested:
## Download and source
- Server plugin route (pick one): Plugin Manager (chim-plugin.tar.gz)
or .dwpkg bundled in the mod-manager ZIP
- Mod-manager ZIP (if any): direct link, and what is inside it
- Files to ignore: source code archives
- Source: link
## Install
1. Install and enable the mod-manager ZIP (if any).
2. Install the plugin from Plugin Manager (if that is the route).
3. Load a save with CHIM enabled, then check the plugin version.
## Settings
- Where to find them, what each one does, and how to turn features off.
## Extra model calls
- Which features call an LLM, which backend, rough cost, and fallback.
## Update and uninstall
- Updates replace the plugin folder. Note anything that is lost.
- How to remove the plugin and any game files.
- What stays in saves or stored data after uninstalling.
- How to roll back, and what to back up first.
## Known limits
- What it does not do, and known conflicts.
## Testing
- Lint: which files were checked.
- Install: clean install / upgrade tested on CHIM and HerikaServer versions.
- Independent testing: what someone other than the author checked.
- In game: what was actually tested in Skyrim, and what was not.
## Bug reports
- Where to report, and what to include (see below).
Be specific about testing. Passing php -l, installing on a server, and working in game are three different claims. Only state the ones you checked.
Plugin version:
CHIM version:
HerikaServer version:
Other relevant mods:
Install route and mod manager:
Steps to reproduce:
1.
2.
Expected result:
Actual result:
Relevant logs (remove API keys, tokens, and personal paths):
See Log Files for where CHIM and server logs are stored.
The chim-plugin topic is a community listing, not a review or an endorsement by Dwemer Dynamics. Installing a plugin runs its PHP code and database migrations with full server privileges. Players should install plugins only from authors they trust, and authors should keep their source public and their changes clearly described.