hyper-animator-codex 0.7.0 → 0.7.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/README.md CHANGED
@@ -22,19 +22,31 @@ Or install the CLI globally:
22
22
 
23
23
  ```bash
24
24
  npm install -g hyper-animator-codex
25
- hyper-animator-codex install --force
26
25
  ```
27
26
 
28
- By default the installer copies the skill to:
27
+ Global install runs a postinstall step that copies the skill to both Codex and Claude Code:
29
28
 
30
29
  ```text
31
30
  ${CODEX_HOME:-$HOME/.codex}/skills/hyper-animator-codex
31
+ ${CLAUDE_HOME:-$HOME/.claude}/skills/hyper-animator-codex
32
+ ```
33
+
34
+ To skip automatic skill installation during npm install:
35
+
36
+ ```bash
37
+ HYPER_ANIMATOR_CODEX_SKIP_POSTINSTALL=1 npm install -g hyper-animator-codex
38
+ ```
39
+
40
+ You can also run or re-run installation manually:
41
+
42
+ ```bash
43
+ hyper-animator-codex install --force
32
44
  ```
33
45
 
34
- Use a custom Codex skills directory:
46
+ Use one custom skills directory:
35
47
 
36
48
  ```bash
37
- npx hyper-animator-codex install --target /path/to/codex/skills
49
+ npx hyper-animator-codex install --target /path/to/skills
38
50
  ```
39
51
 
40
52
  ## Git Checkpoints
@@ -1,21 +1,29 @@
1
1
  #!/usr/bin/env node
2
- import { installSkill, resolveCodexSkillsRoot, SKILL_NAME } from "../lib/install-skill.mjs";
2
+ import {
3
+ installSkillToTargets,
4
+ resolveClaudeCodeSkillsRoot,
5
+ resolveCodexSkillsRoot,
6
+ SKILL_NAME,
7
+ } from "../lib/install-skill.mjs";
3
8
  import { parseInstallArgs } from "../lib/install-options.mjs";
4
9
 
