How Disabling a Plugin Affects Its Configuration in Pi Web

When you disable a plugin in Pi Web, the system purges the plugin’s runtime configuration by emptying its extensions arrays for skills, prompts, and themes in ~/.pi/agent/settings.json while preserving the disabled: true flag and keeping the package installed on disk.

In the Pi Web ecosystem (maintained in the agegr/pi-web repository), plugins are managed through a combination of UI controls and API endpoints that directly manipulate the agent settings. Unlike a simple toggle that merely changes an active state, the disable operation performs a destructive cleanup of the plugin’s contributed extensions, ensuring no residual configuration remains in the running agent.

What Happens to Plugin Configuration on Disable

Each installed plugin in Pi Web maintains an entry in the Pi settings file located at ~/.pi/agent/settings.json. When you disable a plugin—either through the PluginsConfig UI or by calling the /api/plugins endpoint directly—the backend performs a specific sequence of operations that alters this configuration structure.

The system sets the disabled property to true and simultaneously empties all extension arrays. Specifically, the extensions object containing the skills, prompts, and themes arrays is cleared:

{
  "name": "my-plugin",
  "disabled": true,
  "extensions": {
    "skills": [],
    "prompts": [],
    "themes": []
  }
}

This purging ensures that disabled plugins contribute no functionality to the agent while remaining available for reactivation without requiring reinstallation.

Frontend Implementation: Triggering the Disable Action

The disable workflow originates in components/PluginsConfig.tsx, where the UI renders a toggle button for each installed package:

// components/PluginsConfig.tsx (excerpt)
<button
  onClick={() => onAction(pkg.disabled ? "enable" : "disable", pkg)}
  disabled={busy}
  style={buttonStyle(pkg.disabled)}
>
  {pkg.disabled ? t("i18n.enablePackage") : t("i18n.disablePackage")}
</button>

When a user clicks to disable an active plugin, the component calls onAction with the "disable" string, which invokes the pluginAction helper defined in lib/agent-client.ts. This helper constructs a POST request to the backend:

// lib/agent-client.ts
export async function pluginAction(
  pkg: PackageInfo,
  action: "install" | "remove" | "update" | "disable" | "enable"
) {
  const resp = await fetch(`/api/plugins`, {
    method: "POST",
    body: JSON.stringify({ pkg, action }),
    headers: { "Content-Type": "application/json" },
  });
  return resp.json();
}

The function sends the package metadata along with the "disable" action type to the /api/plugins endpoint, initiating the configuration purge on the server side.

Backend Processing: Clearing Configuration Data

The server-side handler in app/api/plugins/route.ts processes the disable action by modifying the package configuration before persisting it to disk. While the actual implementation contains additional logic, the conceptual flow demonstrates the critical configuration transformation:

// app/api/plugins/route.ts (conceptual)
if (action === "disable") {
  // mark the package as disabled
  pkg.disabled = true;
  // clear its configuration extensions
  pkg.extensions = { skills: [], prompts: [], themes: [] };
  await savePackageConfig(pkg);
}

This operation explicitly clears the custom extensions that the plugin contributed, ensuring that no residual skills, prompts, or themes remain active in the agent’s runtime. The savePackageConfig function persists these changes to ~/.pi/agent/settings.json, leaving the plugin in a clean, inactive state.

Re-enabling and Configuration Rebuild

Disabling a plugin is reversible. When you later enable the plugin through the same UI or API endpoint, Pi Web rebuilds the configuration from scratch. The system re-scans the package contents on disk and repopulates the extensions arrays with any skills, prompts, and themes bundled in the plugin code.

This design guarantees that re-enabling always loads the current package state, preventing stale configuration from previous versions from persisting across disable/enable cycles.

Summary

  • Disabling purges extensions: The extensions object for skills, prompts, and themes is emptied in ~/.pi/agent/settings.json, removing all functional contributions from the active agent.
  • Package remains installed: The plugin files stay on disk; only the runtime configuration is cleared, allowing quick reactivation.
  • API-driven process: The frontend components in components/PluginsConfig.tsx and lib/agent-client.ts send disable commands via POST to /api/plugins.
  • Backend handles cleanup: The route handler in app/api/plugins/route.ts sets disabled: true and clears extension arrays before saving.
  • Re-enable rebuilds config: Toggling the plugin back on reconstructs the configuration from the package’s current contents.

Frequently Asked Questions

Does disabling a plugin delete its files from disk?

No. Disabling a plugin only affects the configuration stored in ~/.pi/agent/settings.json. The plugin package remains installed on disk, allowing you to re-enable it later without re-downloading or re-installing the package.

What specific configuration data is removed when disabling?

The system removes all entries from the three extension arrays within the plugin’s configuration object. Specifically, the skills, prompts, and themes arrays under extensions are emptied, while the disabled flag is set to true. This ensures no custom functionality from the plugin remains active in the agent.

How does the frontend communicate the disable action to the backend?

The PluginsConfig component triggers the pluginAction function from lib/agent-client.ts, which sends a POST request to /api/plugins with a JSON payload containing the package metadata and the action string "disable". The backend API then processes this request to update the settings file accordingly.

Can I recover a plugin's configuration after disabling it?

You cannot recover the previous runtime configuration because the arrays are emptied during the disable operation. However, re-enabling the plugin triggers a fresh configuration build from the package source code. If you need to preserve specific custom settings, you must backup the settings.json file before disabling the plugin.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →