Skip to content

[FEATURE]: endpoint to deactivate or remove a session skill #54346

Open

Description

@AmineAce

Describe the enhancement you want to request

A session-scoped way to deactivate/remove an already-activated skill — the missing counterpart to session.skill().

Problem

Activating a skill in a session is one-way. The v2.0.26 surface is add-only:

  • session.skill({ sessionID, id, resume }) — injects the skill into the session (the synthetic skill message the model then sees)
  • skill.list() — lists the catalog
  • session.skill.activated — event for UIs to refresh
  • Nothing removes it. Re-calling session.skill with resume:false is a no-op; the only way out is deleting the session.

Concrete case from my own setup: a session has had the ads skill active since I first activated it while building a skill-picker UI. I cannot turn it off. Every turn since, that session has carried the ads instruction block in context, even for tasks that have nothing to do with ads.

Why this is worth having:

  1. Every other session-scoped action is reversible — skills are the exception. There is session.revert, switchAgent, switchModel, fork… but one spacebar press in a skill picker permanently commits an instruction block to the rest of the session.
  2. Real token cost that can never be reclaimed. Each activated skill injects its SKILL.md body (often 0.5–1.5 KB) into system context for every subsequent turn. Once a UI makes activation a single keystroke, users accumulate active skills quickly — one of my sessions sits at 8 — and there is no way to trim.
  3. Interactive UIs are half-built without it. The builtin /skills picker can only invoke. The in-flight sidebar work (feat(tui): show active skills in session sidebar #48461 / [FEATURE]: Show active session skills in the UI (sidebar, like MCP/TODO/LSP) and keep the model aware of them during the session #48355) can only display. A TUI plugin I've built (sidebar "active skills" widget + searchable picker that activates via session.skill) cannot offer deactivation at all — and with activation being irreversible, every misclick is permanent for that session. A picker without an off switch is a trap.
  4. The server already has a per-session "skill dropped" concept — it's just unreachable. Plugin reload during a turn fails the step retry and marks every skill as removed #51128 shows the harness emitting "the following skills are no longer available and must not be used" when a plugin reload rebuilds the catalog. That path is only reachable today as a side effect of a reload; users and UIs cannot trigger the equivalent deliberately.

What I'm explicitly not asking for

  • Removing a skill from the catalog (globally). Plugins can already do that via transform (SkillEditor.remove() at registration time) — but it is server-wide, not per-session, and requires owning a plugin.
  • Rewriting session history. The minimal ask: stop injecting the skill from the next turn on. (Making the synthetic activation message deletable would be a nice stretch goal, but plain "no longer injected" is enough to unblock UIs.)

Suggested shape (maintainers' call)

Mirror the activation path:

  • session.skill({ sessionID, id, remove: true }) or DELETE /session/{id}/skill/{skillID}, and
  • a session.skill.removed (or .deactivated) event so sidebar/picker UIs can refresh the same way they do on session.skill.activated.

Semantics: subsequent turns don't see the skill in context; no model call is resumed (same as resume:false on activation); idempotent.

Related (checked before filing)

OpenCode v2.0.26, Linux. Happy to test early builds — I already have a working TUI picker plugin and would wire up the off switch the day the endpoint exists.

Activity

  1. opencode-agent commented on Oct 10, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed write-up, @AmineAce!

    In short, you're asking for a per-session way to turn off a skill that's already been activated: an endpoint or option that mirrors session.skill(), plus a matching event so picker/sidebar UIs can refresh. From the next turn on, the model would no longer get that skill. The catalog and the session history would stay as they are.

    I checked the code: an activated skill is stored as a skill message in the session history and is sent to the model on every later turn. Nothing removes it or skips it yet, so you're right that there's currently no way to turn it off.

    Related issues:

    Maintainers will consider this. Thanks for offering to test builds and wire it into your picker plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions