happyskills 0.7.1 → 0.7.3

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,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.3] - 2026-03-08
11
+
12
+ ### Fixed
13
+ - Fix `update` command wiping all other skills from `skills-lock.json` — the `fresh` flag was skipping the lock file read entirely, causing the merge-on-write to start from an empty map instead of preserving existing entries
14
+ - Fix `publish` dependency check producing false "not found" warnings by replacing the bulk `resolve_dependencies` call with individual repo lookups
15
+
16
+ ## [0.7.2] - 2026-03-06
17
+
18
+ ### Fixed
19
+ - Fix `setup` command pointing to the old `happyskillsai/happyskills-cli` skill name; it now installs `happyskillsai/happyskills`
20
+
10
21
  ## [0.7.1] - 2026-03-06
11
22
 
12
23
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happyskills",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Package manager for AI agent skills",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Nicolas Dao <nic@cloudlesslabs.com> (https://cloudlesslabs.com)",
@@ -9,6 +9,10 @@ const { smart_push } = require('../api/push')
9
9
  const { inc } = require('../utils/semver')
10
10
  const { collect_files } = require('../utils/file_collector')
11
11
  const { resolve_skill_dir, resolve_skill_owner } = require('../utils/resolve_skill')
12
+ const { find_project_root } = require('../config/paths')
13
+ const { read_lock, get_all_locked_skills } = require('../lock/reader')
14
+ const { write_lock, update_lock_skills } = require('../lock/writer')
15
+ const { hash_directory } = require('../lock/integrity')
12
16
  const { create_spinner } = require('../ui/spinner')
13
17
  const { print_help, print_success, print_error, print_warn, print_hint, print_json, code } = require('../ui/output')
14
18
  const { exit_with_error, UsageError, CliError } = require('../utils/errors')
@@ -102,14 +106,20 @@ const run = (args) => catch_errors('Publish failed', async () => {
102
106
 
103
107
  if (manifest.dependencies && Object.keys(manifest.dependencies).length > 0) {
104
108
  spinner.update('Checking dependencies...')
105
- const [dep_err] = await repos_api.resolve_dependencies(
106
- `${workspace.slug}/${manifest.name}`,
107
- manifest.version,
108
- {}
109
- )
110
- if (dep_err) {
109
+ const dep_entries = Object.keys(manifest.dependencies)
110
+ const dep_results = await Promise.all(dep_entries.map(async (dep) => {
111
+ const parts = dep.split('/')
112
+ if (parts.length !== 2) return { dep, missing: true }
113
+ const [dep_owner, dep_name] = parts
114
+ const [err] = await repos_api.get_repo(dep_owner, dep_name)
115
+ return { dep, missing: !!err }
116
+ }))
117
+ const missing = dep_results.filter(r => r.missing)
118
+ if (missing.length > 0) {
111
119
  spinner.fail('Dependency check failed')
112
- print_warn('Some dependencies may not be published yet.')
120
+ for (const { dep } of missing) {
121
+ print_warn(`Dependency "${dep}" not found in the registry.`)
122
+ }
113
123
  }
114
124
  }
115
125
 
@@ -122,7 +132,7 @@ const run = (args) => catch_errors('Publish failed', async () => {
122
132
  spinner.update(`Uploading files (${completed}/${total})...`)
123
133
  }
124
134
  const visibility = args.flags.public ? 'public' : 'private'
125
- const [push_err] = await smart_push(workspace.slug, manifest.name, {
135
+ const [push_err, push_data] = await smart_push(workspace.slug, manifest.name, {
126
136
  version: manifest.version,
127
137
  message: `Release ${manifest.version}`,
128
138
  files: skill_files,
@@ -132,11 +142,33 @@ const run = (args) => catch_errors('Publish failed', async () => {
132
142
 
133
143
  spinner.succeed(`Published ${workspace.slug}/${manifest.name}@${manifest.version}`)
134
144
 
145
+ const full_name = `${workspace.slug}/${manifest.name}`
146
+ const project_root = find_project_root()
147
+ const [lock_err, lock_data] = await read_lock(project_root)
148
+ if (!lock_err && lock_data) {
149
+ const all_skills = get_all_locked_skills(lock_data)
150
+ const suffix = `/${skill_name}`
151
+ const lock_key = Object.keys(all_skills).find(k => k.endsWith(suffix))
152
+ if (lock_key && all_skills[lock_key]) {
153
+ const [hash_err, integrity] = await hash_directory(dir)
154
+ const updated_entry = {
155
+ ...all_skills[lock_key],
156
+ version: manifest.version,
157
+ ref: push_data?.ref || `refs/tags/v${manifest.version}`,
158
+ commit: push_data?.commit || null
159
+ }
160
+ if (!hash_err && integrity) updated_entry.integrity = integrity
161
+ const updated_skills = update_lock_skills(lock_data, { [lock_key]: updated_entry })
162
+ await write_lock(project_root, updated_skills)
163
+ }
164
+ }
165
+
135
166
  if (args.flags.json) {
136
167
  print_json({ data: {
137
- skill: `${workspace.slug}/${manifest.name}`,
168
+ skill: full_name,
138
169
  version: manifest.version,
139
- ref: `refs/tags/v${manifest.version}`,
170
+ ref: push_data?.ref || `refs/tags/v${manifest.version}`,
171
+ commit: push_data?.commit || null,
140
172
  bumped_from
141
173
  } })
142
174
  return
@@ -5,13 +5,13 @@ const { print_success, print_info, print_help, print_hint, print_json, code } =
5
5
  const { exit_with_error } = require('../utils/errors')
6
6
  const { EXIT_CODES } = require('../constants')
7
7
 
8
- const SKILL_NAME = 'happyskillsai/happyskills-cli'
8
+ const SKILL_NAME = 'happyskillsai/happyskills'
9
9
 
10
10
  const HELP_TEXT = `Usage: happyskills setup [options]
11
11
 
12
12
  Install (or update) the official HappySkills CLI skill.
13
13
 
14
- Installs happyskillsai/happyskills-cli into .claude/skills/ so AI agents
14
+ Installs happyskillsai/happyskills into .claude/skills/ so AI agents
15
15
  (Claude Code, etc.) can interact with HappySkills using natural language.
16
16
 
17
17
  Options:
@@ -24,7 +24,7 @@ const install = (skill, options = {}) => catch_errors('Install failed', async ()
24
24
  const temp_dir = tmp_dir(base_dir)
25
25
  const lock_dir = lock_root(is_global, project_root)
26
26
 
27
- const [, lock_data] = fresh ? [null, null] : await read_lock(lock_dir)
27
+ const [, lock_data] = await read_lock(lock_dir)
28
28
 
29
29
  if (!fresh && lock_data) {
30
30
  const locked = get_locked_skill(lock_data, skill)
@@ -418,7 +418,7 @@ describe('CLI — setup command', () => {
418
418
  it('setup --help exits 0 and describes the command', () => {
419
419
  const { stdout, code } = run(['setup', '--help'])
420
420
  assert.strictEqual(code, 0)
421
- assert.match(stdout, /happyskillsai\/happyskills-cli/)
421
+ assert.match(stdout, /happyskillsai\/happyskills/)
422
422
  assert.match(stdout, /Options:/)
423
423
  assert.match(stdout, /Examples:/)
424
424
  })