image-skill 0.1.6 → 0.1.7

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
@@ -11,7 +11,14 @@ Install the agent skill from the public mirror repo:
11
11
  npx skills add danielgwilson/image-skill-cli --skill image-skill -g -a codex -y
12
12
  ```
13
13
 
14
- Install the executable CLI from npm:
14
+ Run the executable CLI from npm without requiring a writable global npm prefix:
15
+
16
+ ```bash
17
+ npm exec --yes --package image-skill@latest -- image-skill doctor --json
18
+ ```
19
+
20
+ For repeated shell use, global install is optional only after confirming the
21
+ runtime has a writable npm prefix:
15
22
 
16
23
  ```bash
17
24
  npm install -g image-skill
@@ -37,3 +44,13 @@ The CLI saves hosted agent tokens only when `--save` is explicit. Saved tokens
37
44
  live at `${XDG_CONFIG_HOME:-~/.config}/image-skill/config.json` by default with
38
45
  0600 permissions. Use `IMAGE_SKILL_CONFIG_PATH` to override the config path and
39
46
  `IMAGE_SKILL_TOKEN` or `--token-stdin` for runtime secret injection.
47
+
48
+ Fresh sandboxes should prefer:
49
+
50
+ ```bash
51
+ export IMAGE_SKILL_CONFIG_PATH="$PWD/.image-skill/config.json"
52
+ npm exec --yes --package image-skill@latest -- image-skill signup --agent --agent-contact CONTACT_OR_SPONSOR_INBOX --agent-name creative-agent --runtime openclaw --save --json
53
+ ```
54
+
55
+ If npm prefix/cache paths are read-only, set `npm_config_cache` and
56
+ `npm_config_prefix` to writable directories before using `npm exec`.
@@ -7,7 +7,7 @@ import { Readable } from "node:stream";
7
7
  import { pipeline } from "node:stream/promises";
8
8
  import os from "node:os";
9
9
 
10
- const VERSION = "0.1.6";
10
+ const VERSION = "0.1.7";
11
11
  const DEFAULT_API_BASE_URL = "https://api.image-skill.com";