5
10
  function printHelp() {
6
11
  console.log(`Usage:
7
12
  hyper-animator-codex install [--force] [--target <skills-dir>] [MiniMax options]
8
13
  hyper-animator-codex path
14
+ hyper-animator-codex paths
9
15
  hyper-animator-codex help
10
16
 
11
17
  Commands:
12
- install Install the packaged ${SKILL_NAME} skill into Codex
18
+ install Install the packaged ${SKILL_NAME} skill into Codex and Claude Code
13
19
  path Print the default Codex skills directory
20
+ paths Print default Codex and Claude Code skills directories
14
21
  help Show this help
15
22
 
16
23
  Options:
17
24
  --force Replace an existing installed skill
18
- --target <dir> Install into a specific Codex skills directory
25
+ --quiet Suppress successful install output
26
+ --target <dir> Install into one specific skills directory
19
27
  --minimax-api-key <key> Save MiniMax API key into installed skill config
20
28
  --minimax-group-id <group_id> Save MiniMax group_id into installed skill config
21
29
  --minimax-model <model> MiniMax text music model: music-2.6 or music-2.6-free
@@ -39,20 +47,34 @@ async function main() {
39
47
  return;
40
48
  }
41
49
 
50
+ if (command === "paths") {
51
+ console.log(`Codex: ${resolveCodexSkillsRoot()}`);
52
+ console.log(`Claude Code: ${resolveClaudeCodeSkillsRoot()}`);
53
+ return;
54
+ }
55
+
42
56
  if (command !== "install") {
43
57
  throw new Error(`Unknown command: ${command}`);
44
58
  }
45
59
 
46
60
  const options = parseInstallArgs(args);
47
- const result = await installSkill(options);
61
+ const result = await installSkillToTargets(options);
62
+
63
+ if (options.quiet) {
64
+ return;
65
+ }
48
66
 
49
67
  console.log(`Installed ${result.skillName}`);
50
68
  console.log(`Source: ${result.sourcePath}`);
51
- console.log(`Target: ${result.installedPath}`);
52
69
 
53
- if (result.minimaxConfigPath) {
54
- console.log(`MiniMax config: ${result.minimaxConfigPath}`);
55
- console.log(`MiniMax model: ${result.minimaxConfig.model}`);
70
+ for (const install of result.installs) {
71
+ console.log(`${install.tool}: ${install.installedPath}`);
72
+ if (install.minimaxConfigPath) {
73
+ console.log(`${install.tool} MiniMax config: ${install.minimaxConfigPath}`);
74
+ if (install.minimaxConfig) {
75
+ console.log(`${install.tool} MiniMax model: ${install.minimaxConfig.model}`);
76
+ }
77
+ }
56
78
  }
57
79
  }
58
80
 
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import { installSkillToTargets } from "../lib/install-skill.mjs";
3
+
4
+ if (process.env.HYPER_ANIMATOR_CODEX_SKIP_POSTINSTALL === "1") {
5
+ process.exit(0);
6
+ }
7
+
8
+ try {
9
+ const result = await installSkillToTargets({
10
+ force: true,
11
+ quiet: true,
12
+ env: process.env,
13
+ });
14
+
15
+ const targets = result.installs.map((install) => `${install.tool}:${install.installedPath}`).join(", ");
16
+ console.log(`hyper-animator-codex installed skills: ${targets}`);
17
+ } catch (error) {
18
+ console.warn(`hyper-animator-codex postinstall skipped: ${error.message}`);
19
+ }
@@ -11,6 +11,7 @@ function requireValue(args, index, flag) {
11
11
  export function parseInstallArgs(args) {
12
12
  const parsed = {
13
13
  force: false,
14
+ quiet: false,
14
15
  targetRoot: undefined,
15
16
  minimaxConfig: {},
16
17
  };
@@ -20,6 +21,8 @@ export function parseInstallArgs(args) {
20
21
 
21
22
  if (arg === "--force") {
22
23
  parsed.force = true;
24
+ } else if (arg === "--quiet") {
25
+ parsed.quiet = true;
23
26
  } else if (arg === "--target") {
24
27
  parsed.targetRoot = requireValue(args, index, arg);
25
28
  index += 1;
@@ -1,9 +1,10 @@
1
- import { cp, mkdir, rm, stat } from "node:fs/promises";
1
+ import { chmod, cp, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { basename, dirname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
 
6
6
  import {
7
+ MINIMAX_CONFIG_RELATIVE_PATH,
7
8
  redactMinimaxConfig,
8
9
  resolveInstallMinimaxConfig,
9
10
  writeMinimaxConfig,
@@ -43,6 +44,44 @@ export function resolveCodexSkillsRoot(env = process.env) {
43
44
  return join(home, ".codex", "skills");
44
45
  }
45
46
 
47
+ export function resolveClaudeCodeSkillsRoot(env = process.env) {
48
+ if (env.CLAUDE_HOME) {
49
+ return join(env.CLAUDE_HOME, "skills");
50
+ }
51
+
52
+ const home = env.HOME || homedir();
53
+ if (!home) {
54
+ throw new Error("Cannot resolve Claude Code skills directory: HOME is not set");
55
+ }
56
+
57
+ return join(home, ".claude", "skills");
58
+ }
59
+
60
+ async function readExistingMinimaxConfig(installedPath) {
61
+ const configPath = join(installedPath, MINIMAX_CONFIG_RELATIVE_PATH);
62
+
63
+ if (!(await pathExists(configPath))) {
64
+ return null;
65
+ }
66
+
67
+ return {
68
+ configPath,
69
+ body: await readFile(configPath, "utf8"),
70
+ };
71
+ }
72
+
73
+ async function restoreExistingMinimaxConfig(installedPath, existingConfig) {
74
+ if (!existingConfig) {
75
+ return null;
76
+ }
77
+
78
+ const configPath = join(installedPath, MINIMAX_CONFIG_RELATIVE_PATH);
79
+ await mkdir(dirname(configPath), { recursive: true });
80
+ await writeFile(configPath, existingConfig.body, { encoding: "utf8", mode: 0o600 });
81
+ await chmod(configPath, 0o600);
82
+ return configPath;
83
+ }
84
+
46
85
  export async function installSkill(options = {}) {
47
86
  const targetRoot = options.targetRoot || resolveCodexSkillsRoot(options.env);
48
87
  const sourcePath = options.sourcePath || join(packageRoot, "skills", SKILL_NAME);
@@ -55,6 +94,8 @@ export async function installSkill(options = {}) {
55
94
 
56
95
  await mkdir(targetRoot, { recursive: true });
57
96
 
97
+ const existingMinimaxConfig = force ? await readExistingMinimaxConfig(installedPath) : null;
98
+
58
99
  if (await pathExists(installedPath)) {
59
100
  if (!force) {
60
101
  throw new Error(`${SKILL_NAME} already exists at ${installedPath}; rerun with --force to replace it`);
@@ -74,12 +115,53 @@ export async function installSkill(options = {}) {
74
115
  const minimaxWrite = resolvedMinimaxConfig
75
116
  ? await writeMinimaxConfig(installedPath, resolvedMinimaxConfig)
76
117
  : null;
118
+ const restoredMinimaxConfigPath = minimaxWrite ? null : await restoreExistingMinimaxConfig(installedPath, existingMinimaxConfig);
77
119
 
78
120
  return {
79
121
  skillName: SKILL_NAME,
122
+ tool: options.tool || "codex",
80
123
  sourcePath,
81
124
  installedPath,
82
- minimaxConfigPath: minimaxWrite ? minimaxWrite.configPath : null,
125
+ minimaxConfigPath: minimaxWrite ? minimaxWrite.configPath : restoredMinimaxConfigPath,
83
126
  minimaxConfig: minimaxWrite ? redactMinimaxConfig(minimaxWrite.config) : null,
84
127
  };
85
128
  }
129
+
130
+ export async function installSkillToTargets(options = {}) {
131
+ const sourcePath = options.sourcePath || join(packageRoot, "skills", SKILL_NAME);
132
+
133
+ if (options.targetRoot) {
134
+ const install = await installSkill({
135
+ ...options,
136
+ sourcePath,
137
+ tool: "custom",
138
+ });
139
+ return {
140
+ skillName: SKILL_NAME,
141
+ sourcePath,
142
+ installs: [install],
143
+ };
144
+ }
145
+
146
+ const env = options.env || process.env;
147
+ const installs = [];
148
+
149
+ for (const target of [
150
+ { tool: "codex", targetRoot: resolveCodexSkillsRoot(env) },
151
+ { tool: "claude-code", targetRoot: resolveClaudeCodeSkillsRoot(env) },
152
+ ]) {
153
+ installs.push(await installSkill({
154
+ ...options,
155
+ env,
156
+ sourcePath,
157
+ targetRoot: target.targetRoot,
158
+ tool: target.tool,
159
+ }));
160
+ }
161
+
162
+ return {
163
+ skillName: SKILL_NAME,
164
+ sourcePath,
165
+ installs,
166
+ };
167
+ }
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "hyper-animator-codex",
3
- "version": "0.7.0",
4
- "description": "Install the Hyper Animator Codex skill for Codex.",
3
+ "version": "0.7.1",
4
+ "description": "Install the Hyper Animator skill for Codex and Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "hyper-animator-codex": "bin/hyper-animator-codex.mjs"
8
8
  },
9
9
  "scripts": {
10
+ "postinstall": "node bin/postinstall.mjs",
10
11
  "test": "node --test",
11
12
  "pack:check": "npm pack --dry-run"
12
13
  },