happyskills 0.3.0 → 0.3.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 +5 -0
- package/package.json +1 -1
- package/src/commands/convert.js +4 -3
- package/src/commands/list.js +2 -2
- package/src/commands/update.js +4 -3
- package/src/config/paths.js +5 -0
- package/src/engine/installer.js +4 -3
- package/src/engine/uninstaller.js +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.1] - 2026-03-04
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Fix global installs writing `skills-lock.json` to the local project directory instead of `~/.claude/`; global lock state is now read/written from `~/.claude/skills-lock.json` across `install`, `uninstall`, `list`, `update`, and `convert` commands
|
|
14
|
+
|
|
10
15
|
## [0.3.0] - 2026-03-04
|
|
11
16
|
|
|
12
17
|
### Added
|
package/package.json
CHANGED
package/src/commands/convert.js
CHANGED
|
@@ -12,7 +12,7 @@ const { write_manifest } = require('../manifest/writer')
|
|
|
12
12
|
const { read_lock } = require('../lock/reader')
|
|
13
13
|
const { write_lock, update_lock_skills } = require('../lock/writer')
|
|
14
14
|
const { hash_directory } = require('../lock/integrity')
|
|
15
|
-
const { skills_dir, find_project_root } = require('../config/paths')
|
|
15
|
+
const { skills_dir, find_project_root, lock_root } = require('../config/paths')
|
|
16
16
|
const { file_exists } = require('../utils/fs')
|
|
17
17
|
const { create_spinner } = require('../ui/spinner')
|
|
18
18
|
const { print_help, print_success, print_error, print_info, print_label, print_json } = require('../ui/output')
|
|
@@ -154,7 +154,8 @@ const run = (args) => catch_errors('Convert failed', async () => {
|
|
|
154
154
|
if (push_err) { pub_spinner.fail('Publish failed'); throw e('Push failed', push_err) }
|
|
155
155
|
|
|
156
156
|
pub_spinner.update('Updating lock file...')
|
|
157
|
-
const
|
|
157
|
+
const lock_dir = lock_root(is_global, project_root)
|
|
158
|
+
const [, lock_data] = await read_lock(lock_dir)
|
|
158
159
|
const [, integrity] = await hash_directory(skill_dir)
|
|
159
160
|
|
|
160
161
|
const full_name = `${workspace.slug}/${skill_name}`
|
|
@@ -170,7 +171,7 @@ const run = (args) => catch_errors('Convert failed', async () => {
|
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
const new_skills = update_lock_skills(lock_data, updates)
|
|
173
|
-
const [lock_err] = await write_lock(
|
|
174
|
+
const [lock_err] = await write_lock(lock_dir, new_skills)
|
|
174
175
|
if (lock_err) { pub_spinner.fail('Failed to write lock file'); throw e('Lock write failed', lock_err) }
|
|
175
176
|
|
|
176
177
|
pub_spinner.succeed(`Converted ${full_name}@${version}`)
|
package/src/commands/list.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { error: { catch_errors, wrap_errors: e } } = require('puffy-core')
|
|
2
2
|
const { read_lock, get_all_locked_skills } = require('../lock/reader')
|
|
3
|
-
const { skills_dir, skill_install_dir, find_project_root } = require('../config/paths')
|
|
3
|
+
const { skills_dir, skill_install_dir, find_project_root, lock_root } = require('../config/paths')
|
|
4
4
|
const { file_exists } = require('../utils/fs')
|
|
5
5
|
const { scan_skills_dir } = require('../utils/skill_scanner')
|
|
6
6
|
const { print_help, print_table, print_json, print_info } = require('../ui/output')
|
|
@@ -32,7 +32,7 @@ const run = (args) => catch_errors('List failed', async () => {
|
|
|
32
32
|
const project_root = find_project_root()
|
|
33
33
|
const base_dir = skills_dir(is_global, project_root)
|
|
34
34
|
|
|
35
|
-
const [, lock_data] = await read_lock(project_root)
|
|
35
|
+
const [, lock_data] = await read_lock(lock_root(is_global, project_root))
|
|
36
36
|
const skills = get_all_locked_skills(lock_data)
|
|
37
37
|
const managed_entries = Object.entries(skills)
|
|
38
38
|
|
package/src/commands/update.js
CHANGED
|
@@ -3,7 +3,7 @@ const { install } = require('../engine/installer')
|
|
|
3
3
|
const { read_lock, get_all_locked_skills } = require('../lock/reader')
|
|
4
4
|
const { print_help, print_success, print_info, print_json } = require('../ui/output')
|
|
5
5
|
const { exit_with_error, UsageError } = require('../utils/errors')
|
|
6
|
-
const { find_project_root } = require('../config/paths')
|
|
6
|
+
const { find_project_root, lock_root } = require('../config/paths')
|
|
7
7
|
const { EXIT_CODES } = require('../constants')
|
|
8
8
|
|
|
9
9
|
const HELP_TEXT = `Usage: happyskills update [owner/skill|--all] [options]
|
|
@@ -40,7 +40,8 @@ const run = (args) => catch_errors('Update failed', async () => {
|
|
|
40
40
|
throw new UsageError("Specify a skill to update or use --all (e.g., 'happyskills update acme/deploy-aws' or 'happyskills update --all').")
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const
|
|
43
|
+
const is_global = args.flags.global || false
|
|
44
|
+
const [, lock_data] = await read_lock(lock_root(is_global, project_root))
|
|
44
45
|
const skills = get_all_locked_skills(lock_data)
|
|
45
46
|
|
|
46
47
|
const to_update = target_skill
|
|
@@ -57,7 +58,7 @@ const run = (args) => catch_errors('Update failed', async () => {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
const options = {
|
|
60
|
-
global:
|
|
61
|
+
global: is_global,
|
|
61
62
|
fresh: true,
|
|
62
63
|
project_root
|
|
63
64
|
}
|
package/src/config/paths.js
CHANGED
|
@@ -26,6 +26,10 @@ const tmp_dir = (base_skills_dir) => path.join(base_skills_dir, '.tmp')
|
|
|
26
26
|
|
|
27
27
|
const install_lock_path = (base_skills_dir) => path.join(base_skills_dir, '.install.lock')
|
|
28
28
|
|
|
29
|
+
const lock_root = (is_global, project_root) => {
|
|
30
|
+
return is_global ? path.join(home_dir, '.claude') : project_root
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
const lock_file_path = (project_root = process.cwd()) => path.join(project_root, 'skills-lock.json')
|
|
30
34
|
|
|
31
35
|
const skill_install_dir = (base_skills_dir, name) => path.join(base_skills_dir, name)
|
|
@@ -60,6 +64,7 @@ module.exports = {
|
|
|
60
64
|
skills_dir,
|
|
61
65
|
tmp_dir,
|
|
62
66
|
install_lock_path,
|
|
67
|
+
lock_root,
|
|
63
68
|
lock_file_path,
|
|
64
69
|
skill_install_dir,
|
|
65
70
|
find_project_root
|
package/src/engine/installer.js
CHANGED
|
@@ -8,7 +8,7 @@ const { check_system_dependencies } = require('./system_deps')
|
|
|
8
8
|
const { hash_directory, verify_integrity } = require('../lock/integrity')
|
|
9
9
|
const { read_lock, get_locked_skill } = require('../lock/reader')
|
|
10
10
|
const { write_lock, update_lock_skills } = require('../lock/writer')
|
|
11
|
-
const { skills_dir, tmp_dir, skill_install_dir } = require('../config/paths')
|
|
11
|
+
const { skills_dir, tmp_dir, skill_install_dir, lock_root } = require('../config/paths')
|
|
12
12
|
const { ensure_dir, remove_dir, file_exists } = require('../utils/fs')
|
|
13
13
|
const { create_spinner } = require('../ui/spinner')
|
|
14
14
|
const { print_success, print_warn } = require('../ui/output')
|
|
@@ -22,8 +22,9 @@ const install = (skill, options = {}) => catch_errors('Install failed', async ()
|
|
|
22
22
|
const { version, global: is_global = false, force = false, fresh = false, project_root } = options
|
|
23
23
|
const base_dir = skills_dir(is_global, project_root)
|
|
24
24
|
const temp_dir = tmp_dir(base_dir)
|
|
25
|
+
const lock_dir = lock_root(is_global, project_root)
|
|
25
26
|
|
|
26
|
-
const [, lock_data] = fresh ? [null, null] : await read_lock(
|
|
27
|
+
const [, lock_data] = fresh ? [null, null] : await read_lock(lock_dir)
|
|
27
28
|
|
|
28
29
|
if (!fresh && lock_data) {
|
|
29
30
|
const locked = get_locked_skill(lock_data, skill)
|
|
@@ -148,7 +149,7 @@ const install = (skill, options = {}) => catch_errors('Install failed', async ()
|
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
const new_skills = update_lock_skills(lock_data, updates)
|
|
151
|
-
const [lock_errors] = await write_lock(
|
|
152
|
+
const [lock_errors] = await write_lock(lock_dir, new_skills)
|
|
152
153
|
if (lock_errors) { spinner.fail('Failed to write lock file'); throw e('Lock write failed', lock_errors) }
|
|
153
154
|
|
|
154
155
|
spinner.succeed(`Installed ${packages_to_install.length} package(s)`)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { error: { catch_errors, wrap_errors: e } } = require('puffy-core')
|
|
2
2
|
const { read_lock, get_locked_skill, get_all_locked_skills } = require('../lock/reader')
|
|
3
3
|
const { write_lock, update_lock_skills } = require('../lock/writer')
|
|
4
|
-
const { skills_dir, skill_install_dir } = require('../config/paths')
|
|
4
|
+
const { skills_dir, skill_install_dir, lock_root } = require('../config/paths')
|
|
5
5
|
const { remove_dir } = require('../utils/fs')
|
|
6
6
|
const { print_success, print_info } = require('../ui/output')
|
|
7
7
|
|
|
@@ -24,8 +24,9 @@ const find_orphans = (skills, removed_skill) => {
|
|
|
24
24
|
const uninstall = (skill, options = {}) => catch_errors('Uninstall failed', async () => {
|
|
25
25
|
const { global: is_global = false, project_root } = options
|
|
26
26
|
const base_dir = skills_dir(is_global, project_root)
|
|
27
|
+
const lock_dir = lock_root(is_global, project_root)
|
|
27
28
|
|
|
28
|
-
const [lock_errors, lock_data] = await read_lock(
|
|
29
|
+
const [lock_errors, lock_data] = await read_lock(lock_dir)
|
|
29
30
|
if (lock_errors || !lock_data) {
|
|
30
31
|
throw new Error('No skills-lock.json found. Nothing to uninstall.')
|
|
31
32
|
}
|
|
@@ -58,7 +59,7 @@ const uninstall = (skill, options = {}) => catch_errors('Uninstall failed', asyn
|
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
const new_skills = update_lock_skills(lock_data, updates)
|
|
61
|
-
const [write_errors] = await write_lock(
|
|
62
|
+
const [write_errors] = await write_lock(lock_dir, new_skills)
|
|
62
63
|
if (write_errors) throw e('Failed to update lock file', write_errors)
|
|
63
64
|
|
|
64
65
|
print_success(`Removed ${skill}`)
|