12
12
  const DEFAULT_CONFIG_PATH = join(
13
13
  process.env.XDG_CONFIG_HOME ?? join(os.homedir(), ".config"),
@@ -79,37 +79,37 @@ async function main(rawArgv) {
79
79
  try {
80
80
  switch (command) {
81
81
  case "doctor":
82
- return doctor(rest);
82
+ return await doctor(rest);
83
83
  case "signup":
84
- return signup(rest);
84
+ return await signup(rest);
85
85
  case "auth":
86
- return auth(rest);
86
+ return await auth(rest);
87
87
  case "whoami":
88
- return whoami(rest);
88
+ return await whoami(rest);
89
89
  case "usage":
90
- return usage(rest);
90
+ return await usage(rest);
91
91
  case "quota":
92
- return quota(rest);
92
+ return await quota(rest);
93
93
  case "credits":
94
- return credits(rest);
94
+ return await credits(rest);
95
95
  case "models":
96
- return models(rest);
96
+ return await models(rest);
97
97
  case "capabilities":
98
- return capabilities(rest);
98
+ return await capabilities(rest);
99
99
  case "create":
100
- return create(rest);
100
+ return await create(rest);
101
101
  case "upload":
102
- return upload(rest);
102
+ return await upload(rest);
103
103
  case "edit":
104
- return edit(rest);
104
+ return await edit(rest);
105
105
  case "assets":
106
- return assets(rest);
106
+ return await assets(rest);
107
107
  case "jobs":
108
- return jobs(rest);
108
+ return await jobs(rest);
109
109
  case "activity":
110
- return activity(rest);
110
+ return await activity(rest);
111
111
  case "feedback":
112
- return feedback(rest);
112
+ return await feedback(rest);
113
113
  default:
114
114
  return failure(
115
115
  `image-skill ${command}`,
@@ -209,6 +209,12 @@ async function signup(argv) {
209
209
  }
210
210
  const save = flagBool(args, "save");
211
211
  const showToken = flagBool(args, "show-token");
212
+ if (save) {
213
+ const configReady = await assertConfigWritable("image-skill signup");
214
+ if (!configReady.ok) {
215
+ return configReady.result;
216
+ }
217
+ }
212
218
  const result = await apiRequest({
213
219
  command: "image-skill signup",
214
220
  method: "POST",
@@ -238,12 +244,16 @@ async function signup(argv) {
238
244
  },
239
245
  );
240
246
  }
241
- await saveConfig({
242
- api_base_url: apiBase(args),
243
- token,
244
- saved_at: new Date().toISOString(),
245
- actor: result.envelope.actor ?? result.envelope.data?.actor ?? null,
246
- });
247
+ try {
248
+ await saveConfig({
249
+ api_base_url: apiBase(args),
250
+ token,
251
+ saved_at: new Date().toISOString(),
252
+ actor: result.envelope.actor ?? result.envelope.data?.actor ?? null,
253
+ });
254
+ } catch (error) {
255
+ return configWriteFailure("image-skill signup", error);
256
+ }
247
257
  warnings.push(`saved hosted token to ${configPath()}`);
248
258
  }
249
259
 
@@ -302,12 +312,20 @@ async function auth(argv) {
302
312
  if (!token.ok) {
303
313
  return token.result;
304
314
  }
305
- await saveConfig({
306
- api_base_url: apiBase(args),
307
- token: token.token,
308
- saved_at: new Date().toISOString(),
309
- actor: null,
310
- });
315
+ const configReady = await assertConfigWritable("image-skill auth save");
316
+ if (!configReady.ok) {
317
+ return configReady.result;
318
+ }
319
+ try {
320
+ await saveConfig({
321
+ api_base_url: apiBase(args),
322
+ token: token.token,
323
+ saved_at: new Date().toISOString(),
324
+ actor: null,
325
+ });
326
+ } catch (error) {
327
+ return configWriteFailure("image-skill auth save", error);
328
+ }
311
329
  return success("image-skill auth save", {
312
330
  saved: true,
313
331
  config_path: configPath(),
@@ -1256,6 +1274,43 @@ async function saveConfig(value) {
1256
1274
  await chmod(path, 0o600);
1257
1275
  }
1258
1276
 
1277
+ async function assertConfigWritable(command) {
1278
+ const path = configPath();
1279
+ const probePath = `${path}.write-test-${process.pid}-${randomBytes(4).toString("hex")}`;
1280
+ try {
1281
+ await mkdir(dirname(path), { recursive: true });
1282
+ await writeFile(probePath, "", { mode: 0o600 });
1283
+ await chmod(probePath, 0o600);
1284
+ await rm(probePath, { force: true });
1285
+ return { ok: true };
1286
+ } catch (error) {
1287
+ await rm(probePath, { force: true }).catch(() => {});
1288
+ return {
1289
+ ok: false,
1290
+ result: configWriteFailure(command, error),
1291
+ };
1292
+ }
1293
+ }
1294
+
1295
+ function configWriteFailure(command, error) {
1296
+ const message =
1297
+ error instanceof Error
1298
+ ? error.message
1299
+ : "public CLI could not write its local auth config";
1300
+ return failure(
1301
+ command,
1302
+ 9,
1303
+ "PUBLIC_CLI_CONFIG_WRITE_FAILED",
1304
+ `public CLI could not write auth config at ${configPath()}: ${message}`,
1305
+ true,
1306
+ {
1307
+ suggested_command:
1308
+ 'IMAGE_SKILL_CONFIG_PATH="$PWD/.image-skill/config.json" image-skill signup --agent --agent-contact CONTACT_OR_SPONSOR_INBOX --agent-name NAME --runtime RUNTIME --save --json',
1309
+ docs_url: "https://image-skill.com/cli.md#local-config-and-install",
1310
+ },
1311
+ );
1312
+ }
1313
+
1259
1314
  function parseArgs(argv) {
1260
1315
  const flags = new Map();
1261
1316
  const positionals = [];
package/cli.md CHANGED
@@ -92,6 +92,44 @@ printf '%s\n' "$IMAGE_SKILL_TOKEN" | image-skill usage quota --token-stdin --jso
92
92
  `--api-base-url` is an advanced preview/test override; production public agents
93
93
  should omit it.
94
94
 
95
+ ### Local Config And Install
96
+
97
+ Prefer package execution in fresh agent sandboxes:
98
+
99
+ ```bash
100
+ npm exec --yes --package image-skill@latest -- image-skill doctor --json
101
+ ```
102
+
103
+ Global install is optional, not the primary path. If `npm install -g image-skill`
104
+ or `npx image-skill@latest ...` hits prefix/cache `EACCES`, retry with writable
105
+ package-manager paths instead of cloning private source:
106
+
107
+ ```bash
108
+ export npm_config_cache="${npm_config_cache:-$PWD/.npm-cache}"
109
+ export npm_config_prefix="${npm_config_prefix:-$PWD/.npm-global}"
110
+ export PATH="$npm_config_prefix/bin:$PATH"
111
+ npm exec --yes --package image-skill@latest -- image-skill doctor --json
112
+ ```
113
+
114
+ Saved auth state defaults to
115
+ `${XDG_CONFIG_HOME:-~/.config}/image-skill/config.json`. If that location is
116
+ read-only, set a writable config path before `signup --save`:
117
+
118
+ ```bash
119
+ export IMAGE_SKILL_CONFIG_PATH="$PWD/.image-skill/config.json"
120
+ npm exec --yes --package image-skill@latest -- image-skill signup --agent \
121
+ --agent-contact agent-ops@example.com \
122
+ --agent-name creative-agent \
123
+ --runtime codex \
124
+ --save \
125
+ --json
126
+ ```
127
+
128
+ Config write failures return `PUBLIC_CLI_CONFIG_WRITE_FAILED` with a structured
129
+ `error.recovery.suggested_command`. Agents should follow that recovery field,
130
+ then continue with `whoami`, `usage quota`, `models list`, and the requested
131
+ creative flow.
132
+
95
133
  ### `image-skill whoami`
96
134
 
97
135
  Shows current actor, organization, claim state, token class, and grants.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "image-skill",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Thin hosted CLI for Image Skill, a creative runtime for agents.",
5
5
  "type": "module",
6
6
  "private": false,
package/skill.md CHANGED
@@ -35,12 +35,18 @@ supports skills.sh-compatible installation:
35
35
  npx skills add danielgwilson/image-skill-cli --skill image-skill -g -a codex -y
36
36
  ```
37
37
 
38
- Install the executable CLI from npm:
38
+ Run the executable CLI from npm without relying on a writable global npm
39
+ prefix:
39
40
 
40
41
  ```bash
41
- npm install -g image-skill
42
+ npm exec --yes --package image-skill@latest -- image-skill doctor --json
42
43
  ```
43
44
 
45
+ For repeated shell use, use global package linking only after confirming the
46
+ runtime has a writable npm prefix. In fresh sandboxes, prefer `npm exec`/`npx` and set
47
+ `IMAGE_SKILL_CONFIG_PATH` to a writable persistent path if the default config
48
+ home is read-only.
49
+
44
50
  Check service and client health:
45
51
 
46
52
  ```bash
@@ -75,6 +81,27 @@ If the runtime supports stdin secret handoff, prefer `--token-stdin` for
75
81
  `whoami`, `usage quota`, `quota`, `create`, and `feedback create` instead of
76
82
  placing the token in command args.
77
83
 
84
+ ## Local Config And Install
85
+
86
+ The CLI stores saved hosted tokens only when `--save` is explicit. By default
87
+ that file lives at `${XDG_CONFIG_HOME:-~/.config}/image-skill/config.json` with
88
+ 0600 permissions. If a sandbox or hosted executor has a read-only home or npm
89
+ prefix, keep using the public package through `npm exec` and point auth state at
90
+ a writable path:
91
+
92
+ ```bash
93
+ export IMAGE_SKILL_CONFIG_PATH="$PWD/.image-skill/config.json"
94
+ npm exec --yes --package image-skill@latest -- image-skill signup --agent \
95
+ --agent-contact CONTACT_OR_SPONSOR_INBOX \
96
+ --agent-name AGENT_NAME \
97
+ --runtime RUNTIME_NAME \
98
+ --save \
99
+ --json
100
+ ```
101
+
102
+ Do not clone private source or fall back to direct provider APIs because global
103
+ package linking or the default config directory is blocked.
104
+
78
105
  Inspect identity and quota:
79
106
 
80
107
  ```bash