Official

settings

Built-in settings UI (JavaScript UI plugin).

The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/settings@0.2.0

Permissions in 0.2.0

  • Manage plugins plugins.manageOfficial onlyReloads and enables plugins. Only official plugins can have it.List, enable, disable and reload plugins, install updates, and quit to finish an update
  • Change app settings settings.writeHighChanges the app settings.Change the settings and the theme
  • Manage agents agents.manageHighEnables, disables and signs in agents, and changes their settings.Turn agents on and off, sign in to them and update them
  • Control chats chats.controlHighCreates chats, sends prompts and cancels runs.Import an agent's own sessions as chats
  • Read chats chats.readMediumReads your transcripts and chat lists.List the workspaces an agent's sessions can be imported into
  • Read app settings settings.readLowReads the app settings.Show the settings, and the tools and rules of every plugin
  • Show panels ui.slotsLowShows views in the listed parts of the window.Draw the settings pageSlots: center

Files

views/general.ts4.7 KB
// The General section: appearance, runs, session import and the bug report.
// HTM whitespace is significant; keep these templates out of Prettier's HTML formatter.
import { html as htm } from "convergence";
import type { EffectViewContext } from "convergence/effect";
import type { SettingsPage } from "../controller.ts";
import { card, limit, section, segmented, setting, column } from "./layout.ts";

export function renderGeneral(ctx: EffectViewContext<object>, actions: SettingsPage["Service"]) {
  const state = actions.state;
  const s = state.settings;
  // `renderGeneral` runs only once the settings have loaded.
  if (!s) return htm`<empty>Loading…</empty>`;
  return htm`
      <div ...${column} gap="large" padding="small">
        ${section(
          "Appearance",
          null,
          card([
            setting({
              title: "Color scheme",
              description: "Follow the system, or keep one look.",
              control: segmented(
                "appearance",
                s.appearance,
                [
                  { value: "system", label: "System" },
                  { value: "light", label: "Light" },
                  { value: "dark", label: "Dark" },
                ],
                (value) => ctx.run(actions.changeAppearance(value)),
              ),
            }),
            setting({
              title: "Theme",
              description: "Presets, colours, type and density: the Themes plugin's settings.",
              control: htm`<button id="open-themes" label="Edit themes" onClick=${() => ctx.run(actions.openSection("plugin:themes", "themes"))} />`,
            }),
          ]),
        )}
        ${section(
          "Runs",
          null,
          card([
            setting({
              title: "Checkpoints",
              description:
                "Record the workspace before every prompt, so a message can be reverted together with the files it changed.",
              control: htm`<switch id="checkpoints" label="" checked=${s.checkpoints} onChange=${(e: { value: boolean }) => ctx.run(actions.updateSettings({ checkpoints: e.value }))} />`,
            }),
            setting({
              title: "Keep checkpoints for",
              description: "Older checkpoints are deleted, and their messages can no longer be reverted.",
              control: limit(
                "checkpoint-days",
                s.checkpointRetentionDays,
                [7, 14, 30, 90],
                (days) => `${days} days`,
                "Forever",
                (value) => ctx.run(actions.updateSettings({ checkpointRetentionDays: value })),
              ),
            }),
            setting({
              title: "Checkpoint storage limit",
              description: "Past this size the oldest checkpoints go first. Those from the last day are always kept.",
              control: limit(
                "checkpoint-size",
                s.checkpointMaxMegabytes,
                [512, 1024, 2048, 5120, 10240],
                (mb) => (mb < 1024 ? `${mb} MB` : `${mb / 1024} GB`),
                "No limit",
                (value) => ctx.run(actions.updateSettings({ checkpointMaxMegabytes: value })),
              ),
            }),
          ]),
        )}
        ${section(
          "Sessions",
          null,
          card([
            setting({
              title: "Import sessions",
              description: "Bring existing sessions from enabled agents into a workspace.",
              wide: true,
              control: htm`
              <div ...${column} gap="small" padding="small">
                <select id="import-workspace" value=${state.importWorkspace ?? ""} placeholder="Add a workspace first"
                  options=${state.workspaces.map((w) => ({ value: w.id, label: w.name }))}
                  onChange=${(e: { value: string }) => {
                    state.importWorkspace = e.value;
                    ctx.update();
                  }} />
                <button id="import-sessions" label="Import sessions" icon="inbox"
                  loading=${state.importing} disabled=${state.importing || !state.importWorkspace || !state.agents.some((agent) => agent.enabled)}
                  onClick=${() => ctx.run(actions.importSessions())} />
              </div>`,
            }),
          ]),
        )}
        ${section(
          "Help",
          null,
          card([
            setting({
              title: "Report a bug",
              description:
                "Tell us, or a plugin's publisher, what went wrong. You see everything that is sent before it goes.",
              control: htm`<button id="report-bug" label="Report a bug…" icon="bug" variant="outline" onClick=${() => ctx.run(actions.reportBug())} />`,
            }),
          ]),
        )}
      </div>`;
}

Versions

VersionPublishedPlugin APISizePermissionsStatus
0.2.0latestOct 5, 2026>=2 <324.7 KB7 permissionsListed

Reviews and comments

0 threads · 0 reviews

No comments yet.