Skip to content

feat(permissions): support kilo, augmentcode, cline, qwencode#1585

Merged
dyoshikawa merged 5 commits into
mainfrom
permissions
Apr 30, 2026
Merged

feat(permissions): support kilo, augmentcode, cline, qwencode#1585
dyoshikawa merged 5 commits into
mainfrom
permissions

Conversation

@dyoshikawa
Copy link
Copy Markdown
Owner

Summary

  • Add permissions feature support for Kilo Code, AugmentCode, Cline, and Qwen Code.
  • Apply fail-closed translation semantics: ambiguous source rules (e.g. Cline ask) are translated to deny rather than silently dropped.
  • Use additive merge for deny arrays (preserve user-added denies) while keeping allow/ask wholesale-replace.
  • Kilo Code: per-key merge of kilo.jsonc permission keys with aggregated warning when replacing a key drops existing deny patterns.
  • AugmentCode: preserve any existing toolPermissions[] entry whose permission.type === "deny" for managed canonical tool names (broadened from launch-process only); preserved denies are sorted before generated catch-all allows under first-match-wins.
  • Qwen Code: Claude-style Bash(...)/Read(...) parsing with lastIndexOf(')') to handle nested parens.

This is a re-submission of the closed PR #1338 with three rounds of review fixes already squashed in.

Test plan

  • pnpm cicheck (format / oxlint / eslint / typecheck / cspell / secretlint / sync-skill-docs / 5455 tests)
  • Tool × Feature happy-path E2E matrix preserved
  • Manual pnpm dev gitignore check if .gitignore updates required

Refs #1338

🤖 Generated with Claude Code

dyoshikawa and others added 5 commits April 29, 2026 02:00
Implements the permissions feature for four additional tool targets so
.rulesync/permissions.json now generates and imports for:

- kilo (Kilo Code) — issue #1417 — kilo.jsonc with OpenCode-style
  permission object; project + global support
- augmentcode (Auggie CLI) — issue #1418 — .augment/settings.json with
  toolPermissions[] (allow/deny/ask-user); project + global; bash maps
  to launch-process with shellInputRegex
- cline (Cline CLI) — issue #1420 — .cline/command-permissions.json
  matching the CLINE_COMMAND_PERMISSIONS env shape; project only;
  bash-only with warnings for ask and non-bash categories
- qwencode (Qwen Code) — issue #1422 — .qwen/settings.json with Claude
  Code style permissions.allow/ask/deny arrays; project + global

Wires the new classes into PermissionsProcessor with appropriate
project/global/import meta flags, extends the e2e suite with happy-path
generate + import + global coverage, and updates the supported-tools
matrix and per-tool format docs (with skills/rulesync sync).

Closes #1417
Closes #1418
Closes #1420
Closes #1422

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ode/cline/qwencode

Addresses 18 reviewer findings raised on PR #1338. Highlights:

- #1 (critical): AugmentCode non-bash categories now fail-closed. A single
  deny rule in `read`/`edit`/`write`/`webfetch`/`websearch` collapses the
  whole tool to a catch-all `deny` entry; non-`*` allow/ask patterns are
  dropped with an aggregated warning instead of being silently downgraded
  to a catch-all `allow` that would shadow a deny.
- #2 (high): `toolPermissions` are sorted to make AugmentCode's
  first-match-wins evaluation safe — entries with `shellInputRegex` come
  before catch-alls, longer regex first, with deny < ask-user < allow as
  the tiebreaker.
- #5 (mid): existing `launch-process` deny entries are preserved across
  regeneration so a user-added shell deny rule cannot be silently
  downgraded; non-deny launch-process entries are still owned by rulesync.
- #3 (mid): Qwencode generation uses `readFileContentOrNull` (no
  `readOrInitializeFileContent`) so dry-run does not create the `.qwen/`
  directory.
- #4 (mid): Kilo schema parsing is deferred and respects `params.validate`,
  so `forDeletion` and dry-run construction never throw on permissive input.
- #7, #16 (mid/low): Cline drops non-bash / ask rules at `logger.error`
  level (rather than warn) and surfaces a defensive warn on allow/deny
  pattern collisions.
- #8, #13 (mid/low): Qwencode pattern parser uses the LAST `)` so nested
  parentheses (e.g. `Bash(echo (a))`) round-trip; malformed entries warn
  and fall back to `*`.
