harveyz-skill 0.14.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.14.1] - 2026-06-14
11
+
12
+ ### Fixed
13
+ - `hub` 安装失败(`source_not_found`):新增 `hub.sh` 启动脚本,安装器现在能正确找到 hub 入口
14
+ - `hub` tool.json `extraPaths` 路径错误(`core/cli` 不在工具根目录),修正为 `["hub", "pyproject.toml"]`
15
+ - `hub` 卸载后遗留 `~/.hskill/tools/hub/` Python 源码目录,将其加入 `uninstallPaths`
16
+ - hskill 交互流程次级 fzf 页面(action/target/scope)缺少 preview 面板,视觉风格与主列表页不一致
17
+
18
+ ### Added
19
+ - `docs/how-to/use-hub.md`:hub 人用操作指南(安装、TUI、projects/tasks 常用命令)
20
+ - `docs/reference/hub-reference.md`:hub CLI 完整参考(供 agent 调用,含 JSON 输出格式)
21
+
10
22
  ## [0.14.0] - 2026-06-14
11
23
 
12
24
  ### Added
package/bin/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { select, input } from '@inquirer/prompts'
3
3
  import chalk from 'chalk'
4
4
  import { execSync, spawnSync } from 'child_process'
5
- import { existsSync } from 'fs'
5
+ import { existsSync, writeFileSync, unlinkSync } from 'fs'
6
6
  import { createRequire } from 'module'
7
7
  import os from 'os'
8
8
  import path from 'path'
