diff --git a/src/settings/archived-section.tsx b/src/settings/archived-section.tsx
index 32a7e7b6..20a189cb 100644
--- a/src/settings/archived-section.tsx
+++ b/src/settings/archived-section.tsx
@@ -19,19 +19,11 @@ export function ArchivedThreadSection({ state }: { state: ArchivedThreadSectionS
return (
<>
-
+
-
+
{state.contentAvailable ? (
) : !state.loading && state.status ? (
@@ -45,10 +37,7 @@ export function ArchivedThreadSection({ state }: { state: ArchivedThreadSectionS
function ArchiveExportSettings({ state }: { state: ArchivedThreadSectionState }): UiNode {
return (
-
+
{
@@ -56,7 +45,7 @@ function ArchiveExportSettings({ state }: { state: ArchivedThreadSectionState })
}}
/>
-
+
-
+
-
+
-
+
{state.contentAvailable ? (
) : !state.loading && state.status ? (
diff --git a/src/settings/tab.tsx b/src/settings/tab.tsx
index 69a618d1..52b47387 100644
--- a/src/settings/tab.tsx
+++ b/src/settings/tab.tsx
@@ -10,8 +10,7 @@ import type { CodexPanelSettingTabHost } from "./host";
import { HookSection } from "./hook-section";
import type { SettingsSectionsState } from "./section-state";
-const SETTINGS_INTRO_TEXT =
- "Codex Panel stores only panel preferences. Models, sandboxing, approvals, MCP servers, hooks, and network access still come from Codex config.";
+const SETTINGS_INTRO_TEXT = "Codex Panel stores panel preferences only. Runtime settings still come from Codex.";
const SEND_SHORTCUT_LABELS = {
enter: "Enter",
"mod-enter": "Cmd/Ctrl+Enter",
@@ -103,7 +102,7 @@ export class CodexPanelSettingTab extends PluginSettingTab {
new Setting(configItems)
.setName("Codex executable")
- .setDesc("Path used to start `codex app-server`. Use an absolute path if Obsidian cannot find `codex`.")
+ .setDesc("Command used to start `codex app-server`; use an absolute path if needed.")
.addText((text) => {
text.setPlaceholder(DEFAULT_CODEX_PATH).setValue(this.plugin.settings.codexPath);
const commitCodexPath = () => {
@@ -119,7 +118,7 @@ export class CodexPanelSettingTab extends PluginSettingTab {
});
new Setting(configItems)
.setName("Show chat toolbar")
- .setDesc("Show the chat panel toolbar. Slash commands, composer status controls, and the threads view remain available when hidden.")
+ .setDesc("Show the toolbar above the chat panel.")
.addToggle((toggle) => {
toggle.setValue(this.plugin.settings.showToolbar).onChange(async (value) => {
this.plugin.settings.showToolbar = value;
@@ -133,9 +132,7 @@ export class CodexPanelSettingTab extends PluginSettingTab {
const composerItems = createSettingsItems(composerSection);
new Setting(composerItems)
.setName("Send shortcut")
- .setDesc(
- "Choose how the composer sends messages. Shift+Enter inserts a newline when Enter sends. Obsidian hotkeys may intercept Cmd/Ctrl+Enter.",
- )
+ .setDesc("Pick Enter or Cmd/Ctrl+Enter. Shift+Enter adds a newline when Enter sends.")
.addDropdown((dropdown) => {
dropdown.addOption("enter", SEND_SHORTCUT_LABELS.enter);
dropdown.addOption("mod-enter", SEND_SHORTCUT_LABELS["mod-enter"]);
@@ -147,7 +144,7 @@ export class CodexPanelSettingTab extends PluginSettingTab {
});
new Setting(composerItems)
.setName("Scroll thread from composer edges")
- .setDesc("When enabled, Up/Ctrl+P on the first composer line and Down/Ctrl+N on the last line scroll the thread.")
+ .setDesc("Use Up/Ctrl+P and Down/Ctrl+N at composer edges to scroll the thread.")
.addToggle((toggle) => {
toggle.setValue(this.plugin.settings.scrollThreadFromComposerEdges).onChange(async (value) => {
this.plugin.settings.scrollThreadFromComposerEdges = value;
diff --git a/tests/settings/settings-tab.test.ts b/tests/settings/settings-tab.test.ts
index 8676e4c9..9060e5e3 100644
--- a/tests/settings/settings-tab.test.ts
+++ b/tests/settings/settings-tab.test.ts
@@ -72,7 +72,7 @@ describe("settings tab", () => {
expect(buttonTexts(tab)).not.toContain("Load archive list");
expect(
tab.containerEl.querySelector(".codex-panel-settings__header.setting-item-heading .setting-item-description")?.textContent,
- ).toContain("Codex Panel stores only panel preferences");
+ ).toContain("Codex Panel stores panel preferences only");
expect(tab.containerEl.querySelector(".codex-panel-settings__header button")?.getAttribute("data-icon")).toBe("refresh-cw");
expect(tab.containerEl.querySelector("h2")).toBeNull();
expect(tab.containerEl.querySelector(".codex-panel-settings__general-section.setting-group > .setting-items")?.children).toHaveLength(
@@ -85,14 +85,14 @@ describe("settings tab", () => {
expect(
tab.containerEl.querySelector(".codex-panel-settings__archived-section > .setting-item-heading .setting-item-description")
?.textContent,
- ).toContain("Choose the default archive behavior");
+ ).toContain("Set the default archive action");
expect(
tab.containerEl.querySelector(".codex-panel-settings__archived-threads-section > .setting-item-heading .setting-item-description")
?.textContent,
- ).toContain("Restore archived threads");
+ ).toContain("Restore or permanently delete");
expect(
tab.containerEl.querySelector(".codex-panel-settings__hook-section > .setting-item-heading .setting-item-description")?.textContent,
- ).toContain("Review discovered hooks");
+ ).toContain("Trust, enable, or disable");
expect(
tab.containerEl.querySelector(
".codex-panel-settings__archived-section.setting-group > .setting-items:not(.codex-panel-settings__dynamic-list)",
@@ -117,7 +117,7 @@ describe("settings tab", () => {
]);
});
- it("saves the send shortcut setting and warns about Obsidian hotkeys", async () => {
+ it("saves the send shortcut setting and describes newline behavior", async () => {
const saveSettings = vi.fn().mockResolvedValue(undefined);
const tab = newSettingsTab({ saveSettings });
@@ -131,8 +131,8 @@ describe("settings tab", () => {
await flushPromises();
expect(saveSettings).toHaveBeenCalledOnce();
- expect(settingDesc(tab, "Send shortcut")).toContain("Obsidian hotkeys");
- expect(tab.containerEl.querySelector(".codex-panel-settings__section-status")?.textContent ?? "").not.toContain("Obsidian hotkeys");
+ expect(settingDesc(tab, "Send shortcut")).toContain("Shift+Enter adds a newline");
+ expect(tab.containerEl.querySelector(".codex-panel-settings__section-status")?.textContent ?? "").not.toContain("Shift+Enter");
});
it("saves the toolbar visibility setting and refreshes open panels", async () => {
@@ -150,7 +150,7 @@ describe("settings tab", () => {
expect(saveSettings).toHaveBeenCalledOnce();
expect(refreshOpenViews).toHaveBeenCalledOnce();
- expect(settingDesc(tab, "Show chat toolbar")).toContain("Slash commands");
+ expect(settingDesc(tab, "Show chat toolbar")).toContain("toolbar above the chat panel");
});
it("saves the composer edge scroll setting", async () => {
@@ -198,10 +198,9 @@ describe("settings tab", () => {
await flushPromises();
expect(saveSettings).toHaveBeenCalledTimes(4);
- expect(tab.containerEl.textContent).toContain("title, thread_id, created, and optional tags");
expect(settingDesc(tab, "Save note by default")).toContain("default archive action");
- expect(settingDesc(tab, "Save note by default")).toContain("If saving fails");
- expect(settingDesc(tab, "Saved note tags")).toContain("Leave empty to omit tags");
+ expect(settingDesc(tab, "Saved note filename")).toContain("{{shortId}}");
+ expect(settingDesc(tab, "Saved note tags")).toContain("separated by commas");
});
it("refreshes models, hooks, and archived threads from the global refresh button", async () => {
@@ -730,7 +729,7 @@ describe("settings tab", () => {
tab.display();
await flushPromises();
- expect(tab.containerEl.textContent).toContain("Restore archived threads, or permanently delete archived threads you no longer need.");
+ expect(tab.containerEl.textContent).toContain("Restore or permanently delete archived Codex threads.");
expect(tab.containerEl.textContent).not.toContain("Loaded 1 hook from Codex app server.");
expect(tab.containerEl.textContent).not.toContain("Loaded 1 archived thread from Codex app server.");
expect(tab.containerEl.querySelector(".codex-panel-settings__hook-section .setting-item-heading")?.textContent).toContain(