Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1596751
feat(skills): add auto-skill curator
DragonnZhang Jul 27, 2026
d70df62
fix(i18n): translate /curator command descriptions for zh and zh-TW
claude Jul 27, 2026
91699bf
fix(i18n): add English source keys for /curator command
claude Jul 27, 2026
fc10834
fix(skills): align curator lifecycle safeguards
DragonnZhang Jul 28, 2026
d5a1c70
fix(skills): harden curator trust and name guards
DragonnZhang Jul 28, 2026
a0c943a
fix(skills): guard curator mutations by workspace trust
DragonnZhang Jul 28, 2026
2f8b325
test(skills): cover curator stale-to-active reactivation path
claude Jul 28, 2026
6ca1eb9
Merge branch 'main' into dragon/auto-skill-curator
claude Jul 28, 2026
70d1395
test(skills): cover curator rollback and restore-collision paths
claude Jul 28, 2026
f35f0fe
test(cli): cover curator command errors and stacked auto-skill usage
claude Jul 28, 2026
171ac3f
fix(skills): reject control-byte auto-skill directory names
claude Jul 28, 2026
1c3c030
fix(skills): guard curator state reads and clarify restore errors
claude Jul 28, 2026
4915a72
fix(skills): close curator TOCTOU reads and preserve seeding baseline
claude Jul 28, 2026
2bf5324
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot Jul 28, 2026
c95980b
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot Jul 28, 2026
f3814a1
fix(core): harden auto-skill curator per review feedback (#7846)
qwen-code-dev-bot Jul 28, 2026
8d4b0a4
test(core): cover curator restore rollback and re-read guard (#7846)
qwen-code-dev-bot Jul 28, 2026
f7e2178
fix(core): record auto-skill usage on re-invocation (#7846)
qwen-code-dev-bot Jul 29, 2026
ddfac38
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot Jul 29, 2026
536f3a6
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot Jul 29, 2026
1a3c632
Merge branch 'main' into dragon/auto-skill-curator
wenshao Jul 29, 2026
86f63a4
Merge branch 'main' into dragon/auto-skill-curator
qwen-code-dev-bot Jul 29, 2026
83e3854
fix(skills): preserve curator read failures
DragonnZhang Jul 29, 2026
2d6c8f9
fix(skills): harden curator lifecycle guards
DragonnZhang Jul 30, 2026
3b8d733
test(skills): cover curator safety paths
DragonnZhang Jul 30, 2026
1bd2238
fix(skills): address curator review findings (#7846)
Jul 30, 2026
b753a50
fix(cli): localize curator messages
DragonnZhang Jul 31, 2026
fec3a19
Merge branch 'main' into dragon/auto-skill-curator
Aug 1, 2026
1829624
test(skills): cover curator usage safeguards
DragonnZhang Aug 1, 2026
77f11c0
fix(skills): address curator review feedback (#7846)
qwen-code-ci-bot Aug 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions docs/design/2026-07-27-auto-skill-curator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Auto-Skill Curator

## Problem

Qwen Code can extract reusable project skills from tool-heavy conversations,
but accepted auto-skills only accumulate. The existing review agent can create
or update `source: auto-skill` skills and is explicitly forbidden from deleting
them. Path gating and `skills.disabled` reduce prompt noise but do not maintain
the on-disk library.

## Scope

Add a small, deterministic lifecycle manager for project auto-skills:

- Track successful invocations of project skills whose directory starts with
`auto-skill-` and whose frontmatter contains `source: auto-skill`.
- Mark a managed skill stale after 30 days without activity.
- Archive it after 90 days without activity by moving its whole directory out
of `.qwen/skills/` into `.qwen/archived-skills/`.
- Allow individual managed skills to be pinned out of automatic transitions.
- Run the deterministic pass at most once every 7 days during configuration
initialization when Auto Skill is enabled and the workspace is trusted.
- Expose `/curator`, `/curator status`, `/curator run [--dry-run]`, and
`/curator pin|unpin|restore <directory>` in interactive, non-interactive,
and ACP command surfaces.

This first version does not use an LLM, consolidate overlapping skills, manage
personal/bundled/extension/learned/hand-authored skills, permanently delete
anything, or introduce configurable thresholds.

## Ownership and persistence

The curator is resolved only from `Config.getProjectRoot()`. Its state lives at
`<project>/.qwen/skill-curator.json`, and archived packages live at
`<project>/.qwen/archived-skills/`. There is no fallback to the process's
primary workspace, home directory, or another active session. This keeps
daemon and multi-workspace sessions isolated.

State is keyed by the auto-skill directory name because that is the unit moved
to and from the archive. Each record stores the frontmatter skill name,
first-seen time, last successful use, use count, lifecycle state, pin state,
and optional archive time. Writes are serialized with a cross-process lock and
committed atomically.

Corrupt state is a hard, non-mutating failure. The curator must not infer that
missing usage means inactivity when its persisted evidence cannot be read.

## Eligibility and safety

A directory is curator-managed only when every condition holds:

1. It is a direct, non-symlink directory under the project skills root.
2. Its name starts with `auto-skill-`.
3. It contains a regular, non-symlink `SKILL.md`.
4. The opening YAML frontmatter contains exactly `source: auto-skill`.

This double marker prevents the curator from moving hand-authored, learned,
extension, bundled, personal, malformed, or symlinked content. Archive and
restore never overwrite an existing skill. A destination collision skips only
that package so unrelated maintenance can continue. Archived directory names
are shown as reserved in the review prompt and rejected by its write permission
guard, while confirmation staging still snapshots active skills only.
If state persistence fails after moves, the pass attempts to move every package
back before surfacing the error.

Read-only status and dry-run previews remain available in safe mode and
untrusted workspaces. Applying a maintenance pass, pinning, unpinning, and
restoring require a trusted workspace outside safe mode.

## Activity and transitions

A successful Skill tool or direct skill slash-command invocation updates an
eligible auto-skill record best-effort, even while automatic skill generation
is disabled. This keeps observed activity independent from the switch that
controls generation and scheduled maintenance. Failed, skill-disabled, or
hook-blocked invocations do not count.

For a live skill, activity is the newest of:

- the persisted last successful invocation;
- the persisted first-seen time;
- the persisted restore time; and
- the skill manifest modification time.

Including modification time prevents a recently improved skill from being
archived merely because it has not yet been invoked again.

The first observation of each eligible skill seeds `firstSeenAt = now` rather
than inferring inactivity from an old filesystem timestamp. The first automatic
observation also seeds `lastRunAt`, then waits a full 7-day interval. Explicit
`/curator run` bypasses the interval but preserves per-skill first-sight grace;
`--dry-run` reports the same seeding and transition candidates without moving
directories or changing state. Pinned records bypass stale and archive
transitions until explicitly unpinned.

## Integration points

- `Config.initialize`: performs the due deterministic pass before
`SkillManager` scans the filesystem.
- `SkillTool`: records a successful managed-skill invocation.
- `SkillCommandLoader` and the interactive/non-interactive command processors:
record successful direct slash-command invocations; ACP reuses the
non-interactive processor.
- `SkillManager`: its existing refresh path is used after manual archive or
restore so the model and slash-command surfaces immediately match disk.
- `BuiltinCommandLoader`: publishes the new `/curator` command.

No other consumer should write curator state or move managed skill packages.

## Verification

Unit tests cover eligibility, first-run seeding, stale/archive thresholds,
dry-run non-mutation, recent-use protection, recently-modified protection,
corrupt-state fail-closed behavior, collision handling, restoration, and the
command surface. Existing Skill tool tests verify that only successful loads
record usage. Build and typecheck cover the cross-package export and command
registration.
1 change: 1 addition & 0 deletions docs/users/features/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Commands for managing AI tools and models.
| `/import-config` | Import MCP servers from Claude configs | `/import-config all`, `/import-config claude-code`, `/import-config claude-desktop --scope user\|project` |
| `/tools` | Display currently available tool list | `/tools`, `/tools desc` |
| `/skills` | Open the Skills panel to browse, search, toggle, and launch skills | `/skills`, `/<skill-name>` |
| `/curator` | Inspect, pin, archive, or restore inactive project auto-skills | `/curator`, `/curator run --dry-run`, `/curator pin <directory>`, `/curator restore <directory>` |
| `/plan` | Switch to plan mode or exit plan mode | `/plan`, `/plan <task>`, `/plan exit` |
| `/approval-mode` | Change the tool-approval mode (current session only) | `/approval-mode`, `/approval-mode auto-edit` |
| → `plan` | Analysis only, no execution (secure review) | `/approval-mode plan` |
Expand Down
14 changes: 14 additions & 0 deletions docs/users/features/skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ Use project Skills for:

Project Skills can be checked into git and automatically become available to teammates.

### Maintain auto-generated project Skills

Qwen Code tracks successful uses of generated project Skills locally, including while new Auto Skill generation is disabled, so re-enabling maintenance cannot mistake a recently used skill for an inactive one. When **Auto Skill** is enabled, it periodically moves inactive generated Skills out of the active library. Only directories named `.qwen/skills/auto-skill-*` whose `SKILL.md` frontmatter contains `source: auto-skill` are managed; personal, extension, bundled, and hand-authored Skills are never selected.

- After 30 days without a successful use or `SKILL.md` edit, an auto-skill is marked stale.
- After 90 days, its complete directory is moved to `.qwen/archived-skills/`. Nothing is permanently deleted.
- Automatic maintenance runs at most once every 7 days in trusted workspaces. Each newly observed auto-skill gets a full grace period before maintenance begins.
- A pinned auto-skill is excluded from automatic stale and archive transitions until it is unpinned.
- Archived directory names remain reserved, and an existing archive destination skips only that collision rather than stopping maintenance for other skills.

Use `/curator` to see active, stale, archived, and pinned auto-skills. Run `/curator run --dry-run` to preview a maintenance pass, `/curator run` to apply it immediately, `/curator pin <directory>` or `/curator unpin <directory>` to control per-skill maintenance, or `/curator restore <directory>` to move an archived auto-skill back into the active library.

Status and dry-run previews are available in safe mode and untrusted workspaces. Applying maintenance, changing pins, and restoring archived auto-skills require a trusted workspace outside safe mode.

## Write `SKILL.md`

Create a `SKILL.md` file with YAML frontmatter and Markdown content:
Expand Down
56 changes: 56 additions & 0 deletions packages/cli/src/i18n/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -2738,4 +2738,60 @@ export default {
'Session recording stopped after a write failure. New messages for the affected session will not be saved. Check disk space and permissions, then start a new session to resume recording. See the debug log for details.',
'Session recording stopped after a write failure. New messages for the affected session will not be saved. Check disk space and permissions, then run `/clear` to start a new recorded session. See the debug log for details.':
'Session recording stopped after a write failure. New messages for the affected session will not be saved. Check disk space and permissions, then run `/clear` to start a new recorded session. See the debug log for details.',

// ==========================================================================
// Auto-skill curator (/curator command)
// ==========================================================================
'Maintain project auto-skills based on recent use.':
'Maintain project auto-skills based on recent use.',
Comment thread
DragonnZhang marked this conversation as resolved.
'Show project auto-skill lifecycle status.':
'Show project auto-skill lifecycle status.',
'Run project auto-skill lifecycle maintenance.':
'Run project auto-skill lifecycle maintenance.',
'Restore an archived project auto-skill.':
'Restore an archived project auto-skill.',
'Auto-skill curator': 'Auto-skill curator',
'Last run: {{time}}': 'Last run: {{time}}',
'Active: {{count}}': 'Active: {{count}}',
'Stale: {{count}}': 'Stale: {{count}}',
'Archived: {{count}}': 'Archived: {{count}}',
'Stale skills:': 'Stale skills:',
'Pinned skills:': 'Pinned skills:',
'Archived skills:': 'Archived skills:',
'Dry run complete.': 'Dry run complete.',
'Curator run complete.': 'Curator run complete.',
'Checked: {{count}}': 'Checked: {{count}}',
'First observed: {{count}}': 'First observed: {{count}}',
'Marked stale: {{count}}': 'Marked stale: {{count}}',
'Reactivated: {{count}}': 'Reactivated: {{count}}',
'Skipped archive collisions: {{count}}':
'Skipped archive collisions: {{count}}',
'Archive candidates:': 'Archive candidates:',
'Skipped archive collisions:': 'Skipped archive collisions:',
'{{verb}}: {{count}}': '{{verb}}: {{count}}',
'Would archive': 'Would archive',
Archived: 'Archived',
'Failed to read auto-skill curator status: {{message}}':
'Failed to read auto-skill curator status: {{message}}',
'Usage: /curator run [--dry-run]': 'Usage: /curator run [--dry-run]',
'Failed to run auto-skill curator: {{message}}':
'Failed to run auto-skill curator: {{message}}',
'Usage: /curator restore <directory>': 'Usage: /curator restore <directory>',
'Restored auto-skill: {{name}}': 'Restored auto-skill: {{name}}',
'Failed to restore auto-skill: {{message}}':
'Failed to restore auto-skill: {{message}}',
'Exclude an auto-skill from automatic maintenance.':
'Exclude an auto-skill from automatic maintenance.',
'Return a pinned auto-skill to automatic maintenance.':
'Return a pinned auto-skill to automatic maintenance.',
'Usage: /curator pin <directory>': 'Usage: /curator pin <directory>',
'Usage: /curator unpin <directory>': 'Usage: /curator unpin <directory>',
'Pinned auto-skill: {{name}}': 'Pinned auto-skill: {{name}}',
'Unpinned auto-skill: {{name}}': 'Unpinned auto-skill: {{name}}',
'Failed to update auto-skill pin: {{message}}':
'Failed to update auto-skill pin: {{message}}',
'Auto-skill curator changes are disabled in safe mode.':
'Auto-skill curator changes are disabled in safe mode.',
'Auto-skill curator changes are only available in trusted workspaces. Trust this folder via `/trust` and try again.':
'Auto-skill curator changes are only available in trusted workspaces. Trust this folder via `/trust` and try again.',
};
49 changes: 49 additions & 0 deletions packages/cli/src/i18n/locales/zh-TW.js
Original file line number Diff line number Diff line change
Expand Up @@ -2327,4 +2327,53 @@ export default {
'工作階段錄製因寫入失敗而停止。受影響工作階段中的新訊息將不會被儲存。請檢查磁碟空間和權限,然後建立新的工作階段以恢復錄製。詳細資訊請查看偵錯日誌。',
'Session recording stopped after a write failure. New messages for the affected session will not be saved. Check disk space and permissions, then run `/clear` to start a new recorded session. See the debug log for details.':
'工作階段錄製因寫入失敗而停止。受影響工作階段中的新訊息將不會被儲存。請檢查磁碟空間和權限,然後執行 `/clear` 建立新的可錄製工作階段。詳細資訊請查看偵錯日誌。',
'Maintain project auto-skills based on recent use.':
'根據最近的使用情況維護專案自動技能。',
'Show project auto-skill lifecycle status.':
'顯示專案自動技能的生命週期狀態。',
'Run project auto-skill lifecycle maintenance.':
'執行專案自動技能的生命週期維護。',
'Restore an archived project auto-skill.': '還原已封存的專案自動技能。',
'Auto-skill curator': '自動技能管理器',
'Last run: {{time}}': '上次執行:{{time}}',
'Active: {{count}}': '使用中:{{count}}',
'Stale: {{count}}': '陳舊:{{count}}',
'Archived: {{count}}': '已封存:{{count}}',
'Stale skills:': '陳舊技能:',
'Pinned skills:': '固定技能:',
'Archived skills:': '已封存技能:',
'Dry run complete.': '試執行完成。',
'Curator run complete.': '維護執行完成。',
'Checked: {{count}}': '已檢查:{{count}}',
'First observed: {{count}}': '首次發現:{{count}}',
'Marked stale: {{count}}': '已標記為陳舊:{{count}}',
'Reactivated: {{count}}': '已重新啟用:{{count}}',
'Skipped archive collisions: {{count}}': '已略過封存衝突:{{count}}',
'Archive candidates:': '待封存技能:',
'Skipped archive collisions:': '已略過的封存衝突:',
'{{verb}}: {{count}}': '{{verb}}:{{count}}',
'Would archive': '將封存',
Archived: '已封存',
'Failed to read auto-skill curator status: {{message}}':
'讀取自動技能管理器狀態失敗:{{message}}',
'Usage: /curator run [--dry-run]': '用法:/curator run [--dry-run]',
'Failed to run auto-skill curator: {{message}}':
'執行自動技能管理器失敗:{{message}}',
'Usage: /curator restore <directory>': '用法:/curator restore <directory>',
'Restored auto-skill: {{name}}': '已還原自動技能:{{name}}',
'Failed to restore auto-skill: {{message}}': '還原自動技能失敗:{{message}}',
'Exclude an auto-skill from automatic maintenance.':
'將自動技能排除於自動維護之外。',
'Return a pinned auto-skill to automatic maintenance.':
'讓固定的自動技能重新接受自動維護。',
'Usage: /curator pin <directory>': '用法:/curator pin <directory>',
'Usage: /curator unpin <directory>': '用法:/curator unpin <directory>',
'Pinned auto-skill: {{name}}': '已固定自動技能:{{name}}',
'Unpinned auto-skill: {{name}}': '已取消固定自動技能:{{name}}',
'Failed to update auto-skill pin: {{message}}':
'更新自動技能固定狀態失敗:{{message}}',
'Auto-skill curator changes are disabled in safe mode.':
'安全模式下禁止變更自動技能管理器。',
'Auto-skill curator changes are only available in trusted workspaces. Trust this folder via `/trust` and try again.':
'只有受信任的工作區可以變更自動技能管理器。請透過 `/trust` 信任此資料夾後再試一次。',
};
Loading
Loading