feat(jetbrains): show verbatim skill commands and skill name in permission prompt - #12724
Conversation
Code Review SummaryStatus: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (4 files, incremental)Incremental review of
Resolved / verified during review
Fix these issues in Kilo Cloud Previous Review Summary (commit 86e5507)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 86e5507)Status: 3 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (2 files, incremental)Incremental review of
Notes / verified during review
Reviewed by claude-opus-5 · Input: 28 · Output: 4.6K · Cached: 728.1K Review guidance: REVIEW.md from base branch |
| // repaint the prompt or use Trojan-Source reordering to make the displayed text differ from | ||
| // what executes; newlines become a visible marker. Mirrors displayCommand in the CLI | ||
| // (packages/opencode/src/kilocode/skills/display.ts); keep the ranges in sync. | ||
| private fun escapeControl(command: String): String = buildString { |
There was a problem hiding this comment.
Can we test this?
There was a problem hiding this comment.
There are already a couple of tests for this specifically (check these out), but I did a manual test too.
For the manual test, I added the following skill:
❯ cat escape-demo/SKILL.md
---
name: escape-demo
description: Demo skill to screenshot control/bidi character escaping in the permission card.
---
Result: !`printf 'safe-part-\u202ereversed-part'`and ran the following command in Kilo IntelliJ:
Can you use the escape-demo skill?Results are in the attached screenshot. The list of shell commands are indeed escaped in the approval prompt, confirming everything is working as expected 💪
…skill-context-jetbrains feat(jetbrains): show verbatim skill commands and skill name in permission prompt
Issue
https://docs.google.com/document/d/1eXKc_A9f_mVuc3LiniP3gbLWm7Ic_cPe58z1Tq_ZlzY/
Context
Skills can embed shell commands in a
SKILL.mdusing!`command`syntax, gated by a single up-front approval that lists every command — shipped in the CLI/TUI backend in #12604 (merged tomain).That PR already wired JetBrains' extension-host reply plumbing so approvals work (the
interactive: trueflag satisfies the server's non-interactive-reply refusal for skill-shell batches), but never updated the permission card to display the batch distinctly — a skill-shell request rendered as a generic bash permission, showing the backend's decomposed authorization patterns rather than the verbatim commands that execute.This PR is the JetBrains counterpart to the VS Code fix in #12606: it makes the card show exactly what will run and which skill triggered it, matching the CLI TUI.
Implementation
The backend already sends
metadata.skillShell,metadata.skill, andmetadata.commands(verbatim, per-placeholder) on the permission request; this data already flows into the JetBrains backend's flat metadata map, so the change is display-layer only acrossshared/backend/frontend.ChatDto/KiloCliDataParser: extractmetadata.commandsinto a newskillCommands: List<String>field onPermissionRequestDto— the flatMap<String, String>metadata can't carry a JSON array, so it needs its own typed field, extracted via aJsonObject?.skillCommands()helper matching the file's existingpath()/ruleDecisions()convention.SessionController/Permission: threadskillCommandsthrough to the view model.PermissionView.show(): for a skill-shellbashask, render the header asRun shell commands from skill "<name>"?and the body as the verbatimskillCommandslist — not the decomposedpatterns, which stripcdprefixes and split pipelines and so can differ from what actually executes. The siblingexternal_directoryask (same metadata, when a command touches a directory outside the project) keeps its normal directory-pattern rendering; only the title carries the skill attribution for that one.escapeControl, covering both ASCII control chars and the bidi/format Unicode range (U+200E/F,U+2028/29,U+202A–E,U+2066–9) — mirrorsdisplayCommandin the CLI (packages/opencode/src/kilocode/skills/display.ts) so a command can't repaint the card or use Trojan-Source reordering to make the displayed text lie about what runs.rules.update(if (skillShell) emptyList() else ...)), rather than relying on today's incidental emptyruleDecisions— future-proofs against a backend change that starts sending rule candidates alongsideskillShellmetadata.packages/kilo-jetbrains/is entirely Kilo-owned, so nokilocode_changemarkers are involved.How to Test
Manual/local verification
Verified locally by the author in a sandboxed IntelliJ instance (repo-CLI mode) using the
git-statustest skill:Run shell commands from skill "git-status"?and lists both verbatim commands.interactive: truereply from feat(tui): execute cmds in skill context #12604 is unaffected by this PR).Reviewer test steps
kilo.cli.pinned=falseinpackages/kilo-jetbrains/gradle.properties(this feature is unreleased — the pinned CLI predates it) and build the local CLI:cd packages/kilo-jetbrains ./gradlew :backend:buildRepoCli