- #9 (low): Augment non-bash warnings are aggregated once per category.
- #11 (low): Kilo's wholesale-replace of the `permission` object is
  documented in `docs/reference/file-formats.md`.
- #10, #6 (low): glob→regex behaviour and round-trip caveats are
  documented.
- #14 (low): `mergedPermissions` is typed as
  `{ allow?: string[]; ask?: string[]; deny?: string[]; [k: string]: unknown }`.
- #15 (low): redundant Qwencode global-mode equivalence assert removed.
- #17 (low): `permissions-processor.test.ts` gains `loadToolFiles` cases
  for AugmentCode, Cline, Kilo, and Qwencode.

Deferred:
- #12 (kilo home-mock migration): the existing kilo global-mode test
  already passes `outputRoot` directly and does not reach
  `getHomeDirectory()`, so introducing the home-mock pattern adds only
  ceremony without coverage.
- #18 (tool-name-mapping helper extraction): postponed to keep this
  fix focused and to avoid touching files outside the permissions
  feature.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- #1 (mid): augmentcode-permissions sort the COMBINED [generated, preserved] entries so a preserved launch-process deny cannot be shadowed by a generated catch-all allow/ask under first-match-wins. Adds regression test.

- #2 (low): sortAugmentEntries applies fail-closed type priority (deny < ask-user < allow) BEFORE the regex-length heuristic for has-regex entries. Heuristic limits documented in code.

- #3 (low): cline-permissions downgrades translation-loss logs from logger.error to a single aggregated logger.warn per call (project convention; CI gates that treat error lines as failures no longer trip).

- #4 (low): documents in docs/reference/file-formats.md (and synced skills/rulesync/file-formats.md) that Cline allow/deny arrays are owned by rulesync entirely (no preservation), in contrast to Qwen Code and AugmentCode.

- #5 (low): qwencode-permissions forwards a logger to parseQwenPermissionEntry from both call sites (preservation filter and convertQwenToRulesyncPermissions) so the malformed-entry warnings are no longer dead code in production.

- #6 (low): qwencode-permissions.test extends the nested-paren round-trip test to cover sequential parens (Bash(grep (foo) | wc (-l))) and multi-nesting (Bash(echo ((deep)))).
…code/kilo

- cline: translate ask rules to deny (fail-closed) since Cline lacks ask
  semantics; preserve user-added denies on regenerate (additive deny while
  allow stays wholesale-replaced).
- augmentcode: extend deny preservation to all managed tool names (view,
  str-replace-editor, save-file, web-fetch, web-search), not just
  launch-process; sort comparator continues to keep preserved denies before
  generated catch-all allows under first-match-wins.
- kilo: per-key merge of permission map. Tool keys present in rulesync output
  replace the corresponding key entirely; tool keys present only in the
  existing kilo.jsonc are preserved verbatim. Aggregated logger.warn lists
  any deny patterns dropped when a key is replaced.
- docs: synchronize docs/reference/file-formats.md and skills/rulesync/
  file-formats.md with the new semantics.
…/augmentcode

- Kilo: throw on malformed JSONC instead of silent fallback to {}

- Qwen: drop malformed Bash(...) entries from allow/ask (deny still falls back to "*")

- AugmentCode: import-side fail-closed precedence for managed non-bash tool collisions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dyoshikawa dyoshikawa merged commit a3beaa9 into main Apr 30, 2026
9 checks passed
@dyoshikawa dyoshikawa deleted the permissions branch April 30, 2026 04:07
@dyoshikawa
Copy link
Copy Markdown
Owner Author

@dyoshikawa Thank you!

lgaudez pushed a commit to lgaudez/rulesync that referenced this pull request May 1, 2026
…yoshikawa#1585

Refs: dyoshikawa#1571, dyoshikawa#1587

Issue dyoshikawa#1571 (--input-root follow-ups):
- import.ts: clarify warning suppression scope in comment
- add inputRoot threading assertions to rules/subagents/skills/hooks/permissions/ignore processor tests
- validateBaseDir: make '..' segment check platform-aware

Issue dyoshikawa#1587 (permissions follow-ups):
- cline/augmentcode/qwencode: implement real validate() via safeParse
- gitignore-entries: drop **/kilo.jsonc entry for parity with opencode.jsonc
- augmentcode: warn on non-roundtrippable shellInputRegex; deny falls back to '*' (fail-closed)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant