使用说明
🔥 技能锻造
当地第一 技能运行库+可视化管理器 适用于本地和开放LLM
源 agentskills.io 网站 来自任何地方的技能(git、文件夹、注册表、URL)和技能锻造使 右一火,在运行时注入 三个目标 一个共享的核心。
来源→ 管理→ 路线→ 注入 ·确实如此 不 创作工具。
为什么
您的本地模型无法使用您的云助手可以使用的技能。agentskills.io充满了出色的技能,但它是一个运行中的模型 LM Studio, 奥拉玛, llama.cpp,或 vLLM 没有办法 找到合适的技能,并在合适的时间注入技能锻造是缺失的一层-- 完全本地化,on 127.0.0.1,每个决定都是可观察的 (“永不沉默”)。一条发动机路线;三个薄型适配器。
flowchart LR
A["😕 You ask a local model<br/>to extract tables from a PDF"] --> B{Does it know<br/>the PDF skill?}
B -->|"without skill-forge"| C["❌ generic answer —<br/>the skill never fires"]
B -->|"with skill-forge"| D["✅ the PDF skill is selected<br/>+ injected at runtime"]
style C stroke:#c0392b,stroke-width:2px
style D stroke:#27ae60,stroke-width:2px
架构——杠杆点
一个纯粹的核心完成了这项工作: 来源→ 规范化→ 索引→ 选择→ 注入其他一切都是一个薄适配器 地方 注入到它的通道中,或者一个可选的本地守护进程来加速和观察它。
flowchart TB
subgraph clients["foreign processes (the clients)"]
LMS["🖥️ LM Studio<br/>GUI chats"]
HOST["🧩 MCP host<br/>Claude Desktop · Cursor"]
AGENT["🤖 OpenAI-compat agent<br/>Ollama · llama.cpp · vLLM"]
BROWSER["🌐 Browser<br/>visual manager"]
end
subgraph daemon["@skillforge/daemon — 127.0.0.1 (optional accelerator, sole writer)"]
direction TB
CORE["⚙️ @skillforge/core<br/><b>source · normalize · index · SELECT · INJECT · exec</b>"]
STORE[("🗄️ node:sqlite<br/>read-model + WAL")]
API["REST + SSE control API · serves the UI"]
CORE --- STORE
CORE --- API
end
subgraph adapters["thin adapters (embed core; degrade with a *visible* warning if daemon is down)"]
PLUG["@skillforge/lmstudio<br/>persisted user-turn rewrite"]
MCP["@skillforge/mcp-server<br/>host-driven tools (stdio + HTTP)"]
PROXY["@skillforge/proxy<br/>ephemeral /v1 system message"]
end
LMS --> PLUG
HOST --> MCP
AGENT --> PROXY
BROWSER --> API
PLUG -.embeds.-> CORE
MCP -.embeds.-> CORE
PROXY -.embeds.-> CORE
CLI["⌨️ @skillforge/cli<br/>skill-forge add / list"] --> STORE
五个决议: ① 标题(一种技巧 解雇 在真实聊天中)首先发货,而不是代理; ② 平价是 已证实,未断言 (黄金路由门将每个适配器与核心进行比较); ③ schemaVersion 从第一天开始; ④ 守护进程是 可选加速器,从不在聊天的关键失败路径上; ⑤ 注射是 通道无关内容+每个适配器的位置 --堆芯发射 InjectionContent,每个适配器都按照其通道的持久性语义放置它。
如何选择技能——分层选择
选择只会升级到必须升级的程度,并且 使“不注射任何东西”清晰可辨 --错误的技能比没有技能更糟糕。
flowchart TD
Q["user turn"] --> T0{"explicit?<br/>$slug or X-Skill header"}
T0 -->|yes| FIRE["🎯 inject the named skill<br/>(Tier-0, disclosure: full)"]
T0 -->|no| T1["Tier-1 · lexical<br/>offline BM25-style match"]
T1 --> J1{"clears threshold<br/>+ margin over #2?"}
J1 -->|yes| FIRE
J1 -->|"weak / tie"| T2["Tier-2 · semantic<br/>local embeddings (nomic-embed)"]
T2 --> AVAIL{"embeddings<br/>endpoint up?"}
AVAIL -->|no| BANNER["⚠️ Tier-2 disabled<br/><b>visible</b> banner — never a silent downgrade"]
AVAIL -->|yes| J2{"clears threshold?"}
J2 -->|yes| FIRE
J2 -->|no| NONE["∅ inject nothing<br/>θ-gauge shows why"]
BANNER --> NONE
style FIRE stroke:#27ae60,stroke-width:2px
style NONE stroke:#7f8c8d,stroke-width:2px
style BANNER stroke:#e67e22,stroke-width:2px
Spike A0根据LM Studio的实时数据进行了测量:仅词汇峰值在 77% precision@1;添加语义层达到 93% 假火≤7%。 您在路由/测试选项卡中看到的正是触发的内容。
三个目标,一个决策——注射模型
所选内容相同 InjectionContent 是 放置方式不同 每个通道,匹配每个通道的持久性语义:
flowchart LR
SEL["core.select →<br/>InjectionContent"] --> P1 & P2 & P3
P1["🖥️ LM Studio plugin"] --> O1["rewrites the user turn —<br/><b>persisted & sticky</b> in the transcript<br/>(GUI chats)"]
P2["🧩 MCP server"] --> O2["host-driven tools —<br/>list · load · run<br/>the <b>host</b> picks; never narrowed to one"]
P3["🔌 OpenAI proxy"] --> O3["prepends an <b>ephemeral</b><br/>system message to a copy of<br/>messages (never persisted)"]
| 目标 | 渠道 | 位置 | 你能看到的证据 |
|---|---|---|---|
| LM Studio | GUI聊天 | 用户转重写,持久化 | 技能块保存在成绩单中; injectedBytes 在 inject.log.jsonl 等于着陆的字节数 |
| 主控程序 | 任何MCP主机 | list_skills · load_skill · run_skill_script |
主机菜单;无授权运行返回a 命名、审计 拒绝 |
| 代理 | /v1/chat/completions |
临时系统消息 | X-Skill-Injected / -Disclosure / -Tier 响应标头+a select.log.jsonl 线路 |
安全模型——默认拒绝,每次拒绝均可观察
脚本从不静默运行。 一个经审计的执行瓶颈 每跑一次门;拒绝总是通过以下方式浮出水面 名字 并写入审计日志——绝不是无声的拒绝。
flowchart TD
RUN["run_skill_script"] --> H["recompute the on-disk bundle hash"]
H --> MUTE{"owner muted this<br/>skill for MCP?"}
MUTE -->|yes| R1["⛔ refused: suppressed<br/>(non-rotatable owner mute)"]
MUTE -->|no| GRANT{"exec granted<br/>AND hash still matches?"}
GRANT -->|no| R2["⛔ refused: no-grant / hash-mismatch<br/>(default-deny — D2)"]
GRANT -->|yes| INT{"interpreter resolves<br/>+ argv shape valid?"}
INT -->|no| R3["⛔ refused: interpreter-unresolved / bad-args"]
INT -->|yes| SPAWN["▶️ spawn (audited) — exit code + output tails"]
R1 --> AUDIT[("📝 every outcome →<br/>exec.log.jsonl + live SSE")]
R2 --> AUDIT
R3 --> AUDIT
SPAWN --> AUDIT
style R1 stroke:#c0392b
style R2 stroke:#c0392b
style R3 stroke:#c0392b
style SPAWN stroke:#27ae60,stroke-width:2px
强化亮点:阵列argv spawn (无外壳,无指令注射面);仅HTTPS克隆,带有SSRF防护;一 仅限本地入场 (非本地主机/来源→ 403);内容哈希绑定的exec允许在重新同步时自动撤销;和一个 根据技能,不可旋转的MCP运行静音 在实时和后台进程下行路径上的核心阻塞点强制执行。
单体仓库
| 包装 | 什么 | |
|---|---|---|
@skillforge/contracts |
共享类型, schemaVersion,调整了路由阈值,金色固定装置 |
✅ |
@skillforge/core |
发动机-- normalize +分层 select + inject +高管瓶颈 |
✅ |
@skillforge/daemon |
本地 node:sqlite 读取模型存储,REST+SSE打开 127.0.0.1,为UI提供服务 |
✅ |
@skillforge/cli |
skill-forge add / list --来源(git/文件夹/注册表/url) |
✅ |
@skillforge/lmstudio |
LM Studio插件(GUI聊天) | ✅ |
@skillforge/mcp-server |
适用于任何MCP主机的MCP技能服务器(stdio+HTTP) | ✅ |
@skillforge/proxy |
OpenAI兼容的代理(Ollama·llama.cpp·vLLM·任何OpenAI兼容代理) | ✅ |
@skillforge/ui |
只读可视化管理器(技能·来源·路线/测试·活动·状态) | ✅ |
快速入门
# 0. Zero-install: junction the workspace packages into node_modules (stand-in for pnpm install)
node scripts/link-workspace.mjs
# 1. SOURCE a skill (git URL or local folder) into your home; prints a humble capability inventory
SKILLFORGE_HOME=/tmp/sf node --experimental-strip-types packages/cli/src/bin.ts add <git-url | folder>
SKILLFORGE_HOME=/tmp/sf node --experimental-strip-types packages/cli/src/bin.ts list
# 2. BOOT the daemon + visual manager (both flags required: type-stripping + node:sqlite)
SKILLFORGE_HOME=/tmp/sf node --experimental-strip-types --experimental-sqlite packages/daemon/src/bin.ts
# → daemon listening at http://127.0.0.1:4319/ (open it: Skills · Sources · Route/Test · Activity)
# 3. ROUTE a query headlessly (what you see here is what fires)
curl -s -X POST http://127.0.0.1:4319/route-test \
-H 'content-type: application/json' -H 'origin: http://127.0.0.1:4319' \
-d '{"target":"lmstudio","messages":[{"role":"user","content":"extract tables from a pdf"}]}'
三个注入目标——LM Studio插件(packages/lmstudio-plugin/RUNBOOK.md),MCP服务器(packages/mcp-server),以及代理(packages/proxy)--每个都嵌入了相同的核心。完整的端到端演练存在于私人规划文档中。
安装——连接注射靶
一次发掘你的技能(skill-forge add …,如上),然后打开您使用的任何目标。每个都嵌入了相同的核心,因此所有三个核心的路由都是相同的。
flowchart LR
H["~/.skillforge<br/>(skills + manifest)"] --> T1 & T2 & T3
T1["① LM Studio plugin<br/><i>one-time build + lms dev</i>"]
T2["② MCP server<br/><i>point your host at it</i>"]
T3["③ OpenAI proxy<br/><i>point your client's base URL at it</i>"]
① LM Studio插件(GUI聊天)
插件不能是普通包-- @lmstudio/sdk 仅存在 里面 一个内置的LM Studio插件。因此,它是由LM Studio的参考RAG-v1插件与SkillForge交换后组装而成的。整个组装过程由一个脚本完成:
# Prereq: install LM Studio's "RAG v1" plugin once — LM Studio → Discover → Plugins.
node scripts/build-lmstudio-plugin.mjs # → builds ~/.lmstudio-skillforge-plugin
cd ~/.lmstudio-skillforge-plugin
lms dev --install --yes # persistent one-shot install (no watch). Or `lms dev` to iterate.
您应该看到:
Successfully installed skillforge-local/skillforge-lmstudio该插件出现在LM Studio的 插件 面板——什么都没运行。(如果LM Studio未显示,请重新启动一次。)
然后在LM Studio的主页中添加一项技能(确实如此 不 继承shell的 SKILLFORGE_HOME,所以不要设置)并聊天:
SKILLFORGE_HOME= node --experimental-strip-types packages/cli/src/bin.ts add <git-url|folder>
在GUI聊天中,发送与技能匹配的消息(或明确的 $slug). 您应该看到: 技能说明 做好准备,坚持下去 在成绩单中; tail -n 1 ~/.skillforge/inject.log.jsonl 显示a injectedBytes 等于着陆的块。完整演练+天花板尺寸注意事项: packages/lmstudio-plugin/RUNBOOK.md.
② MCP服务器(克劳德桌面、光标、任何MCP主机)
将主机指向stdio服务器(您添加的技能将成为 list_skills / load_skill / run_skill_script 工具——主机选择):
// e.g. Claude Desktop / Cursor MCP config
{ "mcpServers": { "skillforge": {
"command": "node",
"args": ["--experimental-strip-types", "<repo>/packages/mcp-server/src/bin.ts"]
} } }
您应该看到: 主机中的三个SkillForge工具;一
run_skill_script如果没有exec授权,则返回a 命名、审计no-grant拒绝(默认拒绝)。守护进程还通过HTTP在以下位置挂载MCPPOST /127.0.0.1:4319/mcp.
③ OpenAI兼容代理(Ollama、llama.cpp、vLLM、任何OpenAI兼容客户端)
运行代理(将模型服务器设置为上游),并将客户端的基本URL指向它:
SKILLFORGE_PROXY_PORT=4320 node --experimental-strip-types packages/proxy/src/bin.ts
# then use base URL http://127.0.0.1:4320/v1 in any OpenAI-compatible client
您应该看到: 聊天响应携带
x-skill-injected/x-skill-disclosure/x-skill-tierheaders(临时注入在headers中是证明)。守护进程还提供/v1/*上:4319.
开发(零安装)
继续运行 节点≥22.18 通过原生TypeScript类型剥离-- 无构建步骤;运行时没有依赖关系 (唯一的npm deps存在于一个隔离的、仅限开发人员的typecheck sidecar中,该sidecar由 tsc 门)。
# Full suite — --experimental-sqlite is required for the daemon (node:sqlite) suite;
# some machines OOM without --test-concurrency=2.
node --experimental-strip-types --experimental-sqlite --test-concurrency=2 --test "packages/**/test/*.ts"
# The two other local gates (mirrored in CI):
node scripts/lint-core-no-child-process.mjs # core stays child_process-free outside the audited exec chokepoint
node scripts/typecheck.mjs # tsc --noEmit over src + tests via the dev-only sidecar
测试和质量门
flowchart LR
subgraph gate["every push / PR"]
L1["lint:<br/>core child_process-free"]
L2["lint:<br/>no proprietary fixtures"]
TS["tsc --noEmit<br/>(src + tests)"]
TEST["343 tests<br/>(node:test)"]
end
L1 --> OK["✅ merge"]
L2 --> OK
TS --> OK
TEST --> OK
路由门与 约28项真实技能+一个带标签的查询集.对等是 在三条注入路径上经过验证 针对核心——LM Studio插件(黄金平价,D5)、代理(黄金平价)和守护进程 /route-test (§8)——加上a 碰撞重启 证明(DB重建+陈旧性,第5节)和a 负设假防火天花板Lexical完全离线运行;语义层使用本地嵌入端点,如果无法到达,则自动跳过。
状态
MVP发货 --运行时+可视化管理器跨所有三个注入目标工作,由CLI、可选的本地守护进程和只读UI支持。LM Studio插件的选择/注入经过无头测试;将其连接到LM Studio的GUI是一个一次性的手动步骤(packages/lmstudio-plugin/RUNBOOK.md).
许可证
阿帕奇-2.0 --看 LICENSE.
捆绑夹具技能 packages/contracts/fixtures/skills/ 是第三方提供的内容(Anthropic 阿帕奇-2.0 技能和超能力 麻省理工学院 技能)。看 NOTICE 对于所需的归因, THIRD_PARTY_LICENSES.md 获取完整的上游许可证文本,以及 ATTRIBUTIONS.md 对于每种技能的来源图。
