Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
c4c1f98
feat: Agent Plugins install/update UX (Settings + palette, managed in…
ThomasK33 Aug 20, 2026
d11b256
feat: mark the Plugins settings section experimental
ThomasK33 Aug 20, 2026
a324888
fix: address Codex review round 21
ThomasK33 Aug 20, 2026
f58205a
fix: address Codex review round 22
ThomasK33 Aug 20, 2026
83ea913
fix: address Codex review round 23
ThomasK33 Aug 20, 2026
17a4469
fix: address Codex review round 24
ThomasK33 Aug 20, 2026
c935d8c
fix: address Codex review round 25
ThomasK33 Aug 20, 2026
583b2a5
fix: address Codex review round 26
ThomasK33 Aug 20, 2026
8894850
fix: address Codex review round 27
ThomasK33 Aug 20, 2026
17fdca3
fix: address Codex review round 28
ThomasK33 Aug 20, 2026
6689c05
fix: address Codex review round 29
ThomasK33 Aug 20, 2026
f7494e5
fix: address Codex review round 30
ThomasK33 Aug 20, 2026
710d15c
fix: address Codex review round 31
ThomasK33 Aug 20, 2026
adc540e
fix: address Codex review round 32
ThomasK33 Aug 21, 2026
07ddfca
fix: address Codex review round 33
ThomasK33 Aug 21, 2026
472e34f
fix: address Codex review round 34
ThomasK33 Aug 21, 2026
67f4d46
fix: address Codex review round 35
ThomasK33 Aug 21, 2026
1b1afe8
fix: address Codex review round 36
ThomasK33 Aug 21, 2026
6041218
fix: address Codex review round 37
ThomasK33 Aug 21, 2026
ea63dca
fix: address Codex review round 38
ThomasK33 Aug 21, 2026
d65c5c3
fix: address Codex review round 39
ThomasK33 Aug 21, 2026
8abee7d
fix: address Codex review round 40
ThomasK33 Aug 21, 2026
cb8dca3
fix: address Codex review round 41
ThomasK33 Aug 21, 2026
fe409fa
fix: address Codex review round 42
ThomasK33 Aug 21, 2026
0ffe007
fix: address Codex review round 43
ThomasK33 Aug 21, 2026
e4c6be6
fix: address Codex review round 44
ThomasK33 Aug 21, 2026
182dca4
fix: address Codex review round 45
ThomasK33 Aug 21, 2026
d9ef467
fix: address Codex review round 46
ThomasK33 Aug 21, 2026
d7e9b1c
fix: address Codex review round 47
ThomasK33 Aug 21, 2026
1ee5bc0
fix: address Codex review round 48 + Integration ENOENT unwrapping
ThomasK33 Aug 21, 2026
6d5c796
fix: address Codex review round 49 (registration-time sanitization ha…
ThomasK33 Aug 21, 2026
4d2a897
fix: address Codex review round 50 (cross-process safety + symlink fi…
ThomasK33 Aug 21, 2026
f5348d6
fix: address Codex review round 51 (worktree cleanup + symlink-safe p…
ThomasK33 Aug 21, 2026
168b735
fix: address Codex review round 52 (cross-process override serializat…
ThomasK33 Aug 21, 2026
040f040
fix: address Codex review round 53 (canonical validator keys + fork s…
ThomasK33 Aug 21, 2026
918bcbf
Merge origin/main (.xum canonical project metadata) into agent-plugin…
ThomasK33 Aug 21, 2026
fac3179
fix: address Codex review round 54 (lock reclaim race, consent-surfac…
ThomasK33 Aug 21, 2026
5c02797
fix: address Codex review round 55 (git hooks in staging clones, fork…
ThomasK33 Aug 21, 2026
84964a0
fix: address Codex review round 56 (lock reclaim redesign, raw duplic…
ThomasK33 Aug 21, 2026
21f7819
fix: address Codex review round 57 (lock publication + release atomic…
ThomasK33 Aug 21, 2026
cdec127
fix: sanitize task worktrees before first send (Codex round 57)
ThomasK33 Aug 21, 2026
d41f5f3
fix: address Codex review round 58 (release owns() recheck, task sani…
ThomasK33 Aug 21, 2026
764b481
fix: validate agent definitions before fingerprinting (Codex round 59)
ThomasK33 Aug 21, 2026
d9f1a37
fix: address Codex review round 60 (lease renewal, delta tombstone pe…
ThomasK33 Aug 21, 2026
eeaf6d2
Merge remote-tracking branch 'origin/main' into agent-plugin-install-ux
ThomasK33 Aug 22, 2026
7c035e1
fix: address Codex review round 61 (retry-side live re-enumeration fo…
ThomasK33 Aug 22, 2026
6293dfe
fix: realm-safe ENOENT detection in mutation epoch reads + unreadable…
ThomasK33 Aug 22, 2026
e9fb022
fix: address Codex review round 62 (git config isolation for staging,…
ThomasK33 Aug 22, 2026
e2924f9
fix: address Codex review round 63 (atomic journal publication, zero-…
ThomasK33 Aug 22, 2026
12e02f5
fix: join the in-flight lease renewal on lock release so a stalled ti…
ThomasK33 Aug 22, 2026
6d12bf5
fix: address Codex review round 65 (exclusive mutex owner publication…
ThomasK33 Aug 22, 2026
9e113da
fix: load disk overrides on a workspace's first serve so a stale call…
ThomasK33 Aug 22, 2026
6a708bf
fix: address Codex review round 67 (recheck override cache after firs…
ThomasK33 Aug 22, 2026
908adb5
fix: reject nested plugin:// workflow paths so the executable set mat…
ThomasK33 Aug 22, 2026
4b6d9be
fix: address Codex review round 69 (bounded same-handle hook source r…
ThomasK33 Aug 22, 2026
35b8e89
fix: address Codex review round 70 (pre-read size checks for agents/s…
ThomasK33 Aug 22, 2026
aac2280
fix: refuse symlinked hooks.js at the consuming read (Codex round 71 P2)
ThomasK33 Aug 22, 2026
3bca011
fix: wire direct CLI sessions into plugin override sanitization (Code…
ThomasK33 Aug 22, 2026
d59e33e
fix: recheck hook path containment against the plugin root at read ti…
ThomasK33 Aug 22, 2026
f98dd52
fix: default-wire WorkspaceMcpOverridesService in createCoreServices …
ThomasK33 Aug 22, 2026
7b9ad86
fix: revalidate mcp.json reads and retire live hooks on plugin mutati…
ThomasK33 Aug 22, 2026
7110a0d
fix: scan the persistent config for live siblings in CLI sanitization…
ThomasK33 Aug 22, 2026
d62ab3e
fix: fail closed on unreadable persistent config and bound realpath i…
ThomasK33 Aug 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/agents/agent-skills.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ Enable the **Agent Plugins** experiment (Settings β†’ Experiments) to also disco

Plugin skills have the lowest precedence within their scope and are read-only. A broken plugin (or a broken skill inside one) never affects other plugins or skills. Plugins can also ship MCP servers; see [MCP servers](/config/mcp-servers#agent-plugins-servers-experiment).

Global plugins can be installed from git via **Settings β†’ Plugins** (paste a git URL or `owner/repo[@ref]`); the install preview lists every skill the plugin would contribute before anything is written.

## Skill layout

A skill is a directory named after the skill:
Expand Down
2 changes: 2 additions & 0 deletions docs/config/mcp-servers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ With the **Agent Plugins** experiment enabled (Settings β†’ Experiments), MCP se

Stdio plugin servers launch with the spec's `PLUGIN_ROOT` and `PLUGIN_DATA` environment variables; per-plugin data directories live under `~/.xum/plugin-data/`.

**Settings β†’ Plugins** installs plugins from git into `~/.xum/plugins` (paste a git URL or `owner/repo[@ref]`); the exact location derives from the active Xum home (a legacy `~/.mux` home keeps working) and is shown in the section. Before anything is written, a consent preview lists the plugin's manifest, every skill, and every MCP server command line. Installs are pinned to the resolved commit; update checks compare the tracked branch or tag against the pinned commit and never auto-apply. Applying an update replaces the plugin directory wholesale β€” local edits to a managed plugin directory are discarded β€” and restarts that plugin's running MCP servers. Uninstalling removes the directory, the registry entry, and the plugin's per-workspace server overrides, but keeps `~/.xum/plugin-data/` unless you opt in to deleting it.

## Behavior

- **Hot reload** β€” Config changes apply on your next message (no restart needed)
Expand Down
2 changes: 2 additions & 0 deletions src/browser/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ function AppInner() {

const [isMultiProjectWorkspaceModalOpen, setMultiProjectWorkspaceModalOpen] = useState(false);
const multiProjectWorkspacesEnabled = useExperimentValue(EXPERIMENT_IDS.MULTI_PROJECT_WORKSPACES);
const agentPluginsEnabled = useExperimentValue(EXPERIMENT_IDS.AGENT_PLUGINS);

// Left sidebar is drag-resizable (mirrors RightSidebar). Width is persisted globally;
// collapse remains a separate toggle and the drag handle is hidden in mobile-touch overlay mode.
Expand Down Expand Up @@ -993,6 +994,7 @@ function AppInner() {
onStartWorkspaceCreation: openNewWorkspaceFromPalette,
onStartMultiProjectWorkspaceCreation: openNewMultiProjectWorkspaceFromPalette,
multiProjectWorkspacesEnabled,
agentPluginsEnabled,
onArchiveMergedWorkspacesInProject: archiveMergedWorkspacesInProjectFromPalette,
getBranchesForProject,
onSelectWorkspace: selectWorkspaceFromPalette,
Expand Down
17 changes: 13 additions & 4 deletions src/browser/components/WorkspaceMCPModal/WorkspaceMCPModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export const WorkspaceMCPModal: React.FC<WorkspaceMCPModalProps> = ({
// State for project servers and workspace overrides
const [servers, setServers] = useState<Record<string, MCPServerInfo>>({});
const [overrides, setOverrides] = useState<WorkspaceMCPOverrides>({});
// Revision of the loaded overrides snapshot. Saves pass it back so the
// backend can reject stale snapshots (e.g. after a plugin uninstall pruned
// this workspace's plugin: keys while the dialog was open).
const [overridesRevision, setOverridesRevision] = useState<string | null>(null);
const [loadingTools, setLoadingTools] = useState<Record<string, boolean>>({});
const [loading, setLoading] = useState(false);
const [saving, setSaving] = useState(false);
Expand Down Expand Up @@ -66,7 +70,8 @@ export const WorkspaceMCPModal: React.FC<WorkspaceMCPModalProps> = ({
api.workspace.mcp.get({ workspaceId }),
]);
setServers(projectServers ?? {});
setOverrides(workspaceOverrides ?? {});
setOverrides(workspaceOverrides.overrides ?? {});
setOverridesRevision(workspaceOverrides.revision);
Comment thread
ThomasK33 marked this conversation as resolved.
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to load MCP configuration");
} finally {
Expand Down Expand Up @@ -235,11 +240,15 @@ export const WorkspaceMCPModal: React.FC<WorkspaceMCPModalProps> = ({

// Save overrides
const handleSave = useCallback(async () => {
if (!api) return;
if (!api || overridesRevision === null) return;
setSaving(true);
setError(null);
try {
const result = await api.workspace.mcp.set({ workspaceId, overrides });
const result = await api.workspace.mcp.set({
workspaceId,
overrides,
expectedRevision: overridesRevision,
});
if (!result.success) {
setError(result.error);
} else {
Expand All @@ -250,7 +259,7 @@ export const WorkspaceMCPModal: React.FC<WorkspaceMCPModalProps> = ({
} finally {
setSaving(false);
}
}, [api, workspaceId, overrides, onOpenChange]);
}, [api, workspaceId, overrides, overridesRevision, onOpenChange]);

const serverEntries = Object.entries(servers);

Expand Down
Loading
Loading