@@ -629,6 +629,8 @@ function selectTargetThenScope() {
629
629
  '--layout=reverse',
630
630
  '--border=rounded',
631
631
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
632
+ '--preview=t=$(echo {} | awk \'{print $1}\'); if [ "$t" = "all" ]; then echo ""; echo " 安装到所有平台:"; echo ""; for p in claude cursor codex openclaw hermes opencode; do printf " ~/.%s/skills/\\n" "$p"; done; else p="${HOME}/.${t}/skills/"; echo ""; echo " 安装路径:"; echo ""; printf " \\033[36m%s\\033[0m\\n" "$p"; echo ""; if [ -d "$p" ]; then echo " ✓ 目录已存在"; else echo " · 将自动新建"; fi; fi',
633
+ '--preview-window=right:45%:wrap',
632
634
  ], {
633
635
  input: targetInput,
634
636
  encoding: 'utf8',
@@ -651,6 +653,8 @@ function selectTargetThenScope() {
651
653
  '--layout=reverse',
652
654
  '--border=rounded',
653
655
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
656
+ '--preview=s=$(echo {} | awk \'{print $1}\'); if [ "$s" = "user" ]; then echo ""; echo " ~/.{target}/skills/"; echo ""; echo " 所有项目共享,适合常用 skill"; echo ""; echo " ✓ 推荐选项"; else echo ""; echo " .{target}/skills/"; echo ""; echo " 仅当前项目可见"; echo ""; echo " 适合项目专属 skill"; fi',
657
+ '--preview-window=right:45%:wrap',
654
658
  ], {
655
659
  input: 'user — 所有项目共享 (~/.{target}/skills/)\nproject — 仅当前项目 (.{target}/skills/)',
656
660
  encoding: 'utf8',
@@ -898,17 +902,30 @@ try {
898
902
  })
899
903
 
900
904
  if (anyInstalled) {
905
+ const actionPreviewFile = `/tmp/hskill-action-preview-${process.pid}.txt`
906
+ const actionPreviewLines = [
907
+ '',
908
+ ' 已选中:',
909
+ '',
910
+ ...skillItems.map(s => ` skill ${s.skillName}`),
911
+ ...toolItems.map(t => ` tool ${t.toolName}`),
912
+ ...hookItems.map(h => ` hook ${h.name}`),
913
+ ]
914
+ writeFileSync(actionPreviewFile, actionPreviewLines.join('\n'))
901
915
  const actionResult = spawnSync('fzf', [
902
916
  '--prompt= › ',
903
917
  '--header= Action · enter 确认 · esc 取消',
904
918
  '--layout=reverse',
905
919
  '--border=rounded',
906
920
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
921
+ `--preview=cat ${actionPreviewFile}`,
922
+ '--preview-window=right:45%:wrap',
907
923
  ], {
908
924
  input: `install 安装 / 重新安装\nuninstall 卸载并清理文件`,
909
925
  encoding: 'utf8',
910
926
  stdio: ['pipe', 'pipe', 'inherit'],
911
927
  })
928
+ try { unlinkSync(actionPreviewFile) } catch { /* ignore */ }
912
929
  if (!actionResult.stdout.trim()) {
913
930
  console.log(chalk.dim(' · Cancelled'))
914
931
  break
@@ -964,6 +981,8 @@ try {
964
981
  '--layout=reverse',
965
982
  '--border=rounded',
966
983
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
984
+ '--preview=s=$(echo {} | awk \'{print $1}\'); if [ "$s" = "user" ]; then echo ""; echo " ~/.claude/hooks/"; echo " ~/.codex/hooks/"; echo ""; echo " 所有项目共享"; else echo ""; echo " .claude/hooks/"; echo " .codex/hooks/"; echo ""; echo " 仅当前项目"; fi',
985
+ '--preview-window=right:45%:wrap',
967
986
  ], {
968
987
  input: `user — ~/.{claude,codex}/hooks/ (所有项目共享)\nproject — .{claude,codex}/hooks/ (仅当前项目)`,
969
988
  encoding: 'utf8',
@@ -983,6 +1002,8 @@ try {
983
1002
  '--layout=reverse',
984
1003
  '--border=rounded',
985
1004
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
1005
+ '--preview=t=$(echo {} | awk \'{print $1}\'); if [ "$t" = "all" ]; then echo ""; echo " ~/.claude/hooks/"; echo " ~/.codex/hooks/"; else echo ""; printf " ~/.%s/hooks/\\n" "$t"; fi',
1006
+ '--preview-window=right:45%:wrap',
986
1007
  ], {
987
1008
  input: `claude — ~/.claude/hooks/\ncodex — ~/.codex/hooks/\nall — claude + codex`,
988
1009
  encoding: 'utf8',
@@ -1033,6 +1054,8 @@ try {
1033
1054
  '--header= 从哪里卸载 · tab 多选 · enter 确认 · esc 取消',
1034
1055
  '--layout=reverse', '--border=rounded',
1035
1056
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
1057
+ '--preview=t=$(echo {} | awk \'{print $1}\'); if [ "$t" = "all" ]; then echo ""; echo " 从所有平台卸载:"; echo ""; for p in claude cursor codex openclaw hermes opencode; do printf " ~/.%s/skills/\\n" "$p"; done; else echo ""; printf " ~/.%s/skills/\\n" "$t"; fi',
1058
+ '--preview-window=right:45%:wrap',
1036
1059
  ], {
1037
1060
  input: targetChoices2.map(c => c.name).join('\n') + '\nall — all targets',
1038
1061
  encoding: 'utf8', stdio: ['pipe', 'pipe', 'inherit'],
@@ -1046,6 +1069,8 @@ try {
1046
1069
  '--header= 卸载范围 · enter 确认 · esc 取消',
1047
1070
  '--layout=reverse', '--border=rounded',
1048
1071
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
1072
+ '--preview=s=$(echo {} | awk \'{print $1}\'); if [ "$s" = "user" ]; then echo ""; echo " 从 user 级卸载:"; echo " ~/.{target}/skills/"; else echo ""; echo " 从 project 级卸载:"; echo " .{target}/skills/"; fi',
1073
+ '--preview-window=right:45%:wrap',
1049
1074
  ], {
1050
1075
  input: 'user — 所有项目 (~/.{target}/skills/)\nproject — 仅当前项目 (.{target}/skills/)',
1051
1076
  encoding: 'utf8', stdio: ['pipe', 'pipe', 'inherit'],
@@ -1065,6 +1090,8 @@ try {
1065
1090
  '--header= Hook scope · enter 确认',
1066
1091
  '--layout=reverse', '--border=rounded',
1067
1092
  '--color=header:italic:dim,prompt:cyan,pointer:cyan,hl:cyan,hl+:cyan:bold',
1093
+ '--preview=s=$(echo {} | awk \'{print $1}\'); if [ "$s" = "user" ]; then echo ""; echo " 从 user 级卸载 hook:"; echo " ~/.claude/hooks/"; else echo ""; echo " 从 project 级卸载 hook:"; echo " .claude/hooks/"; fi',
1094
+ '--preview-window=right:45%:wrap',
1068
1095
  ], {
1069
1096
  input: `user — ~/.claude/hooks/\nproject — .claude/hooks/`,
1070
1097
  encoding: 'utf8', stdio: ['pipe', 'pipe', 'inherit'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harveyz-skill",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "description": "Skill manager for Claude Code, Cursor, and Codex",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ VENV_DIR="${HOME}/.hskill/tools/hub/venv"
5
+ INSTALL_DIR="${HOME}/.hskill/tools/hub"
6
+
7
+ if [ ! -x "${VENV_DIR}/bin/hub" ]; then
8
+ python3 -m venv "${VENV_DIR}"
9
+ "${VENV_DIR}/bin/pip" install -q "${INSTALL_DIR}"
10
+ fi
11
+
12
+ exec "${VENV_DIR}/bin/hub" "$@"
@@ -2,7 +2,7 @@
2
2
  "name": "hub",
3
3
  "version": "1.0.0",
4
4
  "description": "personal developer OS — projects, git status, tasks",
5
- "extraPaths": ["core", "cli", "pyproject.toml"],
6
- "uninstallPaths": ["~/.hskill/tools/hub/venv"],
5
+ "extraPaths": ["hub", "pyproject.toml"],
6
+ "uninstallPaths": ["~/.hskill/tools/hub/venv", "~/.hskill/tools/hub"],
7
7
  "configPaths": ["~/.hskill/hub"]
8
8
  }