本文面向想在 deepin/UOS 上开发原生应用和桌面插件的开发者,手把手演示如何安装 deepin-skills 技能库,并通过自然语言驱动 AI 完成四个典型开发任务。所有示例均基于 deepin 25 / UOS V25 环境。
deepin 生态有一套自研的 DTK 框架和 DDE 桌面插件体系,文档分散在多个仓库和 Wiki 中,新手往往要在十几个仓库之间来回跳转才能拼出一个可运行的插件。deepin-skills 把这些经过长期验证的框架知识、插件接口和工程实践,组织成了 AI 可以按需读取的 Skill 文档。安装之后,你只需要用自然语言描述需求,AI 就会自动加载对应的技术资料,帮你生成符合 deepin 规范的代码。
项目地址:https://github.com/linuxdeepin/deepin-skills
https://github.com/linuxdeepin/deepin-skills
SKILL.md
打开终端,执行一行命令即可:
bash <(curl -fsSL https://raw.githubusercontent.com/linuxdeepin/deepin-skills/master/scripts/install.sh)
脚本会把四个技能安装到 ~/.agents/skills/ 目录下。如果之前装过旧版本,加 --force 参数强制覆盖:
~/.agents/skills/
--force
bash <(curl -fsSL https://raw.githubusercontent.com/linuxdeepin/deepin-skills/master/scripts/install.sh) --force
安装完成后,检查一下目录结构:
ls ~/.agents/skills/
你会看到四个目录:
dde-control-center-development dde-shell-development dde-tray-development dtk-development
每个目录就是一个独立的技能,包含 SKILL.md(触发描述与路由)、references/(按需加载的技术资料)和 evals/(验证测试用例)。
references/
evals/
如果你用的是 UOS AI,还需要配置 bash MCP 让 AI 拥有执行命令的权限。打开 UOS AI → 设置 → MCP 服务,添加以下配置:
{ "mcpServers": { "bash": { "command": "npx", "args": ["bash-mcp"] } } }
在动手之前,先了解每个技能的适用场景,这样你才知道该向 AI 描述什么样的任务。
dtk-development
dde-shell-development
dde-control-center-development
dde-tray-development
下面用四个实例分别演示。
这是最基础的场景——用 DTK 框架创建一个原生桌面应用,包含一个符合 deepin 设计规范的设置窗口。
打开你的 AI 编程 Agent,在项目目录中输入:
帮我用 DTK 创建一个 deepin 桌面应用,包含一个设置窗口,里面有"通知"和"外观"两个页面。通知页面有一个开关控件控制是否启用通知,外观页面有一个下拉框选择主题模式(浅色/深色/跟随系统)。用 DConfig 保存配置。
AI 识别到这涉及 DTK 应用开发,自动加载 dtk-development 技能。它会依次读取以下参考文档:
references/app-dev-with-dtk.md
references/declarative/dialogs.md
references/config/dconfig-cpp.md
references/theme/theme-switch.md
然后生成项目代码。以下是一个典型的项目结构和核心代码:
my-settings-app/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ ├── settingswindow.cpp │ └── settingswindow.h └── configs/ └── my-settings-app.json
cmake_minimum_required(VERSION 3.16) project(my-settings-app VERSION 1.0.0) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) find_package(Dtk6Widget REQUIRED) find_package(Dtk6Core REQUIRED) add_executable(my-settings-app src/main.cpp src/settingswindow.cpp ) target_link_libraries(my-settings-app Qt6::Widgets Dtk6::Widget Dtk6::Core ) # 安装 DConfig 配置文件 install(FILES configs/my-settings-app.json DESTINATION /share/dsg/configs/ )
DConfig 是 deepin 的统一配置方案,类似 GSettings。先定义配置 schema:
{ "magic": "dsg.config", "version": "1.0", "contents": { "enable_notifications": { "value": true, "serial": 0, "name": "启用通知", "description": "控制是否接收应用通知" }, "theme_mode": { "value": "auto", "name": "主题模式", "description": "auto/light/dark" } } }
// settingswindow.h #pragma once #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE class SettingsWindow : public DMainWindow { Q_OBJECT public: explicit SettingsWindow(QWidget *parent = nullptr); private slots: void onNotificationToggled(bool enabled); void onThemeChanged(int index); private: DConfig *m_config; DSwitchButton *m_notifySwitch; DComboBox *m_themeCombo; void setupUI(); void loadSettings(); };
// settingswindow.cpp #include "settingswindow.h" #include #include #include #include #include SettingsWindow::SettingsWindow(QWidget *parent) : DMainWindow(parent) , m_config(new DConfig("my-settings-app", this)) { setupUI(); loadSettings(); } void SettingsWindow::setupUI() { auto *centralWidget = new DWidget(this); auto *mainLayout = new QVBoxLayout(centralWidget); // 通知设置组 auto *notifyGroup = new DGroupBox("通知", centralWidget); auto *notifyLayout = new QVBoxLayout(notifyGroup); auto *notifyRow = new QHBoxLayout(); notifyRow->addWidget(new QLabel("启用通知")); m_notifySwitch = new DSwitchButton(); notifyRow->addStretch(); notifyRow->addWidget(m_notifySwitch); notifyLayout->addLayout(notifyRow); // 外观设置组 auto *appearanceGroup = new DGroupBox("外观", centralWidget); auto *appearanceLayout = new QVBoxLayout(appearanceGroup); auto *themeRow = new QHBoxLayout(); themeRow->addWidget(new QLabel("主题模式")); m_themeCombo = new DComboBox(); m_themeCombo->addItems({"跟随系统", "浅色", "深色"}); themeRow->addStretch(); themeRow->addWidget(m_themeCombo); appearanceLayout->addLayout(themeRow); mainLayout->addWidget(notifyGroup); mainLayout->addWidget(appearanceGroup); mainLayout->addStretch(); setCentralWidget(centralWidget); resize(500, 400); setTitle("设置"); connect(m_notifySwitch, &DSwitchButton::checkedChanged, this, &SettingsWindow::onNotificationToggled); connect(m_themeCombo, &DComboBox::currentIndexChanged, this, &SettingsWindow::onThemeChanged); } void SettingsWindow::loadSettings() { // 从 DConfig 读取保存的配置 bool notifyEnabled = m_config->value("enable_notifications", true).toBool(); m_notifySwitch->setChecked(notifyEnabled); QString theme = m_config->value("theme_mode", "auto").toString(); int index = (theme == "light") ? 1 : (theme == "dark") ? 2 : 0; m_themeCombo->setCurrentIndex(index); } void SettingsWindow::onNotificationToggled(bool enabled) { m_config->setValue("enable_notifications", enabled); } void SettingsWindow::onThemeChanged(int index) { QString theme = (index == 1) ? "light" : (index == 2) ? "dark" : "auto"; m_config->setValue("theme_mode", theme); }
// main.cpp #include #include "settingswindow.h" int main(int argc, char *argv[]) { DApplication app(argc, argv); app.setApplicationName("my-settings-app"); app.setApplicationVersion("1.0.0"); SettingsWindow window; window.show(); return app.exec(); }
mkdir build && cd build cmake .. make -j$(nproc) ./my-settings-app
运行后你会看到一个 deepin 风格的设置窗口,开关和下拉框的值会通过 DConfig 持久化保存,下次打开自动恢复。
这个场景演示如何用 dde-shell-development 技能扩展 DDE 桌面的 Dock 栏,添加一个显示当前时间的插件。
帮我开发一个 DDE Shell 的 Dock 插件,显示当前时间,点击后弹出一个面板显示日期和星期。用纯 QML 实现。
references/design.md
references/plugin-development.md
references/api/qml-api.md
这是插件的身份证,dde-shell 启动时通过它发现和加载插件: { "id": "dock-clock", "displayName": "时钟", "description": "在 Dock 栏显示当前时间", "version": "1.0.0", "pluginType": "applet", "Parent": "dock", "content": { "type": "qml", "main": "qml/main.qml" } } 关键字段说明:
{ "id": "dock-clock", "displayName": "时钟", "description": "在 Dock 栏显示当前时间", "version": "1.0.0", "pluginType": "applet", "Parent": "dock", "content": { "type": "qml", "main": "qml/main.qml" } }
关键字段说明:
pluginType
applet
Parent
dock"
content.main
import QtQuick import org.deepin.ds 1.0 AppletItem { id: clockApplet // 插件在 Dock 中的尺寸 implicitWidth: 80 implicitHeight: 40 // 时间更新定时器 Timer { interval: 1000 running: true repeat: true onTriggered: timeLabel.text = Qt.formatDateTime(new Date(), "HH:mm") } // 显示时间的文本 Text { id: timeLabel anchors.centerIn: parent text: Qt.formatDateTime(new Date(), "HH:mm") font.pixelSize: 16 color: palette.windowText } // 点击弹出面板 Panel.popup { id: clockPopup width: 220 height: 120 Column { anchors.centerIn: parent spacing: 8 Text { anchors.horizontalCenter: parent.horizontalCenter text: Qt.formatDateTime(new Date(), "yyyy-MM-dd") font.pixelSize: 24 color: palette.windowText } Text { anchors.horizontalCenter: parent.horizontalCenter text: { var days = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]; return days[new Date().getDay()]; } font.pixelSize: 16 color: palette.windowText } } } MouseArea { anchors.fill: parent onClicked: clockPopup.visible = !clockPopup.visible } }
# 复制到系统插件目录 sudo cp -r dock-clock /usr/share/dde-shell/dock-clock # 重启 dde-shell 使插件生效 systemctl --user restart dde-shell
重启后 Dock 栏右侧会出现一个时钟图标,显示当前时间,点击弹出日期和星期信息。
dde-control-center-development 技能用于扩展 DDE 控制中心。控制中心采用插件化架构,框架只管导航和布局,具体功能全靠插件实现。
帮我在 DDE 控制中心新增一个"网络诊断"模块,包含一个按钮,点击后执行 ping 测试,并在下方显示结果。
{ "id": "network-diag", "displayName": "网络诊断", "description": "网络连通性测试工具", "version": "1.0.0", "pluginType": "control-center", "Parent": "network", "content": { "type": "cpp", "library": "libnetworkdiag.so" } }
cmake_minimum_required(VERSION 3.16) project(networkdiag VERSION 1.0.0) set(CMAKE_CXX_STANDARD 17) set(CMAKE_AUTOMOC ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) find_package(Dtk6Widget REQUIRED) # 控制中心框架头文件 find_path(DCC_INCLUDE_DIRS dccobject.h PATHS /usr/include/dde-control-center ) add_library(networkdiag SHARED src/networkdiagplugin.cpp src/networkdiagpage.cpp ) target_include_directories(networkdiag PRIVATE ${DCC_INCLUDE_DIRS} src ) target_link_libraries(networkdiag Qt6::Widgets Dtk6::Widget ) install(TARGETS networkdiag LIBRARY DESTINATION /usr/lib/dde-control-center/modules ) install(DIRECTORY package/ DESTINATION /usr/share/dde-control-center/modules/network-diag )
控制中心插件需要继承 DccObject 并注册到模块树中:
DccObject
// networkdiagplugin.h #pragma once #include class NetworkDiagPlugin : public DccObject { Q_OBJECT public: explicit NetworkDiagPlugin(QObject *parent = nullptr); };
// networkdiagplugin.cpp #include "networkdiagplugin.h" #include "networkdiagpage.h" NetworkDiagPlugin::NetworkDiagPlugin(QObject *parent) : DccObject(parent) { // 设置模块在控制中心导航树中的显示名称和图标 setDisplayName("网络诊断"); setDescription("测试网络连通性"); setIcon("network-diagnostic"); } // 当用户点击进入此模块时,框架调用此方法创建页面 QWidget *NetworkDiagPlugin::page() { return new NetworkDiagPage(); }
// networkdiagpage.h #pragma once #include #include #include DWIDGET_USE_NAMESPACE class NetworkDiagPage : public DWidget { Q_OBJECT public: explicit NetworkDiagPage(QWidget *parent = nullptr); private slots: void onStartPing(); private: DPushButton *m_startBtn; DPlainTextEdit *m_resultView; };
// networkdiagpage.cpp #include "networkdiagpage.h" #include #include NetworkDiagPage::NetworkDiagPage(QWidget *parent) : DWidget(parent) { auto *layout = new QVBoxLayout(this); m_startBtn = new DPushButton("开始诊断"); m_resultView = new DPlainTextEdit(); m_resultView->setReadOnly(true); m_resultView->setPlaceholderText("点击上方按钮开始网络诊断..."); layout->addWidget(m_startBtn); layout->addWidget(m_resultView); connect(m_startBtn, &DPushButton::clicked, this, &NetworkDiagPage::onStartPing); } void NetworkDiagPage::onStartPing() { m_resultView->clear(); m_resultView->appendPlainText("正在测试网络连通性...\n"); auto *process = new QProcess(this); connect(process, &QProcess::readyReadStandardOutput, [=]() { m_resultView->appendPlainText( process->readAllStandardOutput()); }); connect(process, QOverload::of(&QProcess::finished), [=](int code) { m_resultView->appendPlainText( QString("\n诊断完成,退出码: %1").arg(code)); process->deleteLater(); }); process->start("ping", {"-c", "4", "www.baidu.com"}); }
mkdir build && cd build cmake .. make -j$(nproc) sudo make install # 重启控制中心 killall dde-control-center dde-control-center &
打开控制中心,在网络分组下会看到"网络诊断"模块,点击进入后可以通过按钮执行 ping 测试。
dde-tray-development 技能覆盖任务栏托盘区域的插件开发。托盘插件需要继承 PluginsItemInterfaceV2 接口。
PluginsItemInterfaceV2
帮我做一个任务栏托盘插件,显示 CPU 使用率,右键菜单提供"打开系统监视器"选项,点击图标在快捷面板中显示详细信息。
references/tray-plugin-spec.md
references/quick-panel-guide.md
references/context-menu.md
references/message-protocol.md
// cpu-monitor-plugin.h #pragma once #include
// cpu-monitor-plugin.cpp #include "cpu-monitor-plugin.h" #include #include #include #include #include #include #include CpuMonitorPlugin::CpuMonitorPlugin(QObject *parent) : QObject(parent) { m_iconLabel = new QLabel(); m_iconLabel->setFixedSize(24, 24); m_iconLabel->setAlignment(Qt::AlignCenter); m_tipLabel = new QLabel(); m_tipLabel->setMargin(8); m_proc = new QProcess(this); m_timer = new QTimer(this); connect(m_timer, &QTimer::timeout, this, &CpuMonitorPlugin::updateCpuUsage); m_timer->start(2000); updateCpuUsage(); } QWidget *CpuMonitorPlugin::itemWidget(const QString &itemKey) { return m_iconLabel; } QWidget *CpuMonitorPlugin::itemTipsWidget(const QString &itemKey) { return m_tipLabel; } QList CpuMonitorPlugin::itemContextMenu(const QString &itemKey) { QList actions; auto *openMonitor = new QAction("打开系统监视器"); connect(openMonitor, &QAction::triggered, []() { QDesktopServices::openUrl(QUrl("deepin-system-monitor://")); }); actions << openMonitor; return actions; } int CpuMonitorPlugin::itemFlags(const QString &itemKey) const { // 支持右键菜单 + 快捷面板详情页 return PluginFlag::Type_Common | PluginFlag::Attribute_CanSetting | PluginFlag::Attribute_CanQuickShow; } void CpuMonitorPlugin::updateCpuUsage() { // 读取 /proc/stat 计算 CPU 使用率 m_proc->start("bash", {"-c", "grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {printf \"%.0f\", usage}'" }); m_proc->waitForFinished(); int usage = m_proc->readAllStandardOutput().trimmed().toInt(); // 根据使用率选择颜色显示 QString color = (usage > 80) ? "#ff4444" : (usage > 50) ? "#ffaa00" : "#00aa44"; m_iconLabel->setText(QString("%2%") .arg(color).arg(usage)); m_iconLabel->setTextFormat(Qt::RichText); // 更新快捷面板详情 m_tipLabel->setText(QString("CPU 使用率: %1%\n系统状态: %2") .arg(usage) .arg(usage > 80 ? "高负载" : usage > 50 ? "中等" : "正常")); } { "id": "cpu-monitor", "name": "CPU 监视器", "version": "1.0.0", "description": "在任务栏显示 CPU 使用率", "interface": "PluginsItemInterfaceV2" }
// cpu-monitor-plugin.cpp #include "cpu-monitor-plugin.h" #include #include #include #include #include #include #include CpuMonitorPlugin::CpuMonitorPlugin(QObject *parent) : QObject(parent) { m_iconLabel = new QLabel(); m_iconLabel->setFixedSize(24, 24); m_iconLabel->setAlignment(Qt::AlignCenter); m_tipLabel = new QLabel(); m_tipLabel->setMargin(8); m_proc = new QProcess(this); m_timer = new QTimer(this); connect(m_timer, &QTimer::timeout, this, &CpuMonitorPlugin::updateCpuUsage); m_timer->start(2000); updateCpuUsage(); } QWidget *CpuMonitorPlugin::itemWidget(const QString &itemKey) { return m_iconLabel; } QWidget *CpuMonitorPlugin::itemTipsWidget(const QString &itemKey) { return m_tipLabel; } QList CpuMonitorPlugin::itemContextMenu(const QString &itemKey) { QList actions; auto *openMonitor = new QAction("打开系统监视器"); connect(openMonitor, &QAction::triggered, []() { QDesktopServices::openUrl(QUrl("deepin-system-monitor://")); }); actions << openMonitor; return actions; } int CpuMonitorPlugin::itemFlags(const QString &itemKey) const { // 支持右键菜单 + 快捷面板详情页 return PluginFlag::Type_Common | PluginFlag::Attribute_CanSetting | PluginFlag::Attribute_CanQuickShow; } void CpuMonitorPlugin::updateCpuUsage() { // 读取 /proc/stat 计算 CPU 使用率 m_proc->start("bash", {"-c", "grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {printf \"%.0f\", usage}'" }); m_proc->waitForFinished(); int usage = m_proc->readAllStandardOutput().trimmed().toInt(); // 根据使用率选择颜色显示 QString color = (usage > 80) ? "#ff4444" : (usage > 50) ? "#ffaa00" : "#00aa44"; m_iconLabel->setText(QString("%2%") .arg(color).arg(usage)); m_iconLabel->setTextFormat(Qt::RichText); // 更新快捷面板详情 m_tipLabel->setText(QString("CPU 使用率: %1%\n系统状态: %2") .arg(usage) .arg(usage > 80 ? "高负载" : usage > 50 ? "中等" : "正常")); }
{ "id": "cpu-monitor", "name": "CPU 监视器", "version": "1.0.0", "description": "在任务栏显示 CPU 使用率", "interface": "PluginsItemInterfaceV2" }
安装
任务栏托盘区域会出现一个 CPU 使用率数字,颜色根据负载变化,右键可打开系统监视器,鼠标悬停显示详细信息。 创建你自己的技能 deepin-skills 的贡献规范定义了标准的技能目录结构。如果你想把自己团队的内部开发规范也封装成技能,按照以下结构创建: skills/my-custom-skill/ ├── SKILL.md ├── agents/ │ └── openai.yaml ├── references/ │ └── my-reference.md └── evals/ ├── README.md └── my-test.md SKILL.md 模板 --- name: my-custom-skill description: "我的自定义技能描述,告诉 AI 这个技能在什么场景下触发" --- # 我的自定义技能 ## 文档路由 | 场景 | 参考文档 | |------|----------| | 了解架构 | references/architecture.md | | API 参考 | references/api.md | ## 高频场景 - 场景 A → references/a.md - 场景 B → references/b.md 核心原则是:SKILL.md 只放路由信息和触发条件,详细技术内容放 references/,验证场景放 evals/。这样 AI 只在需要时才加载具体文档,不会浪费上下文窗口。 openai.yaml 模板 skills: - name: my-custom-skill description: "技能描述" system_prompt: | 你是一个 my-custom-skill 专家,当用户提到 XXX 时触发此技能。 提交贡献 fork 仓库后,把你的技能放在 skills/ 下,同步更新 README.md 中的技能列表,然后提交 Pull Request。贡献前请阅读仓库的 CONTRIBUTING.md 了解完整规范。 常见问题排查 AI 没有触发技能 检查 SKILL.md 中的 description 字段是否准确描述了触发场景。如果描述太宽泛,AI 可能无法正确匹配。尝试在对话中明确提及技能名称,例如"使用 dtk-development 技能帮我..."。 技能安装后不生效 确认技能目录路径正确: ls ~/.agents/skills/dtk-development/SKILL.md 如果路径没问题,重启你的 AI 编程 Agent 让它重新扫描技能目录。 UOS AI 执行技能时报错 大部分技能需要 bash 执行权限。确认 MCP 配置中已添加 bash-mcp(见上文安装部分),然后在对话中点击"重新生成"。 插件安装后不显示 DDE Shell 插件需要检查 Parent 字段是否指向了正确的面板(如 dock、top-bar)。控制中心插件需要检查 pluginType 是否为 control-center。重启对应服务后检查日志: # Dock 日志 journalctl --user -u dde-shell -f # 控制中心日志 QT_LOGGING_RULES="*.debug=true" dde-control-center 2>&1 | grep network 四个技能的评估用例分布 deepin-skills 为每个技能配套了验证测试用例(Evals),确保 AI 使用技能时能正确理解和应用技术知识。以下是各技能的用例数量和分类:
任务栏托盘区域会出现一个 CPU 使用率数字,颜色根据负载变化,右键可打开系统监视器,鼠标悬停显示详细信息。 创建你自己的技能 deepin-skills 的贡献规范定义了标准的技能目录结构。如果你想把自己团队的内部开发规范也封装成技能,按照以下结构创建: skills/my-custom-skill/ ├── SKILL.md ├── agents/ │ └── openai.yaml ├── references/ │ └── my-reference.md └── evals/ ├── README.md └── my-test.md SKILL.md 模板 --- name: my-custom-skill description: "我的自定义技能描述,告诉 AI 这个技能在什么场景下触发" --- # 我的自定义技能 ## 文档路由 | 场景 | 参考文档 | |------|----------| | 了解架构 | references/architecture.md | | API 参考 | references/api.md | ## 高频场景 - 场景 A → references/a.md - 场景 B → references/b.md 核心原则是:SKILL.md 只放路由信息和触发条件,详细技术内容放 references/,验证场景放 evals/。这样 AI 只在需要时才加载具体文档,不会浪费上下文窗口。 openai.yaml 模板 skills: - name: my-custom-skill description: "技能描述" system_prompt: | 你是一个 my-custom-skill 专家,当用户提到 XXX 时触发此技能。 提交贡献 fork 仓库后,把你的技能放在 skills/ 下,同步更新 README.md 中的技能列表,然后提交 Pull Request。贡献前请阅读仓库的 CONTRIBUTING.md 了解完整规范。 常见问题排查 AI 没有触发技能 检查 SKILL.md 中的 description 字段是否准确描述了触发场景。如果描述太宽泛,AI 可能无法正确匹配。尝试在对话中明确提及技能名称,例如"使用 dtk-development 技能帮我..."。 技能安装后不生效 确认技能目录路径正确: ls ~/.agents/skills/dtk-development/SKILL.md 如果路径没问题,重启你的 AI 编程 Agent 让它重新扫描技能目录。 UOS AI 执行技能时报错 大部分技能需要 bash 执行权限。确认 MCP 配置中已添加 bash-mcp(见上文安装部分),然后在对话中点击"重新生成"。 插件安装后不显示
任务栏托盘区域会出现一个 CPU 使用率数字,颜色根据负载变化,右键可打开系统监视器,鼠标悬停显示详细信息。
deepin-skills 的贡献规范定义了标准的技能目录结构。如果你想把自己团队的内部开发规范也封装成技能,按照以下结构创建:
skills/my-custom-skill/ ├── SKILL.md ├── agents/ │ └── openai.yaml ├── references/ │ └── my-reference.md └── evals/ ├── README.md └── my-test.md
--- name: my-custom-skill description: "我的自定义技能描述,告诉 AI 这个技能在什么场景下触发" --- # 我的自定义技能 ## 文档路由 | 场景 | 参考文档 | |------|----------| | 了解架构 | references/architecture.md | | API 参考 | references/api.md | ## 高频场景 - 场景 A → references/a.md - 场景 B → references/b.md
核心原则是:SKILL.md 只放路由信息和触发条件,详细技术内容放 references/,验证场景放 evals/。这样 AI 只在需要时才加载具体文档,不会浪费上下文窗口。
skills: - name: my-custom-skill description: "技能描述" system_prompt: | 你是一个 my-custom-skill 专家,当用户提到 XXX 时触发此技能。
fork 仓库后,把你的技能放在 skills/ 下,同步更新 README.md 中的技能列表,然后提交 Pull Request。贡献前请阅读仓库的 CONTRIBUTING.md 了解完整规范。
skills/
README.md
CONTRIBUTING.md
检查 SKILL.md 中的 description 字段是否准确描述了触发场景。如果描述太宽泛,AI 可能无法正确匹配。尝试在对话中明确提及技能名称,例如"使用 dtk-development 技能帮我..."。
description
确认技能目录路径正确:
ls ~/.agents/skills/dtk-development/SKILL.md
如果路径没问题,重启你的 AI 编程 Agent 让它重新扫描技能目录。
大部分技能需要 bash 执行权限。确认 MCP 配置中已添加 bash-mcp(见上文安装部分),然后在对话中点击"重新生成"。
bash-mcp
DDE Shell 插件需要检查 Parent 字段是否指向了正确的面板(如 dock、top-bar)。控制中心插件需要检查 pluginType 是否为 control-center。重启对应服务后检查日志:
DDE Shell 插件需要检查 Parent
dock
top-bar
control-center
# Dock 日志 journalctl --user -u dde-shell -f # 控制中心日志 QT_LOGGING_RULES="*.debug=true" dde-control-center 2>&1 | grep network
deepin-skills 为每个技能配套了验证测试用例(Evals),确保 AI 使用技能时能正确理解和应用技术知识。以下是各技能的用例数量和分类:
dtk-development 的 widgets 分类独占 29 个用例,覆盖了从对话框、按钮到列表视图、树视图等各类控件的验证场景,这也反映了 DTK 控件库的丰富程度。
deepin-skills 的价值不在于它替代了文档,而在于它把分散在十几个仓库和 Wiki 中的知识重新组织成了 AI 可以按需检索的结构。四个技能、130 个评估用例、40 多份参考文档,构成了一个完整的 deepin 原生开发知识图谱。
如果你在 deepin 上有重复性的开发需求,不妨试着把它封装成一个 Skill——这比写一份内部 Wiki 有效得多,因为 AI 会自动帮你的团队成员加载和使用它。
好东西~
这得加精
👍 很好,很实用。
Featured Collection
Popular Ranking
Popular Events
deepin-skills 实战教程:让 AI 帮你写 deepin 原生应用
它解决什么问题
deepin 生态有一套自研的 DTK 框架和 DDE 桌面插件体系,文档分散在多个仓库和 Wiki 中,新手往往要在十几个仓库之间来回跳转才能拼出一个可运行的插件。deepin-skills 把这些经过长期验证的框架知识、插件接口和工程实践,组织成了 AI 可以按需读取的 Skill 文档。安装之后,你只需要用自然语言描述需求,AI 就会自动加载对应的技术资料,帮你生成符合 deepin 规范的代码。
项目地址:
https://github.com/linuxdeepin/deepin-skills你需要准备什么
SKILL.md的 AI 编程 Agent(如 UOS AI 内置的"小U同学",或 Claude Code、Cursor 等支持 Anthropic Skill 规范的工具)安装技能库
打开终端,执行一行命令即可:
脚本会把四个技能安装到
~/.agents/skills/目录下。如果之前装过旧版本,加--force参数强制覆盖:安装完成后,检查一下目录结构:
你会看到四个目录:
每个目录就是一个独立的技能,包含
SKILL.md(触发描述与路由)、references/(按需加载的技术资料)和evals/(验证测试用例)。如果你用的是 UOS AI,还需要配置 bash MCP 让 AI 拥有执行命令的权限。打开 UOS AI → 设置 → MCP 服务,添加以下配置:
四个技能分别做什么
在动手之前,先了解每个技能的适用场景,这样你才知道该向 AI 描述什么样的任务。
dtk-developmentdde-shell-developmentdde-control-center-developmentdde-tray-development下面用四个实例分别演示。
实例一:用 DTK 创建一个设置窗口
这是最基础的场景——用 DTK 框架创建一个原生桌面应用,包含一个符合 deepin 设计规范的设置窗口。
向 AI 描述任务
打开你的 AI 编程 Agent,在项目目录中输入:
AI 会做什么
AI 识别到这涉及 DTK 应用开发,自动加载
dtk-development技能。它会依次读取以下参考文档:references/app-dev-with-dtk.md—— 了解如何创建 DTK 应用和配置 CMakereferences/declarative/dialogs.md—— 了解 QML 对话框控件references/config/dconfig-cpp.md—— 了解 DConfig 的 C++ 接口references/theme/theme-switch.md—— 了解主题切换机制然后生成项目代码。以下是一个典型的项目结构和核心代码:
项目结构
CMakeLists.txt
DConfig 配置文件
DConfig 是 deepin 的统一配置方案,类似 GSettings。先定义配置 schema:
核心代码
构建和运行
运行后你会看到一个 deepin 风格的设置窗口,开关和下拉框的值会通过 DConfig 持久化保存,下次打开自动恢复。
实例二:给 Dock 栏添加一个自定义插件
这个场景演示如何用
dde-shell-development技能扩展 DDE 桌面的 Dock 栏,添加一个显示当前时间的插件。向 AI 描述任务
AI 会读取的参考文档
references/design.md—— 理解三层插件模型(Applet → Containment → Panel)references/plugin-development.md—— 学习如何创建纯 QML Appletreferences/api/qml-api.md—— 查看 QML API(AppletItem、Panel Popup)插件结构
pluginType设为applet,表示这是一个最小功能单元Parent设为dock",告诉框架这个插件挂在 Dock 面板下content.main指向 QML 入口文件main.qml
安装和测试
重启后 Dock 栏右侧会出现一个时钟图标,显示当前时间,点击弹出日期和星期信息。
实例三:在控制中心添加一个设置模块
dde-control-center-development技能用于扩展 DDE 控制中心。控制中心采用插件化架构,框架只管导航和布局,具体功能全靠插件实现。向 AI 描述任务
项目结构
CMakeLists.txt
插件入口
控制中心插件需要继承
DccObject并注册到模块树中:诊断页面
安装
打开控制中心,在网络分组下会看到"网络诊断"模块,点击进入后可以通过按钮执行 ping 测试。
实例四:开发一个任务栏托盘插件
dde-tray-development技能覆盖任务栏托盘区域的插件开发。托盘插件需要继承PluginsItemInterfaceV2接口。向 AI 描述任务
AI 会读取的参考文档
references/tray-plugin-spec.md—— 托盘插件接口规范(最大的一份文档,15KB)references/quick-panel-guide.md—— 快捷面板开发references/context-menu.md—— 右键菜单实现references/message-protocol.md—— 消息协议核心代码
{ "id": "cpu-monitor", "name": "CPU 监视器", "version": "1.0.0", "description": "在任务栏显示 CPU 使用率", "interface": "PluginsItemInterfaceV2" }安装
dtk-developmentdde-control-center-developmentdde-shell-developmentdde-tray-developmentdtk-development的 widgets 分类独占 29 个用例,覆盖了从对话框、按钮到列表视图、树视图等各类控件的验证场景,这也反映了 DTK 控件库的丰富程度。写在最后
deepin-skills 的价值不在于它替代了文档,而在于它把分散在十几个仓库和 Wiki 中的知识重新组织成了 AI 可以按需检索的结构。四个技能、130 个评估用例、40 多份参考文档,构成了一个完整的 deepin 原生开发知识图谱。
如果你在 deepin 上有重复性的开发需求,不妨试着把它封装成一个 Skill——这比写一份内部 Wiki 有效得多,因为 AI 会自动帮你的团队成员加载和使用它。