Summary
When a user changes a plugin's config via the UI (Settings > Plugins > Configure), the registered tools of that plugin keep using the OLD config until the plugin is explicitly deactivated/reactivated (or the service is restarted). Newly saved config values silently do not apply to subsequent tool invocations.
Reproduction
- Install and activate the
claude-code plugin.
- Leave
binaryPath empty in the config, save.
- Trigger
plugin_claude-code_claude_code_run from a Kin. The session will fail with "Claude Code native binary not found".
- Open the plugin config in the UI, set
binaryPath to a valid value (e.g. /home/user/kinbot/node_modules/@anthropic-ai/claude-agent-sdk-linux-x64/claude), save.
- Without restarting/reactivating, trigger
plugin_claude-code_claude_code_run again.
- Expected: the new
binaryPath is used, the session starts.
- Actual: the old (empty)
binaryPath is still used, the error repeats.
Workaround today: toggle the plugin off and on from the UI, or restart kinbot.service. Both work because they force a fresh activate() call.
Root cause hypothesis
Plugin tools are registered once during activate(ctx) and the ctx.config is captured by closure in the tool's create() factory or in the inner execute(). When configure_plugin (or the equivalent UI call) updates the stored config, nothing invalidates the captured reference.
Relevant code paths to audit:
src/server/services/plugins.ts: search for activate(ctx) and how ctx.config is provided. If it's a plain object snapshot (which it appears to be from past audits, see commit 94baaa85 for claude-code plugin), config mutations after activation are invisible to running tools.
src/server/routes/plugins.ts (or wherever configure_plugin lands): check whether saving config triggers a deactivate -> activate cycle on the affected plugin. If not, the config write is silent.
- Pattern reference:
plugins/claude-code/index.ts captures config: ClaudeCodeConfig from the outer activate(ctx) and uses it inside launchSession via closure. Same pattern likely in twilio-sms, teamspeak, home-automation.
Proposed fix (one of)
Option A (simplest, recommended): when configure_plugin saves a config change, automatically deactivate then reactivate the plugin. UX feedback: small toast "Plugin reloaded with new config". This is what users do manually today, just automated. Acceptable behavior for the few-second blip.
Option B (more refined): give plugins a live config reference instead of a snapshot. The ctx.config becomes a getter that reads from the store on every access. Plugin tools naturally see fresh values. More invasive (touches PluginContext shape) but no reload required.
Option C: emit a plugin:config-changed event that the plugin can subscribe to, allowing it to refresh its own state. Most flexible but adds API surface and plugin author burden.
Option A is the lowest-cost fix for users. Option B is the cleanest long-term answer. Either is acceptable; pick based on how invasive the audit shows the closure capture to be across the 6 existing plugins.
Acceptance criteria
- Saving a plugin config from the UI (or via
configure_plugin tool) causes subsequent tool invocations to use the new values, without any user action.
- All 6 existing plugins (
claude-code, twilio-sms, teamspeak, home-automation, example-weather, example-provider) continue to work correctly.
- Brief documentation note in
docs/plugins.md explaining the behavior (especially relevant for plugin authors using Option B or C).
Observed environment
- KinBot v0.41.0
- systemd user service (user: marlburrow)
- claude-code plugin v0.1.0
- Reported by MarlBurroW directly during a live test on May 12, 2026.
Summary
When a user changes a plugin's config via the UI (Settings > Plugins > Configure), the registered tools of that plugin keep using the OLD config until the plugin is explicitly deactivated/reactivated (or the service is restarted). Newly saved config values silently do not apply to subsequent tool invocations.
Reproduction
claude-codeplugin.binaryPathempty in the config, save.plugin_claude-code_claude_code_runfrom a Kin. The session will fail with "Claude Code native binary not found".binaryPathto a valid value (e.g./home/user/kinbot/node_modules/@anthropic-ai/claude-agent-sdk-linux-x64/claude), save.plugin_claude-code_claude_code_runagain.binaryPathis used, the session starts.binaryPathis still used, the error repeats.Workaround today: toggle the plugin off and on from the UI, or restart
kinbot.service. Both work because they force a freshactivate()call.Root cause hypothesis
Plugin tools are registered once during
activate(ctx)and thectx.configis captured by closure in the tool'screate()factory or in the innerexecute(). Whenconfigure_plugin(or the equivalent UI call) updates the stored config, nothing invalidates the captured reference.Relevant code paths to audit:
src/server/services/plugins.ts: search foractivate(ctx)and howctx.configis provided. If it's a plain object snapshot (which it appears to be from past audits, see commit94baaa85forclaude-codeplugin), config mutations after activation are invisible to running tools.src/server/routes/plugins.ts(or whereverconfigure_pluginlands): check whether saving config triggers adeactivate -> activatecycle on the affected plugin. If not, the config write is silent.plugins/claude-code/index.tscapturesconfig: ClaudeCodeConfigfrom the outeractivate(ctx)and uses it insidelaunchSessionvia closure. Same pattern likely intwilio-sms,teamspeak,home-automation.Proposed fix (one of)
Option A (simplest, recommended): when
configure_pluginsaves a config change, automatically deactivate then reactivate the plugin. UX feedback: small toast "Plugin reloaded with new config". This is what users do manually today, just automated. Acceptable behavior for the few-second blip.Option B (more refined): give plugins a live config reference instead of a snapshot. The
ctx.configbecomes a getter that reads from the store on every access. Plugin tools naturally see fresh values. More invasive (touchesPluginContextshape) but no reload required.Option C: emit a
plugin:config-changedevent that the plugin can subscribe to, allowing it to refresh its own state. Most flexible but adds API surface and plugin author burden.Option A is the lowest-cost fix for users. Option B is the cleanest long-term answer. Either is acceptable; pick based on how invasive the audit shows the closure capture to be across the 6 existing plugins.
Acceptance criteria
configure_plugintool) causes subsequent tool invocations to use the new values, without any user action.claude-code,twilio-sms,teamspeak,home-automation,example-weather,example-provider) continue to work correctly.docs/plugins.mdexplaining the behavior (especially relevant for plugin authors using Option B or C).Observed environment