unoverse 0.1.152 → 0.1.154
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/bin/unoverse.mjs +10 -6
- package/lib/skills.mjs +32 -15
- package/operator/operator.sh +11 -0
- package/package.json +1 -1
package/bin/unoverse.mjs
CHANGED
|
@@ -126,15 +126,19 @@ switch (cmd) {
|
|
|
126
126
|
|
|
127
127
|
case "_postupdate": {
|
|
128
128
|
// Runs AS the new version, in the developer's cwd. A universe refreshes its
|
|
129
|
-
// platform images;
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
129
|
+
// platform images; the authoring skills install to ~/.claude/skills from the public
|
|
130
|
+
// mirror, so `unoverse update` is the one command that brings everything current.
|
|
131
|
+
//
|
|
132
|
+
// THE SKILLS ARE NOT CWD-SCOPED. This used to refresh `<cwd>/.claude/skills` and only
|
|
133
|
+
// when that folder already existed, which meant it fired on whichever folder update
|
|
134
|
+
// happened to be run in — a universe, almost never a design workspace — and never
|
|
135
|
+
// installed anything at all. They are per developer, so they go to the home directory
|
|
136
|
+
// and this runs unconditionally.
|
|
133
137
|
if (UNIVERSE) {
|
|
134
138
|
operator(UNIVERSE, ["refresh-images"]);
|
|
135
139
|
}
|
|
136
|
-
const {
|
|
137
|
-
|
|
140
|
+
const { installSkills } = await import("../lib/skills.mjs");
|
|
141
|
+
installSkills();
|
|
138
142
|
process.exit(0);
|
|
139
143
|
}
|
|
140
144
|
|
package/lib/skills.mjs
CHANGED
|
@@ -1,40 +1,57 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Install the Claude Code authoring skills for this developer.
|
|
2
2
|
//
|
|
3
3
|
// The public mirror github.com/unoverse-platform/skills is the one place installed
|
|
4
|
-
// skills come from (publish syncs it from the platform repo's .claude/skills).
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
|
|
4
|
+
// skills come from (publish syncs it from the platform repo's .claude/skills).
|
|
5
|
+
//
|
|
6
|
+
// PER DEVELOPER, NOT PER PROJECT (2026-08-21). These install to ~/.claude/skills, so
|
|
7
|
+
// Claude Code picks them up in every folder the developer opens and nothing lands
|
|
8
|
+
// inside a workspace where it could be committed. They used to be copied into each
|
|
9
|
+
// Studio workspace's own .claude/skills by Studio's scaffold, out of a snapshot
|
|
10
|
+
// vendored in the Studio npm package: that reproduced the platform repo's .claude
|
|
11
|
+
// folder on every remote developer's disk, pinned to whichever Studio version they
|
|
12
|
+
// installed. Studio no longer writes them (packages/studio/local/scaffold.mjs) and
|
|
13
|
+
// the mirror is the only channel.
|
|
14
|
+
//
|
|
15
|
+
// INSTALLS, NOT JUST REFRESHES. This used to return early when the folder was absent,
|
|
16
|
+
// because seeding was Studio's job. Nothing seeds them now, so an absent folder is the
|
|
17
|
+
// FIRST install and creating it is the whole point.
|
|
18
|
+
//
|
|
19
|
+
// Runs on `unoverse update` (_postupdate), which is the one command that brings a
|
|
20
|
+
// developer's tooling current.
|
|
21
|
+
import { mkdtempSync, existsSync, mkdirSync, readdirSync, rmSync, cpSync } from "node:fs";
|
|
10
22
|
import { join } from "node:path";
|
|
11
|
-
import { tmpdir } from "node:os";
|
|
23
|
+
import { tmpdir, homedir } from "node:os";
|
|
12
24
|
import { spawnSync } from "node:child_process";
|
|
13
25
|
|
|
14
26
|
const TARBALL = "https://codeload.github.com/unoverse-platform/skills/tar.gz/refs/heads/main";
|
|
15
27
|
|
|
16
|
-
export function
|
|
17
|
-
const target = join(
|
|
18
|
-
if (!existsSync(target)) return;
|
|
28
|
+
export function installSkills() {
|
|
29
|
+
const target = join(homedir(), ".claude", "skills");
|
|
19
30
|
const tmp = mkdtempSync(join(tmpdir(), "unoverse-skills-"));
|
|
20
31
|
try {
|
|
21
32
|
const dl = spawnSync("bash", ["-c", `curl -fsSL "${TARBALL}" | tar -xz -C "${tmp}" --strip-components=1`], {
|
|
22
33
|
stdio: "pipe",
|
|
23
34
|
});
|
|
24
35
|
if (dl.status !== 0) {
|
|
25
|
-
console.log(" Skills
|
|
36
|
+
console.log(" Skills install skipped (github.com unreachable). They install on the next update.");
|
|
26
37
|
return;
|
|
27
38
|
}
|
|
28
|
-
//
|
|
29
|
-
//
|
|
39
|
+
// A skill is a directory holding a SKILL.md. The mirror's README and dotfiles never
|
|
40
|
+
// install.
|
|
30
41
|
const names = readdirSync(tmp, { withFileTypes: true })
|
|
31
42
|
.filter((e) => e.isDirectory() && existsSync(join(tmp, e.name, "SKILL.md")))
|
|
32
43
|
.map((e) => e.name);
|
|
44
|
+
if (!names.length) return;
|
|
45
|
+
mkdirSync(target, { recursive: true });
|
|
46
|
+
// REPLACED WHOLE, ours only. Each skill folder the mirror carries is removed and
|
|
47
|
+
// re-copied, so a deleted file upstream really goes. Anything else in the
|
|
48
|
+
// developer's ~/.claude/skills is THEIRS and is never touched: this folder is
|
|
49
|
+
// shared with every skill they have installed from anywhere else.
|
|
33
50
|
for (const name of names) {
|
|
34
51
|
rmSync(join(target, name), { recursive: true, force: true });
|
|
35
52
|
cpSync(join(tmp, name), join(target, name), { recursive: true });
|
|
36
53
|
}
|
|
37
|
-
|
|
54
|
+
console.log(` ✓ authoring skills installed to ~/.claude/skills (${names.join(", ")})`);
|
|
38
55
|
} finally {
|
|
39
56
|
rmSync(tmp, { recursive: true, force: true });
|
|
40
57
|
}
|
package/operator/operator.sh
CHANGED
|
@@ -157,6 +157,17 @@ case "${1:-}" in
|
|
|
157
157
|
if [ -n "$(docker compose -f "$ROOT/docker-compose.yml" ps -q 2>/dev/null)" ]; then
|
|
158
158
|
docker compose -f "$ROOT/docker-compose.yml" --env-file "$ROOT/.env" up -d --remove-orphans >/dev/null 2>&1 \
|
|
159
159
|
&& ok "Running services moved to the new images"
|
|
160
|
+
# MIGRATIONS RUN ON UPDATE, same as deploy and start. An update is exactly when a
|
|
161
|
+
# new migration arrives (it ships inside the image just pulled), and this was the
|
|
162
|
+
# one path that skipped db-setup: a universe could run new code against a schema
|
|
163
|
+
# missing the columns that code expects, silently, until something read them.
|
|
164
|
+
# Additive-by-rule until Retire and idempotent, so re-running costs nothing.
|
|
165
|
+
# Subshell because cmd_db_setup exits rather than returns on failure.
|
|
166
|
+
if ! (cmd_db_setup) >/dev/null 2>&1; then
|
|
167
|
+
warn "Migrations did not apply. Run ${BOLD}unoverse check${NC} to see why"
|
|
168
|
+
else
|
|
169
|
+
ok "Database migrations are current"
|
|
170
|
+
fi
|
|
160
171
|
echo ""
|
|
161
172
|
echo -e " ${GREEN}unoverse where${NC} Links to your Canvas and API"
|
|
162
173
|
echo ""
|
package/package.json
CHANGED