LobeHub CLIlh skill与lh plugin命令详解:从命令行管理智能体技能与插件
【免费下载链接】lobehub🤯 LobeHub is your Chief Agent Operator, organizing your agents into 7×24 operations by hiring, scheduling, and reporting on your entire AI team.项目地址: https://gitcode.com/GitHub_Trending/lo/lobehub
本文基于 LobeHub 仓库的 CLI 命令参考文档 skills-plugins.md,完整覆盖lh skill(智能体技能管理)与lh plugin(外部工具插件管理)两组子命令的参数、示例与底层实现。读完后,你可以熟练使用lh skill list / view / create / edit / delete / search / install / resources / read-resource和lh plugin list / install / uninstall / update完成技能与插件的全生命周期管理,并理解这些命令在后端 tRPC 路由与SkillImporter服务中的真实调用链。
前置条件:CLI 如何与 LobeHub 服务端通信
所有lh命令都通过 CLI 的 tRPC 客户端 访问服务端的/trpc/lambda端点。从 getAuthAndServer() 的实现看,认证按以下优先级解析:
- 环境变量
LOBEHUB_JWT(供服务端沙箱场景使用,以Oidc-Auth头传递); - CLI API Key 环境变量(以
X-API-Key头传递); - 本地 OAuth 令牌(需先执行
lh login,未登录时命令会以No authentication found. Run 'lh login' ... first报错退出)。
因此,在执行下述任何 skill / plugin 命令前,请确认已完成lh login或配置了对应环境变量。涉及工作区(Workspace)的操作时,客户端会通过withWorkspaceHeader自动附加工作区头,服务端按 RBAC 权限校验(写操作要求agent:update权限,见 agentSkills.ts)。
技能管理(lh skill)
技能(Skill)是赋予智能体自定义指令与能力的载体,本质是一份SKILL.md提示词内容加上可选的附带资源文件。CLI 入口注册于 registerSkillCommand(),所有子命令最终都调用client.agentSkills.*对应的 tRPC 过程。
lh skill list— 列出技能
lh skill list [--source <source>] [--json [fields]]| 选项 | 说明 |
|---|---|
--source <source> | 按来源过滤:builtin(内置)、market(市场)、user(自建),三者之外取值会直接报错退出 |
--json [fields] | 以 JSON 输出,可选字段名(逗号分隔)做投影 |
默认以表格输出,列为ID、NAME、DESCRIPTION、SOURCE、IDENTIFIER,其中 NAME/DESCRIPTION 会按终端显示宽度截断(实现见 truncate(),对 CJK 全角字符按 2 列宽度计算,中文技能名不会把表格撑乱)。源码中 NAME 截断上限 30 字符、DESCRIPTION 40 字符(skill.ts)。
lh skill view <id>— 查看技能详情
lh skill view <id> [--json [fields]]展示技能名称、描述、来源(Source)、标识符(ID: identifier)以及完整的Content(技能提示词正文)。技能不存在时报错Skill not found: <id>并以非零码退出。
lh skill create— 创建用户技能
lh skill create -n <name> -d <desc> -c <content> [-i <identifier>]| 选项 | 说明 | 必填 |
|---|---|---|
-n, --name <name> | 技能名称 | 是 |
-d, --description <desc> | 技能描述 | 是 |
-c, --content <content> | 技能内容(提示词/指令) | 是 |
-i, --identifier <id> | 自定义标识符 | 否 |
服务端的 createUserSkill() 会做两重唯一性校验:同名技能报CONFLICT(Skill with name "..." already exists);不提供--identifier时自动生成为user.<nanoid(12)>形式。创建成功后终端打印✓ Created skill <id>。
lh skill edit <id>— 更新技能
lh skill edit <id> [-n <name>] [-d <desc>] [-c <content>]三个参数至少提供一个,否则报错No changes specified.。从源码实现看(skill.ts),-c直接更新content字段,而-n / -d会被打包进manifest对象传递——这与服务端 updateSkillSchema 的设计一致:“所有元数据都应通过 manifest 传递”,服务端再把manifest.name / manifest.description同步回顶层字段。
lh skill delete <id>— 删除技能
lh skill delete <id> [--yes]不加--yes时会交互式确认(Are you sure you want to delete this skill?),输入拒绝则打印Cancelled.。服务端删除逻辑是幂等的:目标行不存在时直接返回,不触发权限断言(agentSkills.ts)。
lh skill search <query>— 搜索技能
lh skill search <query> [--json [fields]]表格列为ID、NAME、DESCRIPTION,对应服务端的agentSkills.search过程(agentSkills.ts),底层为AgentSkillModel.search的模糊匹配。
lh skill install <source>(别名lh skill i)— 安装技能
这是功能最复杂的子命令,会根据输入自动识别来源类型:
# GitHub(URL 或 owner/repo 简写) lh skill install lobehub/skill-repo lh skill install https://github.com/lobehub/skill-repo lh skill install lobehub/skill-repo --branch dev # ZIP 直链 lh skill install https://example.com/skill.zip # 市场标识符 lh skill install my-cool-skill lh skill i my-cool-skill| 选项 | 说明 | 备注 |
|---|---|---|
--branch <branch> | 分支名 | 仅 GitHub 来源有效,可选 |
类型检测规则由 detectSourceType() 实现,优先级如下:
https://github.com/...(或 http 前缀)开头 →GitHub;- 匹配正则
^[\w-]+\/[\w.-]+$(即owner/repo简写)→GitHub; - 其他
https://.../http://...URL →ZIP URL; - 其余一律视为市场标识符。
三种类型分别路由到不同的 tRPC 过程(skill.ts):
| 检测类型 | tRPC 过程 | 服务端行为 |
|---|---|---|
| GitHub | agentSkills.importFromGitHub | 拉取仓库 ZIP 并解析SKILL.md,可指定branch |
| ZIP URL | agentSkills.importFromUrl | 下载并解析 ZIP 包 |
| 市场标识符 | agentSkills.importFromMarket | 先经MarketService.getSkillDownloadUrl()换取下载地址,再走 URL 导入并标记source: 'market' |
服务端的SkillImporter(importer.ts)有几个值得了解的实现细节:
- GitHub 导入支持子目录:
importFromGitHub解析时可传basePath,只保留技能目录文件并重新打包(repackSkillZip),manifest 中会写入repository与sourceUrl字段; - 基于 zipHash 的去重与增量更新:若已有技能的
zipFileHash与新包一致且内容非空,直接返回unchanged状态不做写入;内容变化时更新原记录(updated),并仅允许创建者或工作区 owner 覆盖他人技能(assertCanOverwrite); - SSRF 防护:URL 导入使用
ssrfSafeFetch而非原生 fetch,在连接时拦截内网/link-local 地址并逐跳校验重定向(importer.ts),并带 30 秒超时; - 标识符生成:URL 导入时按
url.<host>.<path 中的斜杠转点号>生成标识符,市场导入时优先使用传入的 identifier; - 导入结果状态:
created/updated/unchanged,CLI 端统一打印✓ Installed skill ...。
注意:GitHub 来源导入的技能在数据库中source字段被标记为market(importer.ts),lh skill list --source market即可看到它们。
资源文件子命令
技能可携带额外资源文件(脚本、参考文档等),由resources哈希表引用(文件按内容哈希全局去重存储)。
lh skill resources <id>— 列出技能资源
lh skill resources <id> [--json [fields]]表格列为PATH、TYPE、SIZE,大小以 KB 展示(Math.round(size / 1024))。服务端先校验技能存在,再经SkillResourceService.listResources返回资源清单(agentSkills.ts)。
lh skill read-resource <id> <path>— 读取资源文件内容
lh skill read-resource <skillId> <path>返回文件内容或 JSON 元数据。实现上(skill.ts):若结果含content字段则原样写入 stdout(可直接重定向保存文件),否则输出格式化 JSON;路径不存在时报Resource not found: <path>。
插件管理(lh plugin)
插件(Plugin)是外部工具集成,通过 manifest 声明能力。CLI 入口注册于 registerPluginCommand(),服务端路由为 plugin.ts。
lh plugin list— 列出已安装插件
lh plugin list [--json [fields]]表格列为ID、IDENTIFIER、TYPE、TITLE,其中 TITLE 取自manifest.meta.title,回退到manifest.identifier(plugin.ts)。无插件时打印No plugins installed.。
lh plugin install— 安装插件
lh plugin install -i <identifier> --manifest <json> [--type <type>] [--settings <json>]| 选项 | 说明 | 必填 |
|---|---|---|
-i, --identifier <id> | 插件标识符 | 是 |
--manifest <json> | 插件 manifest JSON 字符串 | 是 |
--type <type> | plugin或customPlugin | 否,默认plugin |
--settings <json> | 插件设置 JSON 字符串 | 否 |
--manifest与--settings都会被客户端JSON.parse,解析失败直接报Invalid manifest JSON./Invalid settings JSON.退出。
底层调用的是幂等的plugin.createOrInstallPlugin(plugin.ts):按 identifier 查不到记录时新建;已存在时仅更新 manifest,且只有创建者或工作区 owner 能覆盖他人插件行(assertWorkspaceRowManageable)。这意味着重复执行同一条 install 命令不会报错,只会刷新 manifest。
lh plugin uninstall <id>— 卸载插件
lh plugin uninstall <id> [--yes]同样带交互确认,--yes跳过。服务端删除同样幂等:记录不存在时静默返回。
lh plugin update <id>— 更新插件
lh plugin update <id> [--manifest <json>] [--settings <json>]--manifest与--settings至少提供一个,否则报错No changes specified.。两个参数可同时提供,一次请求内完成 manifest 与 settings 的联合更新。
源码补充:lh plugin create
命令参考文档未收录、但源码中实际注册的还有一个 plugin create 子命令(无 settings 的纯创建,对应plugin.createPlugin):
lh plugin create -i <id> --manifest <json> [--type <type>] [--custom-params <json>]与install的区别在于它走createPlugin过程(总是创建新记录,identifier 冲突会由数据层报错),并额外支持--custom-params传入自定义参数。
输出约定与脚本化建议
两组命令共享统一的输出协议(utils/format.ts):
--json:输出纯 JSON,不带表格装饰,可直接| jq处理;--json <fields>:字段投影,如lh skill list --json id,name,source只输出指定字段,适合在 Agent 工作流中做轻量数据提取;- 表格输出:列宽按 CJK 显示宽度对齐(全角字符按 2 列计算),长文本以
…截断; - 退出码:
not found、参数校验失败、JSON 解析失败等场景均process.exit(1),可被脚本捕获判断成败。
小结与延伸阅读
- 客户端实现:apps/cli/src/commands/skill.ts、apps/cli/src/commands/plugin.ts;
- 服务端路由:apps/server/src/routers/lambda/agentSkills.ts、apps/server/src/routers/lambda/plugin.ts;
- 导入核心服务:apps/server/src/services/skill/importer.ts,同目录下的 importer.test.ts 覆盖了 ZIP 解析、GitHub 导入与 URL 导入的行为验证,可作为回归行为的参考依据;
- 集成测试:apps/server/src/routers/lambda/tests/integration/agentSkills.integration.test.ts。
理解“CLI 命令 → tRPC 过程 → 服务端服务”这条调用链后,你可以把lh skill install+lh plugin install组合进 CI 或 Agent 编排脚本,实现技能与插件的可版本化、可重复安装。
【免费下载链接】lobehub🤯 LobeHub is your Chief Agent Operator, organizing your agents into 7×24 operations by hiring, scheduling, and reporting on your entire AI team.项目地址: https://gitcode.com/GitHub_Trending/lo/lobehub
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考