Lines 1-21javascript
2import{Command as e}from"commander";import t from"picocolors";import{z as n}from"zod";import{chmodSync as r,closeSync as i,copyFileSync as a,cpSync as o,existsSync as s,lstatSync as c,mkdirSync as l,openSync as u,readFileSync as d,readdirSync as f,readlinkSync as ee,realpathSync as p,renameSync as m,rmSync as h,statSync as te,symlinkSync as ne,writeFileSync as g,writeSync as re}from"node:fs";import{basename as ie,dirname as _,join as v,resolve as ae}from"node:path";import{homedir as y,hostname as oe,platform as se}from"node:os";import{createHash as ce,randomBytes as le}from"node:crypto";import ...
3`)):ne(n,c,`dir`),r.linked.push(c)}return r}function $e(e){try{return c(e).isSymbolicLink()}catch{return!1}}function L(e,t){let n=new Set(t);for(let t of Ye)n.add(v(t.skillsDir(),e));for(let e of n)(s(e)||$e(e))&&Ze(e)&&h(e,{recursive:!0,force:!0})}function et(e){return ce(`sha256`).update(e).digest(`hex`)}async function tt(e,t){h(t,{recursive:!0,force:!0}),l(t,{recursive:!0}),await de(ue.from(e),fe({cwd:t}))}async function nt(e,t){l(E(),{recursive:!0});let n=!1;if(!t||t.hash!==e.hash){let t=await We(e.name),r=et(t);if(r!==e.hash)throw new N(`${e.name} 校验失败(期望 ${e.hash.slice(0,8)},实际 ${r.slice ...
HighSame File Env Network Execution
A single source file combines environment access, network access, and code or shell execution; review context before blocking.
dist/index.jsView on unpkg · L1 4---`),console.log(`[yz-cli] ${n.name}@${n.version}(${n.displayName})`),o.length){console.log(`[yz-cli] 附属文件(用你的文件工具按需读取):`);for(let e of o)console.log(e)}console.error(t.dim(`(来源:${i})`))}async function pt(e){if(!S.test(e))throw new N(`非法技能名:${e}`);let n=(await z()).skills.find(t=>t.name===e);if(!n)throw new N(`未找到技能「${e}」(或当前帐号未被授权);试试 yz-cli skills search <关键词>`);let r=A(),i=r.skills[e],a=i?.hash===n.hash,{installed:o,skipped:s}=await nt(n,i);r.skills[e]=o,j(r);for(let n of s)console.log(t.yellow(`⚠ ${e}: ${n.reason}(${n.path})`));let c=I().map(e=>e.displayName).join(` / `);a?console.log(t.g ...
5`),o=gt();l(_(o),{recursive:!0}),g(o,a);let s=`gui/${process.getuid?.()??0}`;return U([`bootout`,`${s}/${B}`]),U([`bootstrap`,s,o])||U([`load`,`-w`,o])?t.green(`✓ launchd 定时同步已注册(每小时一次,未变更走 304)`):t.yellow(`· launchd plist 已写入但激活未确认:${o}(下次登录自动生效)`)}function yt(){let e=gt();return s(e)?(U([`bootout`,`gui/${process.getuid?.()??0}/${B}`])||U([`unload`,`-w`,e]),h(e,{force:!0}),t.green(`✓ launchd 定时同步已移除`)):null}const W=e=>`'${e.replace(/'/
6`),a=[`[Unit]`,`Description=yz-cli skills sync (每小时)`,``,`[Timer]`,`OnActiveSec=1min`,`OnUnitActiveSec=1h`,``,`[Install]`,`WantedBy=timers.target`,``].join(`
7`);return g(v(e,wt),i),g(v(e,G),a),q([`daemon-reload`]),q([`enable`,`--now`,G])?t.green(`✓ systemd 定时同步已注册(每小时一次,未变更走 304)`):t.yellow(`· systemd 单元已写入但激活未确认:${e}(下次登录自动生效)`)}function Ot(){let e=Tt(),n=v(e,wt),r=v(e,G);return!s(n)&&!s(r)?null:(q([`disable`,`--now`,G]),h(r,{force:!0}),h(n,{force:!0}),q([`daemon-reload`]),t.green(`✓ systemd 定时同步已移除`))}const kt=e=>`'${e.replace(/'/g,`'\\''`)}'`;function At(){try{let e=b(`crontab`,[`-l`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]});return e?e.replace(/\n$/,``).split(`
8`):[]}catch{return[]}}function jt(e){try{return b(`crontab`,[`-`],{input:`${e.join(`
9`)}\n`,stdio:[`pipe`,`ignore`,`ignore`]}),!0}catch{return!1}}function Mt(){let{program:e,prefix:n}=H(),r=`0 * * * * ${[e,...n,...V].map(kt).join(` `)} >> ${kt(ht())} 2>&1 # ${K}`,i=`# yz-cli skills sync (managed) [${K}]`;return jt([...At().filter(e=>!e.includes(K)),i,r])?t.green(`✓ crontab 定时同步已注册(每小时一次)`):null}function Nt(){let e=At(),n=e.filter(e=>!e.includes(K));return n.length===e.length?null:jt(n)?t.green(`✓ crontab 定时同步已移除`):null}function Pt(){return Dt()??Mt()??t.yellow(`· 定时同步未注册(无可用 systemd --user / crontab);Claude Code 仍走会话 hook,其余可手动 yz-cli skills sync`)}function Ft(){let e=Ot(),t=N ...
10正在接线本机 agent…`),Vt(),console.log(`
HighCommand Output Exfiltration
Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.
dist/index.jsView on unpkg · L1 MediumInstall Persistence
Source writes installer persistence such as shell profile or service configuration.
dist/index.jsView on unpkg · L1 11正在同步 skills…`),await Jt({quiet:!1})}async function $t(){let e=await He();console.log(`${t.bold(e.account.name)}${e.account.email?`(${e.account.email})`:``}`),console.log(t.dim(`服务端:${P()}`)),console.log(t.dim(`可用 skills:${e.entitledSkills.join(`, `)||`(无)`}`))}async function en(){try{await qe()}catch{}ke(),Pe(),console.log(t.green(`✓ 已退出登录(本机 token 已吊销)`))}async function tn(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf8`)}async function nn(e,n,r){let i=e.toUpperCase(),a=n.startsWith(`/`)?n:`/${n}`;if(r.params){let e;try{e=JSON.parse(r.params)}catch ...
12`)).version(M),Z.addHelpText(`after`,[``,`常用流程:`,` 首次使用 yz-cli login 登录并自动接线(建目录 / 写自动同步 hook)`,` 服务账号 YZ_CLI_CLIENT_ID=svc_xxx YZ_CLI_CLIENT_SECRET=yzsk_xxx yz-cli skills sync`,` yz-cli login --client-id svc_xxx --client-secret yzsk_xxx # 固定机器持久登录`,` 找技能 yz-cli skills search 数据库 查询 多词 AND;yz-cli skills list 看全量`,` 用技能 yz-cli skills info db-query stdout 即技能全文,照内容执行`,` 装技能 yz-cli skills install db-query 常驻为本机可复用技能`,` 调后端 yz-cli api POST /skill-api/db-query/query -d '{"sql":"select 1"}'`,` 排障 yz-cli doct ...
13`)),Z.command(`login`).summary(`飞书扫码登录 / 服务账号非交互登录`).description([`默认打开浏览器完成飞书扫码登录,凭据写入本机 ~/.yz;登录成功后自动接线本机 agent`,`(建 skills 目录、为 Claude Code 写会话启动自动同步 hook、注册定时器)并做首次同步。`,`帐号为白名单制:登录被拦截时,把拦截页显示的 union_id 发给管理员,`,`在 hyperion-central 后台「原则 CLI → 员工帐号」添加后重试。`,``,`CI / 服务器 / headless agent 可用服务账号:`,` 推荐用 YZ_CLI_CLIENT_ID + YZ_CLI_CLIENT_SECRET 运行命令(secret 不落盘)。`,` 或用 --client-id + --client-secret 持久登录(secret 写入 ~/.yz/service-token.json)。`].join(`
14`)).option(`--no-browser`,`不打开浏览器(SSH 等场景),手动粘贴一次性代码`).option(`--client-id <id>`,`服务账号非交互登录:client_id(需同时给 --client-secret;无需飞书交互)`).option(`--client-secret <secret>`,`服务账号非交互登录:client_secret`).addHelpText(`after`,[``,`示例:`,` yz-cli login`,` yz-cli login --no-browser`,` yz-cli login --client-id svc_xxx --client-secret yzsk_xxx`,` YZ_CLI_CLIENT_ID=svc_xxx YZ_CLI_CLIENT_SECRET=yzsk_xxx yz-cli skills sync`].join(`
15`)).action(e=>$(()=>Qt(e))),Z.command(`logout`).summary(`退出登录并吊销本机 token`).description(`通知服务端吊销本机 token,并删除本地凭据(服务端不可达时仅清本地)。`).action(()=>$(en)),Z.command(`whoami`).summary(`查看当前帐号与授权技能`).description(`输出当前登录帐号(姓名/邮箱)、连接的服务端地址、被授权的技能名单。`).action(()=>$($t)),Z.command(`doctor`).summary(`环境自检`).description(`依次检查:服务端连通性、登录态有效性、本机 agent 检测结果、本地受管技能数量。排障第一步。`).action(()=>$(rn)),Z.command(`update`).summary(`升级到最新版本`).description([`自动检测安装方式并就地升级到最新版本:`,` 二进制 — 从 OSS 下载最新构建、校验 sha256 后原子替换运行中的可执行文件;`,` npm — 检查 registry,已是最新则跳过,否则调用对应包管理器(npm/pnpm/yarn/bun)全局安装。`].join(`
16`)).action(()=>$(dn)),Z.command(`api`).summary(`带登录态调用后端接口`).description([`对后端任意接口发起带登录态的请求,响应输出到 stdout(默认 pretty JSON,HTTP 状态走 stderr)。`,`path 原样透传:/skill-api/<skill>/<endpoint> 调技能后端,/v1/* 调平台接口——`,`skills 对应的接口只是 yz-cli api 能触达的众多命名空间之一。`].join(`
17`)).argument(`<method>`,`HTTP 方法:GET / POST / PATCH / PUT / DELETE`).argument(`<path>`,`请求路径,如 /v1/me 或 /skill-api/<skill>/<endpoint>`).option(`--params <json>`,`query 参数(JSON 对象)`).option(`-d, --data <json>`,`请求体 JSON(或 @文件路径 / - 从 stdin 读)`).option(`--dry-run`,`只打印将发出的请求,不执行`,!1).addHelpText(`after`,[``,`示例:`,` yz-cli api GET /v1/me`,` yz-cli api POST /skill-api/db-query/query -d '{"sql":"select 1"}'`,` yz-cli api GET /skill-api/db-query/tables --params '{"schema":"public"}'`].join(`
18`)).action((e,t,n)=>$(()=>nn(e,t,n)));const Q=Z.command(`skills`).summary(`技能目录与生命周期(list / search / info / install / sync / uninstall)`).description(`公司技能的发现、取用、安装与维护。具体见各子命令:yz-cli skills help <command>。`);Q.command(`list`).summary(`列出全部授权技能与本地状态`).description([`列出当前帐号全部授权技能(自动安装 + 按需)。`,`每行:名称 / 分发模式(自动|按需)/ 最新版本 / 本地状态 / 描述。`,`本地状态:✓ 最新、↑ 可更新、已缓存(info 取用过)、未装。`,`自动技能由 yz-cli skills sync 维护;按需技能用 yz-cli skills install <name> 安装。`].join(`
19`)).option(`--json`,`JSON 输出(含 displayName/requiresBackend/targets/status 等完整字段)`,!1).action(e=>$(()=>ot(e))),Q.command(`search`).summary(`按关键词检索技能目录`).description([`在技能的名称/显示名/描述里检索,多个关键词为 AND 关系,输出格式同 list。`,`无结果时换关键词重试(中英文都试);仍无结果再用 yz-cli skills list 浏览全量。`,`命中后用 yz-cli skills info <name> 取用、或 yz-cli skills install <name> 安装。`].join(`
20`)).argument(`<query...>`,`关键词(可多个,AND 匹配)`).option(`--json`,`JSON 输出`,!1).addHelpText(`after`,`
Long lines were clipped for display.