@cmkk/agentlink
v0.1.0-beta.1
Published
Symlink your .agents/ assets into .cursor / .claude / .codebuddy and other AI agent directories with a single npx.
Maintainers
Readme
@cmkk/agentlink
一行
npx,把.agents/里的 skills / rules / commands 投影到.cursor、.claude、.codebuddy等多个 AI 工具目录。
agentlink 让 .agents/ 成为单一可信源,再通过逐 agent 的轻量 adapter(处理 flatten、rename、include / exclude)投影到各家工具——全程 symlink,不复制。
为什么需要 agentlink
.agents/ 正在悄悄成为 AI 工具间的事实约定——Cursor、Codex 已经支持从 .agents/skills/ 读取 SKILL.md,其他 agent 也在跟进。但在这个约定完全统一之前,同时使用两个以上 AI 编码工具的人,都得在 .cursor / .claude / .codebuddy / ... 之间手动复制同一份 skill / rule / command。而且各家工具还有自己的小约定:
- Cursor 的 commands 目录不支持嵌套(必须扁平)
- Cursor 的 rules 必须用
.mdc后缀 - Claude Code 从
.claude/skills/<name>/SKILL.md递归读取 - CodeBuddy 支持嵌套 commands
agentlink 就是为了弥合这个差距:
单一可信源 — 所有资产维护在一个
.agents/目录(个人用~/.agents,团队场景用项目内cwd/.agents)。投影而非复制 — agentlink 在每个目标 agent 的目录下,为每个一级条目创建一个 symlink,并通过声明式 adapter 处理 agent 特有约定(flatten、
.mdc重命名、扁平 vs 嵌套)。与
skills.sh互补 —skills.sh负责把 skill 包安装(下载)到源目录;agentlink负责把源目录投影到多个工具。两者解决的是同一工作流的不同环节:curl -fsSL skills.sh | sh -s install <pkg> # 安装到 ~/.agents/skills/<pkg> agentlink sync # 投影到 .cursor / .claude / ...
为什么是"逐项 symlink"而不是"整目录 symlink"
最朴素的实现是 ln -s .agents/skills .cursor/skills——整目录一条链接,简单。但这样做会让目标目录变成实际只读:你没法再往 .cursor/skills/scratch/ 里临时塞一个一次性的 skill 做实验,因为整个目录已经是源目录的别名。
agentlink 改为为每个一级条目单独创建一条 symlink(或当 flatten: true 时,按文件粒度)。受管的 skill 与你手写的 skill 可以并存在同一目录里,unlink 也只会移除自己创建的那些链接——你的临时实验不会被波及。
快速上手
# 1. 在 ~/.agents 建脚手架(或加 --local 建在 ./.agents)
npx @cmkk/agentlink init
# 2. 把你的 skills/rules/commands 放进 ~/.agents/
# 3. 进入任何含 .cursor/、.claude/ 或 .codebuddy/ 的项目
cd ~/projects/some-app
npx @cmkk/agentlink sync命令
agentlink init [--local | --source <path>] [--force] [--yes]
交互式创建 .agents/ 脚手架。三个简短提问:
1) 放在哪里(~/.agents vs ./.agents)
2) 启用哪些资产类型(skills/rules/commands/...)
3) 投影到哪些 AI 工具(cursor/claude/codebuddy)
--yes / -y 全部用默认值,跳过交互(CI 友好)
--local 跳过位置选择,直接用 ./.agents
--source <p> 跳过位置选择,用指定路径(自定义路径会打印持久化提示)
--force 目标非空时仍然合并(默认会拒绝)
管道 / 脚本场景(stdin 非 TTY)自动降级为默认值。
生成的 agentlink.config.json 写在"未来 sync 会从哪跑"的位置
(--local 写 cwd,否则写 ~),不在 source 内部。
agentlink sync [--source <path>] [--target <dir> | --user] [-n] [-f] [--strict]
刷新所有 symlink。source 按以下优先级解析:
--source flag → $AGENTLINK_SOURCE → ./.agents → ~/.agents
destination root 默认是 cwd;--user / -u 改为 $HOME(把 source
投影到 ~/.cursor / ~/.claude / ...),--target <dir> 指定任意项目根。
--dry-run / -n 预览将做什么,不动文件系统
--force / -f 修复指向错误的 symlink
--strict flatten 撞名时报错退出(默认仅警告)
agentlink clean
清掉每个启用 adapter 目录下的悬空 symlink(指向已删除文件)。
agentlink unlink
移除所有指向 source 的 symlink,用于从项目中彻底卸载 agentlink。
agentlink doctor
只读健康检查:adapter 可用性、link plan 大小、撞名预警、
悬空链接、orphan 链接(之前 sync 留下、当前 plan 不再覆盖)。-q/--quiet 与 -v/--verbose 对所有命令通用。
source 与 config 解析
agentlink 把"对什么数据操作"(.agents/ source)与"怎么操作"(agentlink.config.json)解耦:两者各有独立解析链,可以共享同一份 source 但每个项目用自己的 config 覆盖行为。
source 解析
| # | 来源 | 说明 |
|---|---|---|
| 1 | --source <path> | 显式 flag |
| 2 | AGENTLINK_SOURCE 环境变量 | 适合写在 shell rc |
| 3 | ./.agents | 本地优先 — 克隆的项目自带 .agents/ 时压过个人全局 |
| 4 | ~/.agents | 个人推荐默认 |
| 5 | (报错) | 提示用户跑 agentlink init |
config 解析
| # | 来源 | 说明 |
|---|---|---|
| 1 | --config <path> | 显式 flag |
| 2 | AGENTLINK_CONFIG 环境变量 | |
| 3 | 从 cwd 向上找最近的 agentlink.config.json | cwd 在 home 内时停在 home;cwd 在 home 外时走到 fs 根 |
| 4 | ~/agentlink.config.json | 全局兜底 |
| 5 | (默认值) | 没找到 = 视为空配置 {} |
类似 git / eslint / tsconfig 的就近发现机制。
配置文件
配置文件可选——每个字段都是可选的且有合理默认值。格式是 JSONC(标准 JSON + // /* */ 注释 + 尾逗号),所以 agentlink init 写出的种子文件自带注释,看一眼就能改,不必翻文档。
严格的闭世界 schema(用 zod 校验):adapter 名、asset 类型、顶层字段拼错都会被友好地拒绝。
{
// asset 类型白名单。默认:["skills", "rules", "commands"]
// 想启用 prompts / templates / agents 在这里加上即可
"include": ["skills", "rules", "commands"],
// asset 类型黑名单(永远压过 include)
"exclude": [],
// 各 adapter 的覆盖。值可以是 true / false / { layout: ... }
"adapters": {
"cursor": { "layout": { "commands": { "flatten": false } } },
"claude": true,
"codebuddy": false
}
}内置 adapter(v1)
| 名称 | rootDir | Skills | Rules | Commands | Prompts |
|---|---|---|---|---|---|
| cursor | .cursor/ | 嵌套 | 扁平,.md → .mdc | 扁平 | 跳过 |
| claude | .claude/ | 嵌套 | 嵌套 | 嵌套 | 未配置 |
| codebuddy | .codebuddy/ | 嵌套 | 嵌套 | 嵌套 | 未配置 |
agentlink 只会在 destination 下已经存在对应 rootDir 时才动它。绝不会主动帮你创建 .cursor/——要启用某个 agent,要么让 agent 自己跑一遍,要么手动 mkdir .cursor 表态。
需要新 agent?v1 仅内置上述三家;提 PR 加一个新 adapter 文件即可。
投影示意
~/.agents/skills/brainstorming/SKILL.md ─┐
├─→ .cursor/skills/brainstorming/ (symlink)
├─→ .claude/skills/brainstorming/ (symlink)
└─→ .codebuddy/skills/brainstorming/ (symlink)
~/.agents/rules/coding.md ─→ .cursor/rules/coding.mdc (ext 重命名)
~/.agents/commands/git/commit.md ─→ .cursor/commands/git__commit.md (flatten)
└→ .codebuddy/commands/git/commit.md (保留嵌套)相比手写 symlink
- 所有链接都是相对路径:source 和 destination 一起搬家不会断
sync是幂等的:相同状态下重跑全部skippedunlink只移除"自己拥有"的(指向当前 source 的)链接,目录里其他手写内容不动--dry-run精确告诉你"会做什么",零写盘
运行要求
- Node 18+
- 支持 symlink 的 POSIX 风格文件系统。Windows 上请在 WSL 内运行或开启开发者模式
状态
v1:skill / rule / command 链接、JSONC 配置、三个内置 adapter。
不在 v1 范围(独立追踪):
- JS / TS 配置文件(
agentlink.config.{js,ts}) - 用户自定义 adapter(通过配置)
link <src> <dest>命令式接口- watch 模式
许可证
MIT.
