diff --git a/docs/getting-started/advanced/.pages b/docs/getting-started/advanced/.pages
index 8769c5ce..c5f42df8 100644
--- a/docs/getting-started/advanced/.pages
+++ b/docs/getting-started/advanced/.pages
@@ -1,4 +1,5 @@
nav:
- change-host-and-port.md
- debug-logging.md
+ - prompt-logging.md
- ...
\ No newline at end of file
diff --git a/docs/getting-started/advanced/change-host-and-port.md b/docs/getting-started/advanced/change-host-and-port.md
index 79482589..1325cf5d 100644
--- a/docs/getting-started/advanced/change-host-and-port.md
+++ b/docs/getting-started/advanced/change-host-and-port.md
@@ -1,5 +1,42 @@
# Changing host and port
+Talemate reads its listen host and port from environment variables, with CLI flags available as an explicit override. The same variables are consumed by the start scripts on Linux and Windows and by the Docker images.
+
+## Environment variables
+
+| Variable | Default | CLI flag | Purpose |
+|----------|---------|----------|---------|
+| `TALEMATE_BACKEND_HOST` | `localhost` | `--host` | Interface the backend websocket server binds to. |
+| `TALEMATE_BACKEND_PORT` | `5050` | `--port` | Port the backend websocket server binds to. |
+| `TALEMATE_FRONTEND_HOST` | `localhost` | `--frontend-host` | Interface the frontend web server binds to. |
+| `TALEMATE_FRONTEND_PORT` | `8082` | `--frontend-port` | Port the frontend web server binds to. |
+
+!!! info "CLI flags override the environment"
+ When both are provided, the explicit CLI flag wins over the matching environment variable. If neither is set, the default in the table above is used. Invalid port values (non-numeric or outside `1–65535`) cause Talemate to exit with an error at startup.
+
+In Docker the host variables default to `0.0.0.0` inside the container (set by the image) so the ports are reachable from your browser. You normally only need to change the port variables when running in Docker.
+
+## Upgrading from 0.36.x
+
+Two changes in **0.37.0** affect anyone who set host/port values or kept bookmarks to the UI:
+
+!!! warning "Frontend default port changed from 8080 to 8082"
+ To avoid a clash with llama.cpp (`llama-server` defaults to 8080) the frontend now listens on port `8082` by default. Update any bookmarks, reverse-proxy configs, and firewall rules that pointed at `http://localhost:8080`.
+
+ To keep the previous default, set `TALEMATE_FRONTEND_PORT=8080` before launching:
+
+ ```bash
+ TALEMATE_FRONTEND_PORT=8080 ./start.sh
+ ```
+
+!!! warning "Docker Compose variables renamed"
+ The Docker Compose variables have been prefixed with `TALEMATE_`:
+
+ - `FRONTEND_PORT` → `TALEMATE_FRONTEND_PORT`
+ - `BACKEND_PORT` → `TALEMATE_BACKEND_PORT`
+
+ If you have either variable set in a `.env` file or your shell, rename it before `docker compose up`. The new variables control **both** the host port that Docker publishes and the port uvicorn binds inside the container, so the two stay in sync automatically.
+
## Backend
By default, the backend listens on `localhost:5050`.
diff --git a/docs/getting-started/advanced/prompt-logging.md b/docs/getting-started/advanced/prompt-logging.md
new file mode 100644
index 00000000..867eeccc
--- /dev/null
+++ b/docs/getting-started/advanced/prompt-logging.md
@@ -0,0 +1,117 @@
+# Prompt Logging
+
+Talemate can write every prompt it sends to a language model — together with the model's response and a bundle of metadata — to a JSON Lines file on disk. This is intended for debugging prompt issues, comparing behaviour across clients, or feeding collected prompts into offline analysis.
+
+Prompt logging is **off by default** and is enabled with a single environment variable.
+
+!!! warning "Prompt logs may contain sensitive scene content"
+ The log stores full prompt text and full model responses, which include character cards, world info, dialogue history, and anything else that was part of the prompt. Treat `logs/prompt_log.jsonl` as sensitive. Do not commit it, share it, or paste excerpts without review.
+
+## Enabling
+
+Set `TALEMATE_LOG_PROMPTS=1` before starting the server. Any truthy value enables logging (Talemate checks for the variable being set to a non-empty string).
+
+#### :material-linux: Linux
+
+Prefix the start command:
+
+```bash
+TALEMATE_LOG_PROMPTS=1 ./start.sh
+```
+
+Or when running manually:
+
+```bash
+TALEMATE_LOG_PROMPTS=1 uv run src/talemate/server/run.py runserver --host 0.0.0.0 --port 5050
+```
+
+#### :material-microsoft-windows: Windows
+
+```batch
+SET TALEMATE_LOG_PROMPTS=1
+start.bat
+```
+
+## Disabling
+
+Unset the variable (or set it to an empty string) and restart Talemate:
+
+#### :material-linux: Linux
+
+```bash
+unset TALEMATE_LOG_PROMPTS
+./start.sh
+```
+
+#### :material-microsoft-windows: Windows
+
+```batch
+SET TALEMATE_LOG_PROMPTS=
+start.bat
+```
+
+## Output file
+
+| Setting | Value |
+|---------|-------|
+| Path | `logs/prompt_log.jsonl` in the Talemate project root |
+| Format | JSON Lines (one JSON object per line) |
+| Write mode | Append — never truncated or rotated |
+| Flush | Every record is flushed immediately, so partial runs are not lost |
+
+The file is opened the first time a prompt is logged after startup and kept open for the lifetime of the process. It is **never rotated or truncated by Talemate**, so the file will keep growing as long as the variable is set. If you only need a short capture, enable the variable, reproduce the problem, disable it, and delete or move the file afterwards.
+
+!!! info "`logs/prompt_log.jsonl` vs `logs/prompt_log.json`"
+ The JSON-Lines file described here is written by the server while it runs.
+
+ The similarly named `logs/prompt_log.json` is a separate, one-shot snapshot produced by the **Export** button in the Debug Tools → Prompts tab and is independent of this environment variable.
+
+## Record schema
+
+Each line in `prompt_log.jsonl` is a single JSON object with the fields below. Field order inside the object is not guaranteed.
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `kind` | string | Prompt kind identifier (e.g. `conversation`, `narrate_scene`, `summarize`). Corresponds to the template/system-prompt kind used for the call. |
+| `prompt` | string | The full finalized prompt text sent to the model, after template rendering and any client-side formatting. |
+| `response` | string | The full model response text, after stop-string trimming and smart-quote normalization. |
+| `prompt_tokens` | int | Prompt token count. Uses the client's own counter unless the backend returned an explicit prompt-token count, in which case that value is preferred. |
+| `response_tokens` | int | Response token count. Uses the backend-reported count when available, otherwise the client's tokenizer. |
+| `client_name` | string | Name of the client that produced the prompt (as configured on the Clients screen). |
+| `client_type` | string | Client type identifier (e.g. `openai`, `anthropic`, `koboldcpp`). |
+| `time` | number | Wall-clock seconds spent on the generation, measured around the backend call. |
+| `agent_stack` | list of strings | The agent call stack at the time of the prompt, outermost first. The final entry is the agent that actually issued the call (e.g. `["director", "conversation"]`). Empty if no agent context was active. |
+| `generation_parameters` | object | Final generation parameters passed to the backend for this call (temperature, top-p, max tokens, etc. — contents vary by client type). |
+| `inference_preset` | string or null | Name of the active inference preset, if any. |
+| `preset_group` | string or null | Preset group the client is using, if any. |
+| `reasoning` | string or null | The extracted reasoning / thinking trace for this response, when the client supports reasoning tokens. |
+| `template_uid` | string or null | UID of the Jinja prompt template that produced the prompt. Useful for correlating a log line back to a specific template in the Prompt Manager. |
+
+The record is the same `PromptData` structure that Talemate emits over the websocket to populate the in-app [Debug Tools](../../user-guide/debug-tools.md#prompts) Prompts tab, so anything visible there is also in the log file.
+
+## Quick inspection
+
+Because each line is a self-contained JSON object, the file works well with standard JSON tools. A few examples:
+
+Pretty-print the last prompt:
+
+```bash
+tail -n 1 logs/prompt_log.jsonl | jq
+```
+
+Count prompts per agent (top of the stack):
+
+```bash
+jq -r '.agent_stack[-1] // "none"' logs/prompt_log.jsonl | sort | uniq -c
+```
+
+Extract only the prompts that took longer than five seconds:
+
+```bash
+jq 'select(.time > 5)' logs/prompt_log.jsonl
+```
+
+## Related
+
+- [Debug Logging](debug-logging.md) — enable `DEBUG`-level logging and error-log file output with `TALEMATE_DEBUG=1`.
+- [Debug Tools › Prompts](../../user-guide/debug-tools.md#prompts) — in-app viewer for the same prompt records, with a one-shot export button.
diff --git a/docs/user-guide/agents/director/chat.md b/docs/user-guide/agents/director/chat.md
index 3720b8c9..91760cc5 100644
--- a/docs/user-guide/agents/director/chat.md
+++ b/docs/user-guide/agents/director/chat.md
@@ -119,6 +119,18 @@ When rejected, the director acknowledges and waits for your next instruction:

+### Confirmation timeout
+
+!!! info "New in 0.37.0"
+
+Each confirmation card shows a countdown timer in the top-right corner. The number turns red when less than 30 seconds remain.
+
+
+
+If the timer runs out before you confirm or reject, the action is treated as rejected and the director will acknowledge and wait for your next instruction — the same behaviour as clicking **Reject**.
+
+The default timeout is **3 minutes**. You can change it (or disable it entirely) from the [Director Chat settings](/talemate/user-guide/agents/director/settings/#action-confirm-timeout).
+
## Enabling and Disabling Actions
The director has access to many different actions for querying information, making changes, and progressing your story. You can control which actions the director is allowed to use by enabling or disabling them through the Actions menu.
diff --git a/docs/user-guide/agents/director/index.md b/docs/user-guide/agents/director/index.md
index 9b8bdfc2..3a0d8ded 100644
--- a/docs/user-guide/agents/director/index.md
+++ b/docs/user-guide/agents/director/index.md
@@ -18,6 +18,12 @@ A conversational interface for interacting with the director directly. You can a
See the [Director Chat](/talemate/user-guide/agents/director/chat) page for more information.
+### Director Planning
+
+Plans and autonomously generates a multi-beat scene arc from a short set of instructions. The director produces an outline, critiques it, and then executes each beat to generate the actual scene content.
+
+See the [Director Planning](/talemate/user-guide/agents/director/planning) page for more information.
+
### Dynamic Actions
Generates clickable choices for the user during scene progression. This allows you to make decisions that affect the scene or story without manually typing out your choice.
diff --git a/docs/user-guide/agents/director/planning.md b/docs/user-guide/agents/director/planning.md
new file mode 100644
index 00000000..795ed797
--- /dev/null
+++ b/docs/user-guide/agents/director/planning.md
@@ -0,0 +1,182 @@
+# Director Planning
+
+!!! info "New in 0.37.0"
+
+Director Planning lets the director break a goal into a task list, track progress against that list, and — depending on how the plan was created — optionally execute each task itself. Plans surface in the [Director Console](/talemate/user-guide/agents/director/chat) as a **Plan** banner above the chat, regardless of which flow created them.
+
+There are two distinct flows that create a plan:
+
+- **Autonomous planning during chat.** While you are talking to the director in a normal chat mode (Normal, Decisive, or No Spoilers), the director can decide on its own to build a short task list for work it is about to do. It ticks tasks off as it completes them using its other actions. The plan is a lightweight todo list, not an auto-executing beat queue.
+- **Generate long progress.** A dedicated dialog on the scene tool bar that creates a multi-beat scene arc and executes every beat sequentially in a fresh chat. Use this when you want to generate a chunk of story at once.
+
+Both flows use the same underlying plan schema and appear in the same Plan banner, but they differ in scope, what triggers them, and whether the director executes the plan automatically.
+
+!!! warning "Strong LLM recommended"
+ A strong language model (100B+ parameters) with reasoning enabled is highly recommended for either flow. Planning produces structured output and involves multiple generation steps — weaker models can produce malformed tasks, malformed beats, or repetitive prose. See [Reasoning Model Support](/talemate/user-guide/clients/reasoning/).
+
+## Planning during chat (autonomous)
+
+In **Normal**, **Decisive**, or **No Spoilers** director chat mode, the director has access to a `manage_plan` action that it can invoke on its own to:
+
+- Create a task list for work it is about to do.
+- Mark individual tasks as completed as it works through them.
+- Replace or delete the plan when its strategy changes.
+
+The director decides whether to create a plan based on your chat instructions. A single-action request (for example, "narrate the door opening") almost never triggers one; a multi-step request ("have the guards arrive, search the room, then find the note") typically does.
+
+You do not interact with the plan directly — it is the director's own scratchpad. As tasks are completed, the chips in the Plan banner update; when the director considers the plan finished, the banner status flips to **completed**. To abandon a planned direction, just give the director new instructions in the chat — it will typically replace or delete the plan on its next turn.
+
+!!! note "Todo list, not an execution queue"
+ Autonomous plans do not run beats automatically. Each task is satisfied when the director takes a separate action (directing the scene, querying context, narrating, and so on). This is the key difference from the Generate long progress flow below, where beats execute automatically and sequentially.
+
+## Generate long progress (manual)
+
+Use this flow when you want the director to both plan and execute a chunk of story in one go. The entry point is the **Generate long progress** item in the director section of the scene tool bar. Click the :material-bullhorn: director menu above the scene input and choose **Generate long progress**.
+
+
+
+This opens the Generate Long Progress dialog:
+
+
+
+### Scene instructions
+
+Describe what should happen in the scene. This is the seed for the whole arc — the director will use it to produce the outline. Be as brief or as detailed as you like; everything else on the dialog controls shape and pacing, not content.
+
+### Number of turns
+
+How many beats to plan. A beat is one unit of narration or dialogue in the outline. The default is 8, and the slider ranges from 3 to 24.
+
+### Dialogue ratio
+
+Target fraction of beats that should be dialogue versus narration. `40%` means roughly 40% of the beats will be dialogue and the rest will be narration, action, reveal, or transition. The slider moves in 10% steps.
+
+The default value comes from the agent-level **Dialogue beat ratio** setting (see [Settings](#settings) below) and can be changed per run.
+
+### Execution mode
+
+Two modes are available, toggled with the button group near the bottom of the dialog:
+
+#### :material-lightning-bolt: Expand
+
+Beats are expanded into prose in chunks. The director assigns each chunk an arc position (setup, rising action, climax, falling action) and pacing metadata, then generates the prose for multiple beats in a single pass. This is significantly faster than turn-by-turn execution and produces more cohesive cross-beat writing because the model sees several beats at once.
+
+#### :material-directions-fork: Turn by turn
+
+Each beat is executed individually through the narrator and conversation agents, the same way the director normally progresses the scene one message at a time. This is slower, but the director can adjust its strategy between beats — for example, if an earlier beat took the story in an unexpected direction.
+
+### Close the arc
+
+Controls how the planned arc ends.
+
+- **Off (default — continuation)**: the arc ends on a high-tension handoff moment so you can keep playing from where it leaves off.
+- **On (closed arc)**: the arc lands a full resolution, including a character choice and wind-down. Use this when you are writing a self-contained short story.
+
+This setting resets to continuation mode every time you open the dialog.
+
+### Outline critique
+
+When enabled, the director runs a critique pass on the generated outline before executing any beats. This helps catch weak pacing, redundant beats, or missing setups in the plan before time is spent generating prose.
+
+Enabled by default.
+
+### Expansion critique
+
+Only visible when **Expand** mode is selected. When enabled, the director runs a second critique pass over the expanded prose to fix cross-beat redundancy, intensity monotony, and repeated vocabulary. Adds roughly 10 seconds per generation.
+
+Enabled by default.
+
+### Warnings
+
+The dialog surfaces a few pre-flight checks:
+
+- **Narrator progress story length** — if the narrator's progress-story response length is below the recommended minimum (1024 tokens) the dialog offers a quick **Fix** button that jumps to the narrator's generation override settings.
+- **Missing acting instructions** — lists any active characters that do not have dialogue instructions set. The plan will still run, but those characters may produce weaker dialogue.
+- **Player characters** — planning may generate actions and dialogue for player-controlled characters. There is no way to exclude them from the arc.
+
+## What happens when you click Plan & Generate
+
+Clicking **Plan & Generate** does three things:
+
+1. Creates a new director chat in **Generate Arc** mode (or **Generate Arc (Expand)** mode, depending on your selection). Your scene instructions are inserted as the opening user message, and action confirmation is turned off for this chat so the flow runs end to end without prompts.
+2. Opens the [Director Console](/talemate/user-guide/agents/director/chat) so you can watch the flow run.
+3. Kicks off the planning pipeline: the director produces an outline, optionally critiques it, and then executes each beat.
+
+You can keep using the scene normally once the run has produced output — generated narration and dialogue are pushed to your scene feed as they are produced.
+
+## Watching a plan run
+
+Whenever a plan is active — whether it was created autonomously by the director or by the Generate Long Progress dialog — a **Plan** banner appears at the top of the Director Console chat with the current status, completed-task count, and a compact task list that windows to the active task:
+
+
+
+The banner statuses map to the planning pipeline:
+
+| Status | Meaning |
+|---|---|
+| `planning` | Director is producing the plan or outline. |
+| `ready` | Plan is built; tasks are available. |
+| `executing` | At least one task/beat is running. |
+| `completed` | All tasks are done. |
+| `cancelled` | The plan was stopped before finishing. |
+
+Each task in the banner has its own icon and status chip — pending, executing, completed, or skipped. Click the chevron at the top-right of the banner to collapse it; click the "N completed tasks" or "N more pending tasks" summaries to expand and show the whole list.
+
+In the Generate Long Progress flow the banner runs through `planning` → `ready` → `executing` → `completed` as the arc executes. In autonomous planning, the banner typically sits in `ready` while the director ticks tasks off one by one using its other actions.
+
+### Chat modes created by planning
+
+When the plan dialog creates a chat, the director-chat mode chip in the toolbar shows **Generate Arc** (:material-directions-fork:) or **Generate Arc (Expand)** (:material-lightning-bolt:), matching the execution mode you chose. These modes are also selectable from the mode menu if you want to convert an existing chat, though the usual entry point is the dialog.
+
+See [Director Chat](/talemate/user-guide/agents/director/chat#chat-modes) for the other available chat modes.
+
+## Settings
+
+The agent-level defaults for planning live under **Arc Generation** in the director's agent settings panel:
+
+
+
+##### Dialogue beat ratio
+
+Default target fraction of beats that are dialogue. Range `0.0`–`1.0`, step `0.1`. The plan dialog pre-fills its **Dialogue ratio** slider from this value.
+
+##### Expand chunk size
+
+Maximum number of beats bundled into one expansion call in Expand mode. Range `3`–`12`, default `5`. Larger chunks produce more cohesive prose across beats but consume more context per call.
+
+##### Outline critique
+
+When enabled, the critique pass on the outline runs by default. The plan dialog mirrors this into its **Outline critique** checkbox and you can override it per run.
+
+##### Expansion critique
+
+When enabled, the post-expansion critique pass runs by default in Expand mode. The plan dialog mirrors this into its **Expansion critique** checkbox and you can override it per run.
+
+## Manual scene direction turn
+
+!!! info "New in 0.37.0"
+
+The director menu in the scene tool bar also includes a **Scene direction turn** button that manually triggers one [Autonomous Scene Direction](/talemate/user-guide/agents/director/scene-direction) turn. It is useful when you have Scene Direction enabled but auto-progression turned off — you can step the director through the scene one turn at a time instead of letting it drive the game loop.
+
+
+
+- **Click** to run a single scene direction turn using your current settings and intentions.
+- **Ctrl+click** (Cmd+click on macOS) to open an instructions dialog. Whatever you type is inserted into the scene direction history as a one-off user direction before the turn executes, letting you nudge the director for just that turn without changing your scene-level instructions.
+
+The button is greyed out when Scene Direction is disabled in the [director agent settings](/talemate/user-guide/agents/director/scene-direction#enabling-scene-direction).
+
+## Troubleshooting
+
+### The plan stops or reports a malformed-output error
+
+Expand mode validates each chunk and retries up to three times if the model produces blocks with leaked tags. If all three attempts fail, the run stops with an error telling you the model is likely too weak for structured generation. Try a stronger model, or switch to **Turn by turn** mode which uses the same per-turn pipeline as normal play.
+
+### Beats feel repetitive or drift off-course
+
+- Enable **Outline critique** to catch weak pacing before beats are generated.
+- In Expand mode, keep **Expansion critique** on so the post-expansion pass can de-duplicate repeated vocabulary and flatten intensity plateaus.
+- Reduce the number of turns — very long plans (toward 24) give the model more room to repeat itself.
+
+### The arc ends too abruptly or too neatly
+
+Toggle **Close the arc**. With it off, the arc is meant to end on a handoff moment; with it on, the arc is meant to resolve. If you want something in between, use a smaller beat count and run another plan afterwards.
diff --git a/docs/user-guide/agents/director/scene-direction.md b/docs/user-guide/agents/director/scene-direction.md
index df5eb54c..826f1e8c 100644
--- a/docs/user-guide/agents/director/scene-direction.md
+++ b/docs/user-guide/agents/director/scene-direction.md
@@ -31,6 +31,19 @@ Scene Direction is disabled by default. To enable it:
!!! tip "Quick Toggle"
Scene Direction has a quick toggle in the agent settings panel, making it easy to turn on and off during play.
+## Manually triggering a turn
+
+!!! info "New in 0.37.0"
+
+When Scene Direction is enabled but auto-progression is turned off, you can step the director through the scene one turn at a time using the **Scene direction turn** button in the director section of the scene tool bar.
+
+
+
+- **Click** to run one scene direction turn with your current settings and intentions.
+- **Ctrl+click** (Cmd+click on macOS) to open an instructions dialog. Whatever you type is inserted into the scene direction history as a one-off user direction before the turn executes, so you can nudge the director for just that turn without editing your scene-level instructions.
+
+The button is greyed out when Scene Direction is disabled.
+
## How It Works
When Scene Direction is enabled, the director analyzes the scene after each turn and decides whether to take action. The director can:
diff --git a/docs/user-guide/agents/director/settings.md b/docs/user-guide/agents/director/settings.md
index 8bd7fe55..ae03199e 100644
--- a/docs/user-guide/agents/director/settings.md
+++ b/docs/user-guide/agents/director/settings.md
@@ -226,6 +226,18 @@ When the chat history needs to be compacted (summarized), this controls what fra
Default is 0.70 (70% will be summarized when compaction is triggered).
+##### Action confirm timeout
+
+!!! info "New in 0.37.0"
+
+How long the chat will wait for you to confirm or reject a write action before it gives up and treats the action as rejected. See [Write action confirmation](/talemate/user-guide/agents/director/chat/#write-action-confirmation) for the confirmation workflow.
+
+- **Range**: 0 to 60 minutes
+- **Default**: 3 minutes
+- **0**: Wait indefinitely — the confirmation card stays open until you click Confirm or Reject
+
+The countdown is shown in the top-right corner of each confirmation card and turns red when less than 30 seconds remain.
+
##### Custom instructions
Add custom instructions that will be included in all director chat prompts. Use this to customize the director's behavior for your specific scene or storytelling style.
diff --git a/docs/user-guide/agents/memory/embeddings.md b/docs/user-guide/agents/memory/embeddings.md
index 2e54dd63..c1168dba 100644
--- a/docs/user-guide/agents/memory/embeddings.md
+++ b/docs/user-guide/agents/memory/embeddings.md
@@ -65,13 +65,24 @@ For custom sentence-transformer models, you may need to toggle this on. This can
The device to use for the embeddings. This can be either `cpu` or `cuda`. Note that this can also be overridden in the Memory agent settings.
+!!! note "Switching device without a restart (0.37.0)"
+ Changing the device no longer requires restarting Talemate. The old model is released from ChromaDB's cache and any GPU memory it held is freed before the new device is applied, and the active scene's memory database is re-imported automatically.
+
##### Distance
The maximum distance for results to be considered a match. Different embeddings may require different distances, so if you find low accuracy, try changing this value.
##### Distance Mod
-A multiplier for the distance. This can be used to fine-tune the distance without changing the actual distance value. Generally you should leave this at 1.
+A multiplier applied to **Distance** when deciding whether a result is a match. The effective cutoff used during a search is `Distance × Distance Mod`, so this slider lets you fine-tune search sensitivity without changing the base distance.
+
+- Range: `0.1` to `2.0`, in steps of `0.1`.
+- Default: `1.0`.
+- Lower values tighten the match (fewer, more relevant results).
+- Higher values loosen the match (more results, lower relevance).
+
+!!! info "Also tunable from the Context Database"
+ The [Context Database](/talemate/user-guide/world-editor/context-db/#search-strictness) page exposes this same value as the **Search Strictness** slider, making it easy to adjust on the fly while testing searches. Changes made in either place are saved to the same preset.
##### Distance Function
diff --git a/docs/user-guide/agents/memory/settings.md b/docs/user-guide/agents/memory/settings.md
index 71dfd000..ac7f4fc8 100644
--- a/docs/user-guide/agents/memory/settings.md
+++ b/docs/user-guide/agents/memory/settings.md
@@ -11,4 +11,7 @@ Select which embedding to use. Embeddings themselves are managed through the [Ap
###### Device
-The device to use for the embeddings. This can be either `cpu` or `cuda`.
\ No newline at end of file
+The device to use for the embeddings. This can be either `cpu` or `cuda`.
+
+!!! note "Switching device without a restart (0.37.0)"
+ As of version 0.37.0, changing the device while a scene is loaded no longer requires restarting Talemate. The previously loaded model is released from ChromaDB's cache and any GPU memory it held is freed before the new device is applied. The scene's memory database is re-imported automatically — depending on the size of the model and scene this may take a moment.
\ No newline at end of file
diff --git a/docs/user-guide/agents/voice/openai-compatible.md b/docs/user-guide/agents/voice/openai-compatible.md
index b076c2b8..8becf9f9 100644
--- a/docs/user-guide/agents/voice/openai-compatible.md
+++ b/docs/user-guide/agents/voice/openai-compatible.md
@@ -3,7 +3,11 @@
!!! info "New in 0.37.0"
The OpenAI Compatible TTS backend lets you connect to any server that exposes an OpenAI-style `/v1/audio/speech` endpoint.
-Use this backend to connect Talemate to any TTS service that implements the OpenAI speech API format. This includes local servers such as KoboldCpp, Kokoro-FastAPI, LocalAI, Speaches, vLLM-based TTS deployments, and any other OpenAI-compatible TTS endpoint.
+Use this backend to connect Talemate to any TTS service that implements the OpenAI speech API format, such as vLLM, LocalAI, Speaches, and other self-hosted or third-party services that mirror the same endpoint shape.
+
+Enable the **OpenAI Compatible** API in the Voice agent's [Enabled APIs](settings.md#enabled-apis) setting before configuring it.
+
+
## Settings
@@ -13,39 +17,49 @@ Use this backend to connect Talemate to any TTS service that implements the Open
Base URL of the OpenAI-compatible TTS server, including the `/v1` path.
-Example: `http://localhost:8000/v1`
+Default: `http://localhost:8000/v1`
+
+The agent will report "API URL not set" and will not generate audio until this value is provided.
##### API Key
-Optional API key for authentication. Leave empty if your server does not require one — a placeholder value is sent automatically when no key is provided.
+API key for the server. Leave empty if your server does not require authentication — Talemate will send a placeholder value so the underlying OpenAI client accepts the request.
##### Model
-Model identifier sent with each request. Some servers ignore this and always use their loaded model; others require a specific value to route requests correctly. Check your server's documentation.
+Model identifier sent with each request. Some servers ignore this field and always use the model they have loaded; others route requests based on this value. Check your server's documentation.
+
+Default: `tts-1`
##### Chunk size
-Split text into chunks of this size. Smaller values increase responsiveness at the cost of losing context between chunks (inflection, pacing, etc.). `0` disables chunking.
+Split text into chunks of this size before sending to the server. Smaller values increase responsiveness at the cost of losing context between chunks (inflection, pacing, etc.). `0` disables chunking.
+
+Default: `512`. Range: `0`–`2048`, in steps of `64`.
## Adding Voices
-Voices are not discovered automatically — you need to add them to the Voice Library manually using voice identifiers supported by your server.
+Voices for this backend are **not** auto-discovered. You need to add each voice manually to the [Voice Library](voice-library.md) using a voice identifier supported by your server.
-1. Open the Voice Library
-2. Click **:material-plus: New**
-3. Select **OpenAI Compatible** as the provider
-4. Configure the voice:
+
- - **Label** — Display name (e.g. "Narrator - Deep Male")
- - **Provider ID** — The voice identifier your server expects
- - **Tags** — Descriptive tags for organization
+1. Open the Voice Library from the main application bar.
+2. Click **:material-plus: New**.
+3. Select **OpenAI Compatible** as the provider.
+4. Fill in the voice:
-Refer to your TTS server's documentation for the list of supported voice identifiers.
+ - **Label** — Display name shown in Talemate (e.g. "Narrator - Deep Male").
+ - **Provider ID** — The voice identifier your server expects (e.g. `alloy`, `echo`, or a custom voice name defined by the server).
+ - **Tags** — Optional descriptive tags for organization and filtering.
+
+Refer to your TTS server's documentation for the list of supported voice identifiers. Once added, the voice can be [assigned to characters](voice-library.md#character-voice-assignment) or used as the [narrator voice](settings.md#narrator-voice).
## Troubleshooting
**Connection errors**: Verify the base URL is correct (including the `/v1` path) and that the server is running and reachable from Talemate.
-**Empty or silent audio**: Confirm your server actually has a TTS model loaded and that the voice ID you are sending is valid for that model. Some servers fall back silently when given an unknown voice.
+**Empty or silent audio**: Confirm your server has a TTS model loaded and that the voice ID you sent is valid for that model. Some servers fall back silently when given an unknown voice.
-**Authentication errors**: If your server requires an API key, make sure it is set. Otherwise leave the field empty.
+**Authentication errors**: If your server requires an API key, make sure it is set in the settings above. Otherwise leave the field empty.
+
+See also the general [TTS Troubleshooting Guide](troubleshooting.md).
diff --git a/docs/user-guide/agents/voice/settings.md b/docs/user-guide/agents/voice/settings.md
index e91f3352..f8eacb55 100644
--- a/docs/user-guide/agents/voice/settings.md
+++ b/docs/user-guide/agents/voice/settings.md
@@ -13,6 +13,7 @@ Select which TTS APIs to enable. You can enable multiple APIs simultaneously:
- **ElevenLabs** - Professional voice synthesis with voice cloning
- **Google Gemini-TTS** - Google's text-to-speech service
- **OpenAI** - OpenAI's TTS-1 and TTS-1-HD models
+- **OpenAI Compatible** - Any server exposing an OpenAI-style `/v1/audio/speech` endpoint (vLLM, LocalAI, Speaches, etc.)
!!! note "Multi-API Support"
You can enable multiple APIs and assign different voices from different providers to different characters. The system will automatically route voice generation to the appropriate API based on the voice assignment.
diff --git a/docs/user-guide/agents/voice/voice-library.md b/docs/user-guide/agents/voice/voice-library.md
index b5c77dbf..ace21f08 100644
--- a/docs/user-guide/agents/voice/voice-library.md
+++ b/docs/user-guide/agents/voice/voice-library.md
@@ -91,6 +91,11 @@ Check the provider specific documentation for more information on how to configu
- Choose from available OpenAI voice models
- Configure model (GPT-4o Mini TTS, TTS-1, TTS-1-HD)
+**OpenAI Compatible:**
+
+- Manually add voices using the voice identifiers supported by your server
+- Voices are not auto-discovered (see the [OpenAI Compatible backend docs](openai-compatible.md))
+
**Google Gemini-TTS:**
- Select from Google's voice models
diff --git a/docs/user-guide/app-settings/presets.md b/docs/user-guide/app-settings/presets.md
index de58b44a..3e308510 100644
--- a/docs/user-guide/app-settings/presets.md
+++ b/docs/user-guide/app-settings/presets.md
@@ -37,34 +37,11 @@ Allows you to add, remove and manage various embedding models for the memory age

-This allows you to override the global system prompts for the entire application for each overarching prompt kind.
+This panel lets you override the global system prompts for the entire application for each prompt kind (Conversation, Narration, Creation, and so on). Per-client overrides live on the **System Prompts** tab of each client's [configuration dialog](../clients/client-configuration.md).
-If these are not set the default system prompt will be read from the templates that exist in `src/talemate/prompts/templates/{agent}/system-*.jinja2`.
+See [System Prompt Overrides](system-prompts.md) for the full reference, including:
-This is useful if you want to change the default system prompts for the entire application.
-
-The effect these have, varies from model to model.
-
-### Prompt types
-
-- Conversation - Use for dialogue generation.
-- Narration - Used for narrative generation.
-- Creation - Used for other creative tasks like making new characters, locations etc.
-- Direction - Used for guidance prompts and general scene direction.
-- Analysis (JSON) - Used for analytical tasks that expect a JSON response.
-- Analysis - Used for analytical tasks that expect a text response.
-- Editing - Used for post-processing tasks like fixing exposition, adding detail etc.
-- World State - Used for generating world state information. (This is sort of a mix of analysis and creation prompts.)
-- Summarization - Used for summarizing text.
-
-### Normal / Uncensored
-
-Overrides are maintained for both normal and uncensored modes.
-
-Currently local API clients (koboldcpp, textgenwebui, tabbyapi, llmstudio) will use the uncensored prompts, while the clients targeting official third party APIs will use the normal prompts.
-
-The uncensored prompts are a work-around to prevent the LLM from refusing to generate text based on topic or content.
-
-
-!!! note "Future plans"
- A toggle to switch between normal and uncensored prompts regardless of the client is planned for a future release.
+- Which prompt kinds exist and what they are used for.
+- How Normal and Uncensored variants are selected.
+- The pencil icon that marks entries with an active override (added in 0.37.0).
+- How to include the default prompt inside your override with `{{ system_prompt }}` (added in 0.37.0).
diff --git a/docs/user-guide/app-settings/system-prompts.md b/docs/user-guide/app-settings/system-prompts.md
new file mode 100644
index 00000000..b3a33d44
--- /dev/null
+++ b/docs/user-guide/app-settings/system-prompts.md
@@ -0,0 +1,100 @@
+# :material-text-box: System Prompt Overrides
+
+Talemate sends a different system prompt depending on which task an agent is performing (dialogue, narration, analysis, and so on). You can override the text of any of these prompts, either globally for the whole application or for a single [client](../clients/client-configuration.md).
+
+!!! info "Updated in 0.37.0"
+ - The override list now shows a small pencil icon next to every prompt kind that has an active override, so you can see at a glance which entries you have customised.
+ - You can use `{{ system_prompt }}` inside an override to insert the default system prompt for that kind at generation time. This works in both the app-level and per-client override editors.
+
+## Where overrides live
+
+Talemate resolves the system prompt for a generation in this order:
+
+1. The **client** override, if the client has one set for this prompt kind.
+2. The **app-level** override, if one is set for this prompt kind.
+3. The built-in default prompt, rendered from the template under `src/talemate/prompts/templates/{agent}/system-*.jinja2`.
+
+If a level is blank it falls through to the next one. An empty textarea counts as "no override" — you do not need to delete the entry separately.
+
+### App-level overrides
+
+Open **Settings** (the cogwheel in the top navigation), then go to the **Presets** tab and select **System Prompts**.
+
+
+
+App-level overrides apply to every client unless that client has its own override for the same prompt kind.
+
+### Per-client overrides
+
+Open a client's [configuration dialog](../clients/client-configuration.md) from the cogwheels on its sidebar row, then switch to the **System Prompts** tab.
+
+
+
+Per-client overrides only apply to generations that go through that specific client. They take precedence over the app-level override.
+
+## Prompt kinds
+
+The list on the left of the editor is the same in both places:
+
+| Kind | Used for |
+|---|---|
+| Conversation | Dialogue generation. |
+| Narration | Narrative generation. |
+| Creation | Creative tasks such as building characters, locations, and similar content. |
+| Direction | Guidance prompts and general scene direction. |
+| Analysis (JSON) | Analytical tasks that expect a JSON response. |
+| Analysis Freeform | Analytical tasks that expect a text response. |
+| Editing | Post-processing tasks such as fixing exposition and adding detail. |
+| World State | Generating world state information. Sits between analysis and creation. |
+| Summarization | Summarising text. |
+
+### Normal and Uncensored variants
+
+The app-level editor has two tabs, **Normal** and **Uncensored**, so you can maintain both variants of every prompt. Currently, local API clients (koboldcpp, text-generation-webui, tabbyapi, LM Studio) use the uncensored prompts while clients that target third-party APIs use the normal prompts.
+
+The per-client editor only shows the tab that applies to that client type.
+
+## The pencil icon (0.37.0)
+
+
+
+A small :material-pencil: icon is shown in the override list next to every prompt kind that currently has a non-empty override for the active tab (Normal or Uncensored). The icon is scoped to the list you are looking at:
+
+- In the **app-level** editor, it marks kinds that have an app-wide override.
+- In a **client's** editor, it marks kinds that have a client-specific override for that client.
+
+Clearing a field (or using the textarea's clear button) removes the override and the pencil disappears the next time the list is redrawn.
+
+## Using `{{ system_prompt }}` in an override (0.37.0)
+
+If you want to add a line or two to the default prompt without rewriting the whole thing, use the `{{ system_prompt }}` template variable inside your override. When Talemate builds the final prompt for the model, every occurrence of `{{ system_prompt }}` is replaced with the default system prompt for the same kind and censorship mode.
+
+
+
+For example, in the **Conversation** override you could write:
+
+```
+{{ system_prompt }}
+
+Never acknowledge that characters are fictional or written by an AI. Characters only know what their own point of view allows.
+```
+
+Talemate then sends the full built-in Conversation system prompt followed by your extra instruction.
+
+!!! note "What belongs in a system prompt"
+ System prompts shape the AI's role and general approach — things that should apply across every scene. Writing style, tense, and scene-specific tone live in the scene's [perspective field](../world-editor/scene/outline.md#perspective-and-tense) and writing-style settings, not here.
+
+Points to know:
+
+- Expansion uses the default prompt for the kind you are editing and the tab you are on. Editing **Narration** on the **Uncensored** tab expands to the uncensored Narration default, not the normal one.
+- The variable is expanded at generation time. If a future Talemate update changes the default prompt, your override automatically picks up the new text.
+- Multiple occurrences are allowed. Every `{{ system_prompt }}` in the override is replaced.
+- The variable works the same way in app-level and per-client overrides.
+
+!!! tip "Inserting the default as editable text"
+ If you would rather copy the default prompt into the textarea so you can edit it line by line, use the **Apply Default** button in the top-right of the editor. That inserts a static copy of the current default — it will not stay in sync with future updates the way `{{ system_prompt }}` does.
+
+## Related
+
+- [Client Configuration](../clients/client-configuration.md) — the dialog that hosts the per-client **System Prompts** tab.
+- [Prompt Manager](../prompts/index.md) — manages the Jinja2 prompt templates themselves, which is a separate mechanism from these system prompt overrides.
diff --git a/docs/user-guide/clients/.pages b/docs/user-guide/clients/.pages
index c37f285c..ac954560 100644
--- a/docs/user-guide/clients/.pages
+++ b/docs/user-guide/clients/.pages
@@ -1,10 +1,13 @@
nav:
- Overview: index.md
+ - Client Configuration: client-configuration.md
- Prompt Templates: prompt-templates.md
- Recommended Local Models: recommended-models.md
+ - Model Testing Harness: model-testing-harness.md
- Inference Presets: presets.md
- Client Types: types
- Endpoint Override: endpoint-override.md
- Concurrent Requests: concurrent-requests.md
- Response Length Instructions: response-length.md
+ - Section Format: section-format.md
- ...
\ No newline at end of file
diff --git a/docs/user-guide/clients/client-configuration.md b/docs/user-guide/clients/client-configuration.md
new file mode 100644
index 00000000..2398fa5f
--- /dev/null
+++ b/docs/user-guide/clients/client-configuration.md
@@ -0,0 +1,51 @@
+# Client Configuration
+
+Each LLM client is configured through a settings dialog that you open from the client list in the sidebar. The dialog organizes settings into tabs so the common options stay easy to find while the less-used controls are grouped out of the way.
+
+!!! info "Updated in 0.37.0"
+ Advanced settings (Inference Presets, Structured Data Format, Section Format, Response Length Enforcement, Prompt Caching, Rate Limit) were moved out of the General tab into a dedicated **Advanced** tab.
+
+## Opening the dialog
+
+Click the cogwheels on a client row in the **Clients** sidebar to open its configuration dialog. When you switch to a different client, the dialog always opens on the **General** tab.
+
+
+
+## Tabs
+
+The tabs that appear depend on the client type. The core set is:
+
+| Tab | Purpose |
+|---|---|
+| **General** | Client type, name, API URL / key, model, context length, prompt template (for local clients). |
+| **Coercion** | Prefill text used to enforce compliance. Only shown for clients that can be coerced. |
+| **Advanced** | Inference Presets, Structured Data Format, [Section Format](section-format.md), [Response Length Enforcement](response-length.md), Prompt Caching, and [Rate Limit](rate-limiting.md). |
+| **Reasoning** | [Reasoning model support](reasoning.md) settings. |
+| **System Prompts** | Per-client [system prompt overrides](../app-settings/system-prompts.md). |
+
+Some client types add extra tabs (for example the **Endpoint Override** tab on remote clients, or the **Concurrency** tab on clients that support concurrent requests).
+
+### Advanced tab
+
+
+
+The Advanced tab contains settings that you usually only need to touch once per client:
+
+- **Inference Presets** — selects which [preset group](presets.md) is used for generation parameters.
+- **Structured Data Format** — whether structured responses (function calls, data management) are formatted as JSON or YAML. Leave set to *Talemate decides* to use the built-in default for the client.
+- **Section Format** — whether prompt sections are rendered as Markdown headings or XML tags. See [Section Format](section-format.md).
+- **Response Length Enforcement** — how the response length is communicated to the model. See [Response Length Enforcement](response-length.md).
+- **Optimize for Prompt Caching** — moves volatile context after the scene history to improve cache hit rates. See [Volatile Context Placement](../prompts/volatile-context-placement.md).
+- **Rate Limit** — caps requests per minute. See [Rate Limiting](rate-limiting.md).
+
+From the General tab you can also jump straight to Advanced with the :material-cog-outline: **Advanced Options** button underneath the basic fields.
+
+## Simple View
+
+The **Simple View** switch at the top of the dialog hides everything except the essential fields on the General tab (client type, name, API URL / key, and model). Use it when you just need to wire up a client quickly.
+
+- Toggling Simple View on or off resets the dialog to the **General** tab.
+- When Simple View is on, the sidebar list of tabs is hidden and the **Advanced Options** button is hidden. A reminder at the bottom of the General tab links back to the full view.
+- Turning Simple View off restores access to every tab, including **Advanced**.
+
+Clients created through the onboarding wizard open in Simple View by default. All other clients open with Simple View off.
diff --git a/docs/user-guide/clients/index.md b/docs/user-guide/clients/index.md
index 26ea5e44..558b034d 100644
--- a/docs/user-guide/clients/index.md
+++ b/docs/user-guide/clients/index.md
@@ -10,6 +10,10 @@ Talemate supports and encourages use of multiple clients. We believe it makes se
It is, however, perfectly fine to just use a single client for all tasks if you prefer.
+## Checking a model
+
+The bundled [Model Testing Harness](model-testing-harness.md) scene runs a fixed suite of minimum-viability tests against the clients assigned to your agents. Load it after configuring a new client to confirm the model can handle what Talemate will ask of it.
+
## Client setup instructions
### Officially supported APIs
diff --git a/docs/user-guide/clients/model-testing-harness.md b/docs/user-guide/clients/model-testing-harness.md
new file mode 100644
index 00000000..3624959a
--- /dev/null
+++ b/docs/user-guide/clients/model-testing-harness.md
@@ -0,0 +1,76 @@
+# Model Testing Harness
+
+!!! info "New in 0.37.0"
+ The Model Testing Harness is a bundled scene shipped with Talemate. No installation is needed beyond updating to 0.37.0.
+
+The **Model Testing Harness** is a scene that runs a fixed suite of minimum-viability tests against the language model clients assigned to your agents. It is the fastest way to check whether a new model — especially a local one — can handle the response formats, function calls, and generation styles that Talemate relies on.
+
+Passing every test does not guarantee good creative output, but any failure is a strong signal that the model is likely to struggle with Talemate's more complex features.
+
+## When to use it
+
+- Qualifying a new local model before using it for real scenes.
+- Confirming that a newly configured client (API URL, prompt template, data format, section format) actually produces the output Talemate expects.
+- Diagnosing a model that started to behave oddly after a settings change — a failing test in a specific category points at the subsystem that is broken.
+
+## Loading the scene
+
+The harness is a normal Talemate scene and loads the same way as any other — see [Load a scenario](/talemate/getting-started/load-a-scene/) for the general flow.
+
+1. From the **Home** screen, start typing `Model Testing Harness` into the **Search scenes** field.
+2. Select the matching entry from the autocomplete.
+3. Click **Load**.
+
+
+
+The tests start automatically as soon as the scene finishes loading — there is no separate "run" button to press.
+
+## What the tests exercise
+
+The harness runs a sequence of six tests. Each test calls into one of the regular Talemate agents, which means the **client currently assigned to that agent** is the one being evaluated.
+
+| # | Test | Agent used | What it checks |
+|---|---|---|---|
+| 1 | Basic Instruction Following | Director | That the model produces a short response containing the literal tagged pattern `Start`, exactly as instructed. |
+| 2 | Data Response Instruction Following | Director | That the model can return a well-formed data structure (JSON or YAML, depending on the client's [Structured Data Format](client-configuration.md) setting) matching a specified schema. |
+| 3 | Conversation Generation | Conversation | That the conversation agent can generate dialogue for a specific named character without derailing. |
+| 4 | Narrative Generation | Narrator | That the narrator agent produces continuous narrative prose without collapsing into character dialogue lines (no `VERA-7:` / `NIKO-12:` style prefixes). |
+| 5 | Function Calling | Director + Summarizer | That the model can reliably call a sequence of tool functions (`put_into_container`, `remove_from_container`, `empty_container`) through Talemate's FOCAL function-calling system to complete a multi-step task. |
+| 6 | Problem Solving | Director + Summarizer | That the model can reason about a starting state vs. a desired state and produce the correct sequence of function calls to transform one into the other. |
+
+Because each test targets a specific agent, the harness effectively covers every client in your current setup — if two agents share a client, that client is tested through both of them.
+
+## Watching the tests run
+
+While the suite is running, a **Tests Running** status banner is shown above the chat. Each test emits its own system message in the scene log as it finishes:
+
+- Green :material-check-circle-outline: check icon — the test **passed**.
+- Red :material-close-circle-outline: cross icon — the test **failed**.
+
+The message title is the test name (for example, "Basic Instruction Following") followed by **SUCCESS** or **FAILURE**, and the body repeats a short description of what the test was looking for.
+
+
+
+When all six tests are finished, the status banner changes to **Tests Finished**.
+
+!!! warning "Interruptions"
+ If the run is cancelled (for example by cancelling generation), the banner changes to **Tests Interrupted**. Reload the scene to start the tests again from the beginning.
+
+## Interpreting results
+
+A failure tells you that the model under test could not satisfy a specific minimum-viability requirement:
+
+- **Basic Instruction Following fails** — the model is not reliably following literal formatting instructions. Expect downstream problems with almost any structured Talemate feature.
+- **Data Response Instruction Following fails** — the model struggles to return JSON/YAML in the format Talemate requests. Check the client's **Structured Data Format** setting on the [Advanced tab](client-configuration.md) and confirm the chosen format is one the model can actually produce.
+- **Conversation Generation fails** — the conversation agent's client is producing output Talemate cannot parse as a single character's dialogue.
+- **Narrative Generation fails** — the narrator's output contains dialogue markers like `VERA-7:` or `NIKO-12:`, meaning the model is slipping into actor-style output instead of continuous prose.
+- **Function Calling fails** — the model cannot reliably produce function calls in the format required by [FOCAL](../node-editor/core-concepts/functions.md). This will disable most of the director's advanced tooling.
+- **Problem Solving fails** — the model can call functions in isolation but cannot chain them correctly to solve a multi-step task.
+
+To re-run the suite after changing a client setting, reload the scene.
+
+## Related
+
+- [Client Configuration](client-configuration.md) — includes the Structured Data Format and Section Format settings that the data-response test exercises.
+- [Prompt Templates](prompt-templates.md) — a wrong template is a common reason for the instruction-following tests to fail on local models.
+- [Recommended Local Models](recommended-models.md) — general guidance on choosing a local model.
diff --git a/docs/user-guide/clients/presets.md b/docs/user-guide/clients/presets.md
index 3a0a0da7..885f9f10 100644
--- a/docs/user-guide/clients/presets.md
+++ b/docs/user-guide/clients/presets.md
@@ -145,3 +145,5 @@ In the client listing find the :material-tune: selected preset and click it to e


+
+You can also pick the preset group from the **Inference Presets** dropdown on the **Advanced** tab of the [client configuration](client-configuration.md) dialog.
diff --git a/docs/user-guide/clients/prompt-templates.md b/docs/user-guide/clients/prompt-templates.md
index dd3ef8e0..0bf9da20 100644
--- a/docs/user-guide/clients/prompt-templates.md
+++ b/docs/user-guide/clients/prompt-templates.md
@@ -34,16 +34,8 @@ In the case for `Phi-3-medium-128k-instruct-Q8_0` that is `Phi3` - select it fro
## Adding a new prompt template
-Talemate keeps its prompt templates in the `./templates/llm-prompts/` directory.
+The easiest way to add or edit prompt templates is from the **Prompts** view in the main toolbar. Open the **LLM Prompt Templates** tab to create new user templates, copy built-in templates as starting points, or paste a GGUF/llama.cpp chat template directly. See [LLM Prompt Templates](/talemate/user-guide/prompts/llm-prompt-templates/) for details.
-In there you will find a `std`, `talemate` and `user` subdirectory.
+User templates are stored in `./templates/llm-prompt/std/user/` and are gitignored, so they are preserved across Talemate updates. Built-in templates live in `./templates/llm-prompt/std/` and are read-only.
-The `std` directory contains the most common prompt templates by format.
-
-The `talemate` directory contains the talemate supplied templates for some popular models (although this is quickly becoming redundant with the automatic detection).
-
-The `user` directory is for user supplied templates.
-
-Templates in the `user` and `talemate` directories will be auto assigned based on name matching. If you want to add a new template, you can do so by creating a new file in the `user` directory.
-
-Although it is recommended to just use the user-interface to assign the template, assuming it exists in the `std` directory (See above). Any template assigned through the user-interface will create a new file in the `user` directory.
\ No newline at end of file
+User templates appear in the client's **Prompt Template** dropdown with a `user/` prefix and are matched against model names the same way built-in templates are.
\ No newline at end of file
diff --git a/docs/user-guide/clients/rate-limiting.md b/docs/user-guide/clients/rate-limiting.md
index 3fc074bd..292e7863 100644
--- a/docs/user-guide/clients/rate-limiting.md
+++ b/docs/user-guide/clients/rate-limiting.md
@@ -1,6 +1,6 @@
# Rate Limiting
-You can rate limit a client to N requests per minute.
+You can rate limit a client to N requests per minute. The slider is on the **Advanced** tab of the [client configuration](client-configuration.md) dialog.

diff --git a/docs/user-guide/clients/recommended-models.md b/docs/user-guide/clients/recommended-models.md
index 424c024a..e0a9d351 100644
--- a/docs/user-guide/clients/recommended-models.md
+++ b/docs/user-guide/clients/recommended-models.md
@@ -7,4 +7,6 @@ Any of the top models in any of the size classes here should work well.
[https://oobabooga.github.io/benchmark.html](https://oobabooga.github.io/benchmark.html)
-We do not recommend going lower than 7B, and for 7B and 8B we recommend running the unquantized version if you have the resources.
\ No newline at end of file
+We do not recommend going lower than 7B, and for 7B and 8B we recommend running the unquantized version if you have the resources.
+
+Once you have a candidate model running, the [Model Testing Harness](model-testing-harness.md) scene is the quickest way to confirm it can handle the formats and function calls Talemate relies on.
\ No newline at end of file
diff --git a/docs/user-guide/clients/response-length.md b/docs/user-guide/clients/response-length.md
index a1f651a3..fd464b53 100644
--- a/docs/user-guide/clients/response-length.md
+++ b/docs/user-guide/clients/response-length.md
@@ -37,10 +37,11 @@ The instruction is derived from the configured max token count for the current g
## Configuration
-The setting is found in the client settings under the **General** tab.
+The setting is found on the **Advanced** tab of the [client configuration](client-configuration.md) dialog.
-1. Open the client settings by clicking on a client in the sidebar
-2. Find the **Response Length Enforcement** dropdown
-3. Select the desired mode
+1. Click the cogwheels on a client in the sidebar to open its configuration
+2. Open the **Advanced** tab
+3. Find the **Response Length Enforcement** dropdown and select the desired mode
+4. Click **Save**
This setting defaults to **Limit tokens and send instructions**.
diff --git a/docs/user-guide/clients/section-format.md b/docs/user-guide/clients/section-format.md
new file mode 100644
index 00000000..39f0ab2d
--- /dev/null
+++ b/docs/user-guide/clients/section-format.md
@@ -0,0 +1,27 @@
+# Section Format
+
+!!! info "New in 0.37.0"
+ Per-client setting that controls how prompt sections are delimited. Found on the **Advanced** tab of the [client configuration](client-configuration.md) dialog.
+
+Talemate's prompt templates split their content into named sections (for example *Characters*, *Scene*, *Task*). The **Section Format** setting controls how those section boundaries are rendered in the text that is sent to the model.
+
+## Options
+
+| Option | Effect |
+|---|---|
+| **Talemate decides** (default) | Uses Talemate's built-in default, which is the same output as **Markdown**. Leave this selected unless you have a reason to pick something specific. |
+| **Markdown** | Sections open with a Markdown heading, for example `## Characters`. There is no closing marker. |
+| **XML** | Sections are wrapped in paired uppercase tags, for example `...`. Spaces in section names become underscores. Empty lines at the start and end of a section are stripped. |
+
+The setting only changes the delimiters Talemate inserts around sections. It does not change what information is sent, the order of sections, or any other part of the prompt.
+
+## Where to set it
+
+
+
+1. Click the cogwheels on a client in the sidebar to open its [configuration dialog](client-configuration.md).
+2. Open the **Advanced** tab.
+3. Pick a value from the **Section Format** dropdown, next to **Structured Data Format**.
+4. Click **Save**.
+
+When a non-default value is set, the current choice is shown as a small tag in the client's row in the sidebar so you can see at a glance which clients are using which format.
diff --git a/docs/user-guide/debug-tools.md b/docs/user-guide/debug-tools.md
index e5cec70f..56aee7bb 100644
--- a/docs/user-guide/debug-tools.md
+++ b/docs/user-guide/debug-tools.md
@@ -12,6 +12,8 @@ The Debug Tools panel slides in from the right side of the screen and contains s
The Prompts tab shows a log of all AI prompts that have been sent during your session. Click on any prompt to inspect its full content. This is useful for understanding what information is being sent to the AI and debugging unexpected AI responses.
+For headless captures or longer-running debug sessions, the same prompt records can also be streamed to a file — see [Prompt Logging](../getting-started/advanced/prompt-logging.md).
+
### :material-memory: Memory
The Memory tab displays memory retrieval requests made by the Memory Agent. Use this to verify that relevant context is being retrieved during generation.
diff --git a/docs/user-guide/inline-visuals.md b/docs/user-guide/inline-visuals.md
index 1129ffc2..2ed28e63 100644
--- a/docs/user-guide/inline-visuals.md
+++ b/docs/user-guide/inline-visuals.md
@@ -22,16 +22,20 @@ There are several ways to generate images that appear in your scene feed:
The quickest way to generate inline visuals is through the scene tools visualizer menu.
-
+
From this menu you can:
- **Visualize Scene (Card)**: Generate a cover image of the current scene
- **Visualize Scene (Background)**: Generate a purely environmental image
-- **Visualize [Character] (Card)**: Generate a cover image portrait of a character
-- **Visualize [Character] (Portrait)**: Generate a face-focused portrait
+- **[Character]** submenu (one per character in the scene):
+ - **Card**: Generate a cover image portrait of that character
+ - **Portrait**: Generate a face-focused portrait of that character
- **Visualize Moment (Illustration)**: Generate an image of the current moment in the story
+!!! note "Per-character submenus (0.37.0)"
+ As of version 0.37.0, each character in the scene is grouped into its own submenu instead of appearing as separate top-level entries. Hover a character's name to open their submenu and pick **Card** or **Portrait**. See [Scene Tools — Visualizer](scenario-tools.md#material-image-frame-visualizer) for the full menu reference.
+
!!! tip "Keyboard Modifiers"
- Hold **ALT** to generate only the prompt without creating an image
- Hold **CTRL** to open a dialog where you can provide custom instructions
diff --git a/docs/user-guide/node-editor/core-concepts/prompt-templates.md b/docs/user-guide/node-editor/core-concepts/prompt-templates.md
index 371c6731..5ae9a0c3 100644
--- a/docs/user-guide/node-editor/core-concepts/prompt-templates.md
+++ b/docs/user-guide/node-editor/core-concepts/prompt-templates.md
@@ -21,11 +21,27 @@ The prompt template system uses [Jinja2 templating](https://jinja.palletsproject
### `Prompt from Template`
-The primary node for working with templates. It accepts:
+The primary node for working with templates.
-- `template_text` - For inline template content via a connected string input
-- `template_file` - For loading templates from files
-- `variables` - A dictionary of values to substitute into the template
+**Inputs**
+
+- `template_file` - Name of a template file to load (without the `.jinja2` extension). Mutually exclusive with `template_text`.
+- `template_text` - Raw inline template content supplied by a connected string input. Mutually exclusive with `template_file`.
+- `variables` - A dictionary of values to substitute into the template.
+
+**Outputs**
+
+- `prompt` - The rendered `Prompt` instance. Pass it to a `Generate Response` node (or another prompt-aware node) to send it to an agent.
+
+**Properties**
+
+- `scope` - Template scope. One of `scene` or an agent type (`narrator`, `director`, `creator`, `editor`, `summarizer`, `world_state`, …). Controls which `templates/` subfolder is searched for `template_file`. See [Template Scope and File Storage](#template-scope-and-file-storage) below.
+- `template_file` - Fallback template name used when the `template_file` input is not connected.
+- `template_text` - Fallback inline template text used when the `template_text` input is not connected.
+- `dedupe` (default: `true`, added in 0.37.0) - Controls whether the rendered prompt passes through line-level deduplication. Leave it on unless the template contains structured repeated content (e.g. beat listings) — see [Prompt Deduplication](../../prompts/deduplication.md) for when to turn it off.
+
+!!! warning "Pick one source"
+ Providing both `template_file` and `template_text` raises an input error. Feed the node from exactly one source per run.
### `Template Variables`
diff --git a/docs/user-guide/node-editor/reference/template_functions.md b/docs/user-guide/node-editor/reference/template_functions.md
index b348eab0..640a886f 100644
--- a/docs/user-guide/node-editor/reference/template_functions.md
+++ b/docs/user-guide/node-editor/reference/template_functions.md
@@ -155,6 +155,8 @@ Scaffolds a data structure (JSON or YAML) for the agent to complete. The functio
Disables deduplication for the prompt text. By default, Talemate removes duplicate lines from prompts to save tokens. This function prevents that behavior for the current prompt.
+See [Prompt Deduplication](../../prompts/deduplication.md) for when to reach for this and the equivalent per-node flag on `Prompt from Template`.
+
!!! payload "Arguments"
This function takes no arguments.
@@ -812,7 +814,9 @@ Provides access to the global Talemate configuration object.
### condensed
-Condenses a string by removing extra whitespace and newlines.
+Collapses runs of spaces and tabs within each line so that the prompt's deduplication pass can compare entries as single-line strings. The filter is intended for multi-line context chunks (world info, memory entries, pins, etc.) where you want duplicate paragraphs to be detected reliably but the original paragraph breaks should still reach the LLM.
+
+Internally the filter replaces newlines with a marker token before rendering. After the prompt has been rendered and deduplicated, the markers are expanded back to real newlines, so the final prompt the model sees keeps its original multi-line structure.
!!! example "Example: Condensed String"
@@ -820,7 +824,15 @@ Condenses a string by removing extra whitespace and newlines.
{{ "Hello\n\nWorld" | condensed }}
```
- Output:
+ The prompt sent to the model:
```
- Hello World
- ```
\ No newline at end of file
+ Hello
+
+ World
+ ```
+
+ During deduplication the same value is compared as the single line `Hello World`, so a second entry with the same text on one line would be detected as a duplicate and removed.
+
+!!! info "Changed in 0.37.0"
+
+ Before 0.37.0 the filter permanently compacted its input into a single line, so a multi-paragraph memory or pin reached the LLM as one long line. It now only compacts temporarily for the dedupe comparison and restores the original line breaks afterwards. Templates that use `{{ value | condensed }}` do not need to be changed.
\ No newline at end of file
diff --git a/docs/user-guide/prompts/deduplication.md b/docs/user-guide/prompts/deduplication.md
new file mode 100644
index 00000000..15a2dd58
--- /dev/null
+++ b/docs/user-guide/prompts/deduplication.md
@@ -0,0 +1,45 @@
+# Prompt Deduplication
+
+Talemate runs a line-level fuzzy-dedupe pass over every rendered prompt before it is sent to the language model. The pass removes lines longer than 32 characters whose similarity to an earlier line is ≥95%, which saves tokens when the same paragraph slips into a prompt from multiple context sources (world info, memories, pins).
+
+In most cases this is exactly what you want. Occasionally you need to turn it off.
+
+## When to disable it
+
+Disable dedupe when your template contains **structured repeated content** that must reach the model intact. The canonical case is a beat listing where the beats happen to share long near-identical prefixes:
+
+```
+Beat 1: Alice confronts Bob about the missing ledger.
+Beat 2: Alice confronts Bob about the missing ring.
+Beat 3: Alice confronts Bob about the missing key.
+```
+
+With dedupe on, the similarity threshold collapses these into one line and the model loses the plan. With dedupe off the whole list reaches the prompt verbatim.
+
+## How to disable it
+
+There are two control points. Pick whichever is closer to the content you're protecting.
+
+### From inside a template
+
+Call `disable_dedupe()` once at the top of the template (or anywhere before the structured content):
+
+```jinja2
+{{ disable_dedupe() }}
+<|SECTION:BEATS|>
+Beat 1: Alice confronts Bob about the missing ledger.
+Beat 2: Alice confronts Bob about the missing ring.
+Beat 3: Alice confronts Bob about the missing key.
+<|CLOSE_SECTION|>
+```
+
+This is the usual choice when the template itself owns the repeated structure. See the [`disable_dedupe()` function reference](../node-editor/reference/template_functions.md#disable_dedupe) for the full function entry.
+
+### From a `Prompt from Template` node
+
+Set the node's `dedupe` property to `false`. This toggles deduplication for the prompt produced by that specific node only. Use this when you don't own the template file but still need to opt out for a specific invocation. See the node's [Properties reference](../node-editor/core-concepts/prompt-templates.md#prompt-from-template) for full details.
+
+## Scope and interactions
+
+- Disabling dedupe in one place does **not** cascade. A `disable_dedupe()` call only affects the prompt it is rendered into, and the node's `dedupe` property only affects that node's output.
+- Dedupe is separate from the [`condensed`](../node-editor/reference/template_functions.md) template filter. The condensed filter uses its own marker-based mechanism to collapse multi-line context for comparison and does not rely on the dedupe pass. Disabling dedupe leaves the condensed filter's behavior unchanged.
diff --git a/docs/user-guide/prompts/index.md b/docs/user-guide/prompts/index.md
index c13087a2..25f5227a 100644
--- a/docs/user-guide/prompts/index.md
+++ b/docs/user-guide/prompts/index.md
@@ -13,14 +13,18 @@ The Prompt Manager is accessible from the main application toolbar. Click the **

-The Prompt Manager is organized into three main tabs:
+The Prompt Manager is organized into four main tabs:
- **Prompts** -- view prompts that have been sent to the LLM, with full detail inspection
- **Template Files** -- browse, edit, and manage template groups and overrides
+- **LLM Prompt Templates** -- manage the base chat-format templates (ChatML, Llama3, etc.) used for local LLM inference (see [LLM Prompt Templates](llm-prompt-templates.md))
- **Scene Context** -- review how scene history is rendered into AI context (see [Scene Context History Review](context-history-review.md))
The sidebar also provides quick-access panels for recent prompts and recently rendered templates.
+!!! tip "Outdated override warning"
+ When one or more of your active template overrides is older than the built-in default it overrides, the top-level **Prompts** tab in the main navigation shows a warning icon. Open the **Active** tab (see below) to see which templates are flagged and review or remove them.
+
## Template Groups
Templates are organized into groups that control override priority. Each group is a collection of Jinja2 template files organized by agent (narrator, director, conversation, etc.).
diff --git a/docs/user-guide/prompts/llm-prompt-templates.md b/docs/user-guide/prompts/llm-prompt-templates.md
new file mode 100644
index 00000000..5ee975fb
--- /dev/null
+++ b/docs/user-guide/prompts/llm-prompt-templates.md
@@ -0,0 +1,99 @@
+# LLM Prompt Templates
+
+!!! info "New in 0.37.0"
+ The **LLM Prompt Templates** tab lets you view, create, edit, and delete base chat-format templates from within the Prompt Manager. User templates are stored separately from the built-ins and are preserved across updates.
+
+The **LLM Prompt Templates** tab manages the base chat-format templates used for local LLM inference -- the per-model wrappers like `ChatML`, `Llama3`, `Mistral`, or `Gemma4` that decide how system, user, and assistant turns are tokenized before being sent to the model.
+
+These are different from the Jinja2 agent templates covered in the [Prompt Manager](index.md). Agent templates build the *content* of a prompt; LLM prompt templates wrap that content in the format a specific model expects.
+
+
+
+## Accessing the Tab
+
+Open the **Prompts** view from the main toolbar and select the **LLM Prompt Templates** tab.
+
+
+
+The tab is split into two panels:
+
+- **List panel** (left) -- shows your **User Templates** (editable) on top and **Built-in Templates** (read-only) below.
+- **Editor panel** (right) -- previews the selected template, or opens it for editing when you select a user template.
+
+## Built-in vs User Templates
+
+| Source | Location | Editable | Notes |
+|--------|----------|----------|-------|
+| **Built-in** | `templates/llm-prompt/std/` | No | Ship with Talemate. Updated with each release. |
+| **User** | `templates/llm-prompt/std/user/` | Yes | Your templates. Gitignored, never overwritten by updates. |
+
+When a client looks up a prompt template by model name, both built-in and user templates are searched. User templates are listed in the model picker with a `user/` prefix (for example `user/MyModel`).
+
+## Creating a New User Template
+
+Click **New Template** in the tab header to open the create dialog.
+
+
+
+1. Enter a name (the `.jinja2` extension is added automatically).
+2. Click **Create**.
+
+The new template is saved to `templates/llm-prompt/std/user/` with a minimal starter body and is opened in the editor so you can fill it in.
+
+Names are sanitized: they cannot contain slashes, backslashes, or any of the characters `< > : " | ? *`.
+
+## Copying a Built-in Template
+
+Built-in templates cannot be edited directly. To customize one, copy it into your user templates:
+
+1. Select the built-in template in the list.
+2. Click **Copy to User Templates** in the editor header.
+
+
+
+A new user template with the same filename is created in `std/user/` and automatically selected for editing. If a user template with that name already exists, you will see a warning and need to delete or rename the existing copy first.
+
+## Editing a User Template
+
+Select a user template from the list. The editor opens with the full Jinja2 source.
+
+
+
+- An **unsaved** chip appears in the header as soon as the content differs from the saved file.
+- Click **Save** to write the changes back to disk.
+- Click **Delete** to permanently remove the template. A confirmation prompt is shown.
+
+## Using GGUF / llama.cpp Chat Templates
+
+Chat templates pulled from a GGUF model's `tokenizer_config.json` (or the matching `chat_template.jinja2` on a Hugging Face model repo) can be pasted directly into a user template. The following variables used by those templates are provided by Talemate when rendering:
+
+| Variable | Description |
+|----------|-------------|
+| `messages` | List of `{role, content}` dicts (roles: `system`, `user`, `assistant`). |
+| `bos_token`, `eos_token` | Empty strings -- Talemate does not add BOS/EOS itself; if the model requires them, include the literal tokens in the template. |
+| `add_generation_prompt` | Always `True`. |
+| `enable_thinking` | `True` when reasoning tokens are enabled on the client, otherwise `False`. |
+| `thinking_budget` | The client's reasoning token count, or `0`. |
+| `strftime_now(fmt)` | Helper that returns the current time formatted with `strftime`. |
+| `raise_exception(msg)` | Helper compatible with GGUF templates that emit errors. |
+
+Talemate's native variables (`system_message`, `user_message`, `coercion_message`, `reasoning_tokens`, `spec`) remain available in the same template, so you can mix a GGUF template with Talemate-specific features if needed.
+
+## Assigning a Template to a Client
+
+Adding or editing a template here only makes it available -- it does not automatically assign it to any client. To use a template with a specific model:
+
+1. Open **Clients** from the main toolbar and edit the client.
+2. Pick the template from the **Prompt Template** dropdown. User templates appear prefixed with `user/`.
+
+See [Prompt Templates](../clients/prompt-templates.md) for how clients resolve templates from a model name and [Template Locking](../clients/template-locking.md) for locking a client to a specific template.
+
+## Outdated Override Warning on the Prompts Tab
+
+The top-level **Prompts** tab in the main navigation shows a small warning icon when any of your active Jinja2 template overrides (managed from the [Prompt Manager](index.md#active-tab-resolved-template-tree)) are older than the built-in default they override. This happens most often after an update that ships improvements to default templates.
+
+
+
+The icon is an alert, not a tab count. Open the Prompt Manager and check the **Active** tab to see which templates are flagged as outdated, then review or delete those overrides as needed.
+
+This warning tracks Jinja2 agent template overrides only. It is not related to the LLM prompt templates described on this page -- user LLM prompt templates are not compared against built-ins and therefore never show as outdated.
diff --git a/docs/user-guide/prompts/volatile-context-placement.md b/docs/user-guide/prompts/volatile-context-placement.md
index 24bb4722..429eb829 100644
--- a/docs/user-guide/prompts/volatile-context-placement.md
+++ b/docs/user-guide/prompts/volatile-context-placement.md
@@ -35,13 +35,13 @@ Volatile context placement is controlled at two levels: per-client and per-agent
### Per-Client Setting
-The primary toggle is the **Optimize for Prompt Caching** setting on each LLM client.
+The primary toggle is the **Optimize for Prompt Caching** setting on each LLM client, found on the **Advanced** tab of the [client configuration](../clients/client-configuration.md) dialog.

-1. Open the client settings by clicking on a client in the sidebar
-2. Find the **Optimize for Prompt Caching** toggle
-3. Enable it to move volatile context after scene history
+1. Click the cogwheels on a client in the sidebar to open its configuration
+2. Open the **Advanced** tab
+3. Enable the **Optimize for Prompt Caching** checkbox to move volatile context after scene history
This setting applies to all agents using this client, unless overridden at the agent level.
diff --git a/docs/user-guide/scenario-tools.md b/docs/user-guide/scenario-tools.md
index 598f837d..2948377e 100644
--- a/docs/user-guide/scenario-tools.md
+++ b/docs/user-guide/scenario-tools.md
@@ -83,6 +83,34 @@ or
Automatically picks a character to generate dialogue and actions based on the current scene state.
+### :material-bullhorn: Director Actions
+
+Opens a context menu with director-driven actions for the scene.
+
+
+
+#### :material-tournament: Generate dynamic actions
+
+Asks the director to generate a set of clickable action choices for the current player turn. See [Dynamic Actions](/talemate/user-guide/agents/director/settings/#dynamic-actions) for how to configure this.
+
+!!! note "Keyboard modifiers"
+ Hold `ctrl` (Cmd on macOS) while clicking to provide a one-off direction that guides the generated actions.
+
+#### :material-movie-play: Scene direction turn
+
+Manually triggers a single [Autonomous Scene Direction](/talemate/user-guide/agents/director/scene-direction) turn. Useful when Scene Direction is enabled but auto-progression is off and you want to step the director through the scene one turn at a time.
+
+Greyed out when Scene Direction is disabled in the [director agent settings](/talemate/user-guide/agents/director/scene-direction#enabling-scene-direction).
+
+!!! note "Keyboard modifiers"
+ Hold `ctrl` (Cmd on macOS) while clicking to provide one-off instructions for the director to follow on this turn only.
+
+#### :material-movie-open: Generate long progress
+
+Opens the Generate Long Progress dialog, where the director plans and autonomously generates a multi-beat scene arc from your instructions.
+
+See [Director Planning](/talemate/user-guide/agents/director/planning) for the full workflow and settings.
+
### :material-script-text: Narrator Actions
Will open a context menu that allows you to have the narrator perform actions.
@@ -122,8 +150,34 @@ Will prompt you for a question and then have the narrator generate narrative tex
### :material-clock: Advance time
-Opens a context menu with options to advance time in the scene, ranging from 5 minutes to 10 years.
+Opens a menu with options to advance time in the scene. As of version 0.37.0, the presets are organized into per-unit submenus and the menu includes a **Custom...** entry for durations that are not covered by the presets.
+
+
+#### Preset submenus
+
+Hovering a group opens its submenu. Clicking a preset advances time by that amount immediately.
+
+| Group | Options |
+| --- | --- |
+| :material-timer-sand: **Minutes** | 5, 15, 30 minutes |
+| :material-clock-outline: **Hours** | 1, 2, 4, 8, 12 hours |
+| :material-weather-sunny: **Days** | 1, 2, 3 days |
+| :material-calendar-week: **Weeks** | 1, 2 weeks |
+| :material-calendar-month: **Months** | 1, 3, 6 months |
+| :material-calendar-multiple: **Years** | 1, 2, 3, 5, 10 years |
+
+#### Custom time dialog
+
+Selecting **Custom...** at the bottom of the menu opens a small dialog for entering an arbitrary duration.
+
+
+
+1. Enter an **Amount** (minimum `1`).
+2. Pick a **Unit** from the dropdown: *minutes*, *hours*, *days*, *weeks*, *months*, or *years*.
+3. Click **Advance** to apply, or **Cancel** to close without advancing.
+
+The dialog defaults to `1 hour` each time it is opened.
By default the [:material-script-text: Narrator Agent](/talemate/user-guide/agents/narrator) will narrate the time jump, but you can disable this in the [:material-script-text: Narrator Agent Settings](/talemate/user-guide/agents/narrator/settings/).
@@ -271,7 +325,9 @@ Once it is done, the character will now be part of the scene and can be interact
The visualizer menu provides several options for generating images of your scene and characters. As of version 0.35.0, generated images can appear directly in your scene feed as [inline visuals](/talemate/user-guide/inline-visuals).
-
+
+
+As of version 0.37.0, per-character entries are grouped into submenus. Scene-level actions stay at the top level of the menu; each character in the scene has its own submenu with the character-specific actions inside.
#### Auto-attach visuals
@@ -289,13 +345,18 @@ Generates a portrait-oriented cover image of the current scene, suitable for use
Generates a purely environmental image of the scene without characters. Good for establishing shots or backgrounds.
-#### :material-brush: Visualize [Character] (Card)
+#### :material-account-tie: / :material-account: Character submenus
-Generates a cover image portrait of the selected character in the current scene context. This creates a larger, more detailed character image.
+Each character present in the scene has its own submenu, listed between the scene-level entries and the scene illustration entry. The player character is marked with the :material-account-tie: icon; NPCs are marked with :material-account:. Hovering a character entry opens the submenu.
-#### :material-brush: Visualize [Character] (Portrait)
+
-Generates a face-focused portrait of the selected character. These are ideal for showing expressions and are commonly used as character avatars in the message feed.
+Each character submenu contains:
+
+- **:material-brush: Card** — Generates a cover image portrait of the character in the current scene context. This creates a larger, more detailed character image.
+- **:material-brush: Portrait** — Generates a face-focused portrait of the character. These are ideal for showing expressions and are commonly used as character avatars in the message feed.
+
+The **ALT** and **CTRL** keyboard modifiers described above apply to items inside the character submenus as well.
#### :material-image-filter-hdr: Visualize Moment (Illustration)
diff --git a/docs/user-guide/time-passage.md b/docs/user-guide/time-passage.md
index a35066c9..ec200ac2 100644
--- a/docs/user-guide/time-passage.md
+++ b/docs/user-guide/time-passage.md
@@ -9,7 +9,10 @@ Time passage messages mark the flow of time within your scene. They appear as cl
### From the Scene Tools Menu
-The primary way to advance time is through the **Advance Time** option in the [Scene Tools](scenario-tools.md#advance-time) menu. This opens a submenu with preset durations ranging from 5 minutes to 10 years. By default, the [Narrator Agent](/talemate/user-guide/agents/narrator/) will narrate the time jump.
+The primary way to advance time is through the :material-clock: **Advance Time** button in the [Scene Tools](scenario-tools.md#advance-time) tool bar. It opens a menu of grouped duration presets (Minutes, Hours, Days, Weeks, Months, Years) plus a **Custom...** option for arbitrary durations. By default, the [Narrator Agent](/talemate/user-guide/agents/narrator/) will narrate the time jump.
+
+
+
### From the Scene View
diff --git a/docs/user-guide/world-editor/characters/.pages b/docs/user-guide/world-editor/characters/.pages
index 831d329f..9f5ea211 100644
--- a/docs/user-guide/world-editor/characters/.pages
+++ b/docs/user-guide/world-editor/characters/.pages
@@ -7,6 +7,7 @@ nav:
- Delete a character: delete.md
- Description: description.md
- Details: details.md
+ - Folders: folders.md
- Import a character: import.md
- Tracked states: states.md
- Visuals: visuals.md
diff --git a/docs/user-guide/world-editor/characters/folders.md b/docs/user-guide/world-editor/characters/folders.md
new file mode 100644
index 00000000..64a0f053
--- /dev/null
+++ b/docs/user-guide/world-editor/characters/folders.md
@@ -0,0 +1,64 @@
+# Folders
+
+The character list in the :material-earth-box: **World Editor** can optionally be organized into collapsible folders. Folders are a sidebar-only organization tool — they do not affect how characters behave in the scene, only how they are grouped in the list.
+
+Characters that are not assigned to a folder stay at the top of the list as a flat, ungrouped section. Folders appear below the ungrouped characters, sorted alphabetically.
+
+
+
+Each folder header shows a count chip with the number of members it contains. The chip turns green when at least one character in the folder is currently active in the scene.
+
+## Assigning a character to a folder
+
+Folders are assigned from the character editor, not from the sidebar.
+
+1. Open the :material-earth-box: **World Editor** and navigate to the **Characters** tab.
+2. Select the character you want to organize.
+3. At the top of the character editor, next to the character's name and color chip, use the folder input (the text field with a :material-folder-outline: icon).
+4. Start typing a folder name. Existing folder names from the scene will be offered as suggestions in a dropdown.
+5. Pick an existing folder to move the character into it, or press **Enter** (or click the **Create "..."** option) to put the character into a brand-new folder.
+
+
+
+The field is capped at 29 characters. Leading and trailing whitespace is trimmed automatically.
+
+The folder assignment saves immediately — you don't need to confirm it.
+
+### Removing a character from a folder
+
+To unassign a character, open the character in the editor and clear the folder input (click the :material-close-circle: clear icon inside the field, or delete the text and press **Enter**). The character moves back into the ungrouped section at the top of the list.
+
+## Renaming a folder
+
+Folders are renamed from the sidebar, not from the character editor.
+
+1. In the character list, locate the folder you want to rename.
+2. Click the :material-pencil: pencil icon on the right side of the folder header.
+3. In the **Rename folder** dialog, edit the folder name and click **Rename**.
+
+
+
+Renaming a folder updates every character currently assigned to it in one step. Characters in other folders are left alone.
+
+## Expanding and collapsing folders
+
+Click a folder header to expand or collapse it. The open/closed state of each folder is remembered per scene across page reloads.
+
+When a character is moved into a folder (for example, from the character editor), that folder is automatically expanded so you can see where the character landed.
+
+## How folders sync across scenes
+
+Folder assignments are part of a character's [shared world context](/talemate/user-guide/world-editor/scene/shared-context/), and behave the same way as shared attributes and details:
+
+- If a character is **marked as shared** (the **Shared to World Context** checkbox in the character editor is on), their folder assignment is stored in the shared context file and applied to every scene that is linked to the same shared context.
+- If a character is **not shared**, their folder is a per-scene setting and is not copied anywhere else.
+
+In practice this means that once you organize a shared character into a folder in one scene, opening any other scene linked to the same shared context will show that character in the same folder. Clearing a shared character's folder also propagates — the character becomes ungrouped across all linked scenes.
+
+!!! info "Scene-local folders"
+ Folders themselves are not a shared-context object. A folder "exists" wherever at least one character points at it. That means a folder name that only contains non-shared characters is scene-local, and will not appear in other scenes.
+
+## Related
+
+- [Shared World & Episodes](/talemate/user-guide/world-editor/scene/shared-context) — how shared world context works and how to link scenes.
+- [Character editor overview](/talemate/user-guide/world-editor/characters) — the Characters tab and the rest of the character editor.
diff --git a/docs/user-guide/world-editor/characters/index.md b/docs/user-guide/world-editor/characters/index.md
index aa461dd0..722c27cd 100644
--- a/docs/user-guide/world-editor/characters/index.md
+++ b/docs/user-guide/world-editor/characters/index.md
@@ -6,6 +6,8 @@ You can create and remove characters, manage their details, and track their stat
Characters can also be temporarily disabled, which will prevent them from being included in the scene' dialogue generation. (e.g., they are out of the scene for a moment.)
+The character list can optionally be organized into collapsible [folders](/talemate/user-guide/world-editor/characters/folders).
+
## Character Components
A character is made up of the following components:
diff --git a/docs/user-guide/world-editor/context-db.md b/docs/user-guide/world-editor/context-db.md
index 4598d5ef..80d3371c 100644
--- a/docs/user-guide/world-editor/context-db.md
+++ b/docs/user-guide/world-editor/context-db.md
@@ -1,6 +1,6 @@
# Context DB
-A very rudimentary interface to browse the current context database managed by the [Memory Agent](/talemate/user-guide/agents/memory/).
+A read-only interface to browse and search the current context database managed by the [Memory Agent](/talemate/user-guide/agents/memory/).
!!! note
This interface will likely be revamped soon, so documentation will be minimal currently.
@@ -9,12 +9,30 @@ A very rudimentary interface to browse the current context database managed by t
Search is done by typing in the search field and pressing `Enter`.
-The search will look for the entered text based on relevancy using embeddings. Without getting too technical here, that means if you're using the basic chromadb configuration, accuracy may be lacking.
+The search looks for the entered text based on relevancy using embeddings. Without getting too technical here, that means if you're using the basic chromadb configuration, accuracy may be lacking.
-See [Memory Agent - ChromaDB Setup](/talemate/user-guide/agents/memory/chromadb) for more information on how to improve the search accuracy.
+See [Memory Agent - Embeddings](/talemate/user-guide/agents/memory/embeddings) for more information on how to improve the search accuracy.

+### Search Strictness
+
+The **Search Strictness** slider tunes how closely a result must match the query before it is returned.
+
+
+
+- Range: `0.1` to `2.0`, in steps of `0.1`.
+- Default: `1.0`.
+- **Lower values** require closer matches (stricter search, fewer but more relevant results).
+- **Higher values** accept more loosely related results (looser search, more results of lower relevance).
+
+The slider value is the `distance_mod` multiplier on the active embedding preset's `distance` setting, and it is applied immediately to any subsequent search.
+
+!!! info "Saved to the active embedding preset"
+ Moving the slider writes the new value to the embedding preset currently selected in the [Memory agent settings](/talemate/user-guide/agents/memory/settings). The change persists across restarts and affects every search that uses that preset.
+
+ The same value is also editable from the embedding preset itself as the [Distance Mod](/talemate/user-guide/agents/memory/embeddings/#distance-mod) field.
+
## Adding an entry
While you can manually add an entry through this interface, its not really encouraged anymore.
@@ -28,4 +46,4 @@ It is better to use the :material-earth: **World** and :material-account-group:
Resets the context database, and will remove all entries and then re-populate it with the entries in the current scene.
!!! warning
- Entries added manually directly to the context db will not be in the scene file, and be lost during this operation.
\ No newline at end of file
+ Entries added manually directly to the context db will not be in the scene file, and be lost during this operation.
diff --git a/docs/user-guide/world-editor/scene/outline.md b/docs/user-guide/world-editor/scene/outline.md
index 5d43ce85..b647a1d0 100644
--- a/docs/user-guide/world-editor/scene/outline.md
+++ b/docs/user-guide/world-editor/scene/outline.md
@@ -29,6 +29,27 @@ You can type in a value or pick something from the list.
> A terrifying adventure with lovecraftian elements
+### Perspective and Tense
+
+The narrative perspective and tense for the story (for example `Third person limited, past tense` or `Second person, present tense`).
+
+When set, the value is included in the context sent to the AI for narration, dialogue, and autocomplete prompts, so the model knows which point of view and tense to write in.
+
+The field is free-form text. Leave it blank if you don't need to specify one — prompts will simply omit the line.
+
+
+
+##### Examples
+
+> Third person limited, past tense
+
+> Second person, present tense
+
+> First person past tense, from Annabelle's point of view
+
+!!! note "Exposed as a context ID"
+ This field is also available as the `story_configuration:perspective` context ID, which means it can be referenced or updated by features that work with context IDs (for example the [Context Database](/talemate/user-guide/world-editor/context-db)).
+
### Description
This should be an internal description - that will be included in the context sent to the ai, but not the player. It can be used to give the ai more information about the scene or how to treat certain elements.
diff --git a/docs/user-guide/world-editor/scene/shared-context.md b/docs/user-guide/world-editor/scene/shared-context.md
index bb91d427..ab00a333 100644
--- a/docs/user-guide/world-editor/scene/shared-context.md
+++ b/docs/user-guide/world-editor/scene/shared-context.md
@@ -186,3 +186,5 @@ Shared world entries appear with an orange/amber highlight. These entries contai
- **Static History** - Manually created history entries (not summarized layers)
These elements remain synchronized across all scenes linked to the same shared context.
+
+A shared character's [folder assignment](/talemate/user-guide/world-editor/characters/folders) is also synchronized — organizing a shared character into a folder in one scene places it in the same folder in every linked scene.