A local AI character chat app: manage character cards, prompt presets, and lorebooks (world info), then stream conversations with models in the browser. All data stays on disk for backup or sync.
English guide · 中文教程 · 中文说明
- Chunked chat storage — Conversations are stored as linked turn chunks on disk, so long chats stay manageable for backup and tools like Syncthing (avoid writing the same data dir from two machines at once).
- Readable session audit — Open an assistant message’s Audit panel to inspect prompt assembly, regex stages, and group-chat speaker picks when debug audit is on (guide).
- Native regex pipeline — User-level display / outgoing / persist rules, plus batch apply on history (guide).
- Drag-and-drop prompt groups — Prompt presets use groups and entries you can reorder by dragging, with clear injection / trigger controls (guide).
- Group chat speaker modes — Multi-segment turns: sequential, dice bidding, or LLM
[NEXT@], plus/@mentions that override the mode (guide). - Isolated API keys — Keys stay on the server (not exposed to the browser UI); list APIs return masked status, and reveal requires your login password.
- Plugin sandbox & host boundary — Plugins call models and disk through the host; browser plugins never hold plaintext keys. Optional server Worker sandbox for stronger isolation (guide).
- Conversation branches — Fork a storyline from a message without destroying the main line (same chapter).
Everyday “how do I…” steps live in the beginner manual.
- Node.js 22+ (nodejs.org LTS is fine; matches dependency requirements such as
vue-i18n) - A modern browser (Chrome, Edge, Firefox, etc.)
- On Windows, double-click
!_start.bat; on macOS / Linux, usestart.sh
Install Git first if needed. In a terminal:
First time — clone the repository
git clone https://github.com/vevan/arousalPub.git
cd arousalPubLater — pull the latest version (run inside the project folder)
cd arousalPub
git pullThen start the app as usual (!_start.bat / ./start.sh). After git pull, startup may auto-run npm install and rebuild when needed.
You can also download a ZIP from GitHub and extract it; ZIP installs do not get git pull updates — download a new ZIP or switch to git clone above.
Step-by-step for beginners: Install and start.
- Have the project folder ready (see §0 above, or unpack a ZIP).
- If you do not have
config.yamlyet, copyconfig.example.yamltoconfig.yaml(the app can also generate it from the example on first start). - Double-click
!_start.bat(Windows) or run./start.shin a terminal.
The first run installs dependencies automatically. After a git pull (or similar), if package-lock.json or a workspace package.json changed, startup also runs npm install as needed. If build artifacts are missing, the app compiles them before starting. Keep the startup window open — closing it stops the service.
When startup succeeds, the terminal shows a clickable URL, typically:
http://localhost:6633/
The port comes from serverPort in config.yaml (example default: 6633).
- The first visit walks you through creating an admin account (username and password).
- After login you can check “Set as default user” so this machine can enter without a password next time (data still lives on disk).
- Change the password or register more users under Settings → Account.
| Method | When to use |
|---|---|
!_start.bat / start.sh |
Everyday use (recommended) |
| Docker | NAS / Linux servers and other container hosts |
npm run dev |
Local development (two ports + hot reload) |
Before !_start.bat launches, there is a startCountdownSeconds countdown (default 5 seconds; set in config.yaml; 0 skips it).
- No key: after the countdown, start quickly with the existing build.
- Press
B: rebuild frontend and backend, then start (use this after changing app code). - Press Space: skip the countdown and start immediately (no rebuild).
If web/dist or server/dist is missing, or the current git revision differs from the last build record (for example after git pull), a rebuild runs automatically. When dependency manifests change, npm install runs before the build (usually no need to run it by hand). If you edited code locally without committing, press B during the countdown to force a rebuild.
Requires Docker and Docker Compose.
docker compose up -d --buildUse --build on first run and after code updates. If the local image does not exist yet, Compose builds it; it does not pull arousalpub:local from Docker Hub (that tag is local-only).
Open http://127.0.0.1:6633/ in a browser (not the dev webPort 6699). To change the host port: AROUSALPUB_PORT=8080 docker compose up -d --build
- Confirm the URL is
http://127.0.0.1:6633/(includehttp://; do not use https; do not use 6699). - Run
docker compose ps— you should see0.0.0.0:6633->6633/tcpand status Up (healthy). - If
!_start.batis already running locally, it may hold port 6633: close that window, thendocker compose up -d. - Check logs:
docker compose logs -f— look forstatic web:andlistening on. - Quick check:
curl http://127.0.0.1:6633/healthshould return{"ok":true}.
By default, project ./data is mounted at /data in the container (chats, characters, API keys, etc.), same path layout as local !_start.bat use of data/ — easy to back up or sync with Syncthing.
Do not let multiple container instances read/write the same data directory at once.
| Command | Description |
|---|---|
docker compose logs -f |
Follow logs |
docker compose down |
Stop and remove the container |
docker compose up -d --build |
Rebuild and start after image updates |
The image ships with frontend and backend prebuilt; it does not run git pull or a local rebuild on container start. To upgrade, run docker compose up -d --build again or pull a new image.
Optional environment variables (set under environment in docker-compose.yml):
| Variable | Description |
|---|---|
JWT_SECRET |
JWT secret (≥16 characters); if unset, first start writes /data/.jwt-secret |
DATA_DIR |
Data directory, default /data |
PORT |
Listen port, default 6633 |
- On the home page, “New chat”: pick a user persona card and main character card; optionally set a title and select lorebooks.
- In a chat, type and send; supports streaming replies, reasoning display, regenerate, and multi-version swipes.
- The sidebar can bind/switch characters and lorebooks, and adjust prompt / memory options for this chat.
Top bar “Characters”: import SillyTavern PNG/JSON, create or edit cards, export PNG/JSON. Session bindings are set in the chat sidebar.
Top bar “Prompts”: manage presets and grouped entries (injection order and triggers); a chat can bind one preset.
Top bar “Lorebooks”: organize by lorebook → group → entry; select which lorebooks to inject when creating a chat or in the sidebar.
Top bar “Settings”:
- Connection / API: OpenAI-compatible base URL, key, model, etc.
- Chat history / lorebooks / vector recall: history depth, lorebook recursion, long-term memory and Embeddings API, hybrid tokenization, etc. (vector options are under the “Vector recall” tab).
- Language: switch UI between Chinese and English.
- Theme, font size, and other display options.
API keys live in the local data directory, not in public browser storage.
Common keys:
| Key | Description |
|---|---|
dataDir |
Data directory, default ./data |
serverPort |
Browser port after start (!_start.bat) |
startCountdownSeconds |
Countdown seconds before start; 0 = no wait |
authIdleMinutes, etc. |
Login session timeout (optional) |
Full comments are in config.example.yaml.
Chats, characters, prompts, lorebooks, API config, and related files all live under dataDir (default project data/), one subdirectory per user.
- Backup: copy the whole
data/directory. - Restore on another machine: install the app, then replace with your backed-up
data/. - Sync (e.g. Syncthing): avoid two machines writing the same data directory at the same time, or you risk conflicts.
Path details: data/README.md (中文).
Page will not open
- Confirm the startup window is still running and the port is free.
- Check that
config.yamlserverPortmatches the URL in the browser.
UI did not update after code changes
- Restart with
!_start.batand pressBduring the countdown to force a rebuild.
Forgot password
- Adjust user records under the data directory, or delete that user’s data and register again (that user’s data is lost). Ops details are in
DOC/devNotes/.
JWT in production
- First
!_start.batrun can write a secret todata/.jwt-secret; you can also setjwtSecretinconfig.yaml(≥16 characters).
npm audit shows high severity / suggests --force
- End users only need
./start.sh/!_start.bat(ornpm start). You do not need to runnpm auditornpm audit fix --force. - Do not run
npm audit fix --force— it can jump major versions and break the install. - Current
mainpins patched@fastify/static,sharp, andvue-tsc. Aftergit pull+ a normal install,npm auditshould report 0 vulnerabilities. Older clones may still show stale advisories until you update. allow-scriptswarnings (esbuild / sharp install scripts) are normal for a Node app that compiles native/binary helpers; they are not the same as the audit CVEs above.
Architecture, APIs, and implementation notes: DOC/devNotes/. Project index: cursor.md. Beginner manual: EN · CN. Chinese overview: DOC/README.zh.md. Docs hub: DOC/README.md.
Dev mode:
npm install
npm run devnpm run dev also starts scripts/watch-plugins.mjs in parallel: it watches repo plugins/*/src and rebuilds only when sources are newer than dist (avoids false positives on Windows watchers). Debug: PLUGIN_WATCH_DEBUG=1.
Open the webPort from config.yaml in the browser (default differs from serverPort).
Special thanks to the following pioneers and projects for inspiration:
- SillyTavern — SillyTavern team
- SillyTavern Memory Books (STMB) — aikohanasaki
- SillyTavern WTracker — bmen25124
- Guided Generations — Samueras
- All But This Swipe — Avilnetro