@zalosai/zalos-cli 0.2.13 → 0.2.15
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/PUBLISHING.md +9 -4
- package/README.md +21 -1
- package/dist/commands/skills.js +90 -0
- package/dist/main.js +5 -1
- package/package.json +13 -11
- package/skills/zl-ops/SKILL.md +116 -0
package/PUBLISHING.md
CHANGED
|
@@ -8,8 +8,9 @@ Zalos product access.
|
|
|
8
8
|
|
|
9
9
|
- The release commit must be merged into `develop`.
|
|
10
10
|
- The package version must not already exist in npm.
|
|
11
|
-
-
|
|
12
|
-
|
|
11
|
+
- npm Trusted Publishing must authorize GitHub Actions from
|
|
12
|
+
`Zalos-io/mesh` through `publish-zalos-cli.yml`, with direct publishing
|
|
13
|
+
enabled.
|
|
13
14
|
|
|
14
15
|
## Release
|
|
15
16
|
|
|
@@ -38,8 +39,8 @@ Zalos product access.
|
|
|
38
39
|
pnpm --filter @zalosai/zalos-cli exec npm pack --dry-run
|
|
39
40
|
```
|
|
40
41
|
|
|
41
|
-
Only `package.json`, `README.md`, `PUBLISHING.md`,
|
|
42
|
-
should be included.
|
|
42
|
+
Only `package.json`, `README.md`, `PUBLISHING.md`, the bundled `skills/` Markdown, and runtime
|
|
43
|
+
JavaScript under `dist/` should be included.
|
|
43
44
|
|
|
44
45
|
4. In GitHub, open **Actions → Publish Zalos CLI → Run workflow**.
|
|
45
46
|
Select `develop` and enter the exact version from `package.json`. The workflow rejects
|
|
@@ -58,6 +59,10 @@ Do not publish with uncommitted package changes or reuse an existing version.
|
|
|
58
59
|
|
|
59
60
|
## Central developer access release
|
|
60
61
|
|
|
62
|
+
Version 0.2.15 bundles the `zl-ops` production-operations skill and adds offline `zl skills`
|
|
63
|
+
commands to list, read, and install it into Codex or Claude skill roots.
|
|
64
|
+
Version 0.2.14 moves publishing to npm Trusted Publishing through the
|
|
65
|
+
`publish-zalos-cli.yml` GitHub Actions workflow, so releases no longer rely on a stored npm token.
|
|
61
66
|
Version 0.2.13 adds revision-safe Markdown import and export for team Pages. It converts common
|
|
62
67
|
Tiptap process-document structures while rejecting unsupported stored nodes during export, and uses
|
|
63
68
|
the `pages:read` and `pages:write` scopes for least-privilege API access.
|
package/README.md
CHANGED
|
@@ -11,11 +11,31 @@ Requires Node.js 22 or newer. The product CLI is public on npm and does not
|
|
|
11
11
|
require GitHub CLI or GitHub Packages access.
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm install --global @zalosai/zalos-cli@0.2.
|
|
14
|
+
npm install --global @zalosai/zalos-cli@0.2.15
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Installing the CLI does not grant access.
|
|
18
18
|
|
|
19
|
+
## Agent skills
|
|
20
|
+
|
|
21
|
+
The package includes a production-operations skill for Codex and Claude. It describes
|
|
22
|
+
region selection, browser login, team switching, preview-first changes, workflow
|
|
23
|
+
publishing, Team Files, Pages, and Motion work without embedding credentials.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
zl skills list
|
|
27
|
+
zl skills read zl-ops
|
|
28
|
+
zl skills install zl-ops --target codex
|
|
29
|
+
# Or:
|
|
30
|
+
zl skills install zl-ops --target claude
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Codex installs to `$CODEX_HOME/skills` when `CODEX_HOME` is set, otherwise `~/.codex/skills`;
|
|
34
|
+
Claude installs to `~/.claude/skills`. Use `--directory <path>` to install beneath a custom skills
|
|
35
|
+
root. Installation leaves an identical existing skill unchanged and refuses to replace local edits unless `--force` is
|
|
36
|
+
explicitly supplied. These commands work locally and do not need authentication or an
|
|
37
|
+
environment selection.
|
|
38
|
+
|
|
19
39
|
## First run
|
|
20
40
|
|
|
21
41
|
```bash
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { ValidationError } from '../utils/errors.js';
|
|
6
|
+
import { printJson } from '../utils/output.js';
|
|
7
|
+
import { action } from '../utils/product-api.js';
|
|
8
|
+
const OPS_SKILL_NAME = 'zl-ops';
|
|
9
|
+
const OPS_SKILL_PATH = fileURLToPath(new URL('../../skills/zl-ops/SKILL.md', import.meta.url));
|
|
10
|
+
function isSkillTarget(value) {
|
|
11
|
+
return value === 'claude' || value === 'codex';
|
|
12
|
+
}
|
|
13
|
+
function skillPath(name) {
|
|
14
|
+
if (name !== OPS_SKILL_NAME)
|
|
15
|
+
throw new ValidationError('skill', `Unknown skill: ${name}. Available: ${OPS_SKILL_NAME}`);
|
|
16
|
+
return OPS_SKILL_PATH;
|
|
17
|
+
}
|
|
18
|
+
export function resolveDefaultSkillsDirectory(target, home = homedir()) {
|
|
19
|
+
if (target === 'codex') {
|
|
20
|
+
const codexHome = process.env.CODEX_HOME;
|
|
21
|
+
if (codexHome)
|
|
22
|
+
return join(codexHome, 'skills');
|
|
23
|
+
return join(home, '.codex/skills');
|
|
24
|
+
}
|
|
25
|
+
return join(home, '.claude/skills');
|
|
26
|
+
}
|
|
27
|
+
function resolveInstallDirectory(options) {
|
|
28
|
+
if (options.directory && options.target)
|
|
29
|
+
throw new ValidationError('skills', 'Specify either --target or --directory, not both');
|
|
30
|
+
if (options.directory)
|
|
31
|
+
return resolve(options.directory);
|
|
32
|
+
if (!options.target)
|
|
33
|
+
throw new ValidationError('target', 'Choose --target codex or --target claude, or provide --directory');
|
|
34
|
+
if (!isSkillTarget(options.target))
|
|
35
|
+
throw new ValidationError('target', 'Expected --target codex or --target claude');
|
|
36
|
+
return resolveDefaultSkillsDirectory(options.target);
|
|
37
|
+
}
|
|
38
|
+
export async function readSkill(name) {
|
|
39
|
+
return readFile(skillPath(name), 'utf8');
|
|
40
|
+
}
|
|
41
|
+
async function existingContents(path) {
|
|
42
|
+
try {
|
|
43
|
+
return await readFile(path, 'utf8');
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT')
|
|
47
|
+
return null;
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function installSkill(name, options) {
|
|
52
|
+
const contents = await readSkill(name);
|
|
53
|
+
const directory = resolveInstallDirectory(options);
|
|
54
|
+
const destination = join(directory, name, 'SKILL.md');
|
|
55
|
+
const existing = await existingContents(destination);
|
|
56
|
+
if (existing === contents)
|
|
57
|
+
return { skill: name, status: 'unchanged', path: destination };
|
|
58
|
+
if (existing !== null && !options.force)
|
|
59
|
+
throw new ValidationError('destination', `Skill already exists at ${destination}; use --force to replace local changes`);
|
|
60
|
+
await mkdir(dirname(destination), { recursive: true, mode: 0o755 });
|
|
61
|
+
await writeFile(destination, contents, { mode: 0o644 });
|
|
62
|
+
return {
|
|
63
|
+
skill: name,
|
|
64
|
+
status: existing === null ? 'installed' : 'updated',
|
|
65
|
+
path: destination,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function registerSkillsCommand(program) {
|
|
69
|
+
const command = program.command('skills').description('Read and install bundled agent skills');
|
|
70
|
+
command
|
|
71
|
+
.command('list')
|
|
72
|
+
.description('List bundled skills (no network or authentication required)')
|
|
73
|
+
.action(() => printJson({
|
|
74
|
+
skills: [{ name: OPS_SKILL_NAME, description: 'Zalos production operations' }],
|
|
75
|
+
}));
|
|
76
|
+
command
|
|
77
|
+
.command('read <name>')
|
|
78
|
+
.description('Print a bundled SKILL.md (no network or authentication required)')
|
|
79
|
+
.action(async (name) => action(async () => {
|
|
80
|
+
process.stdout.write(await readSkill(name));
|
|
81
|
+
}));
|
|
82
|
+
command
|
|
83
|
+
.command('install <name>')
|
|
84
|
+
.description('Install a bundled skill for Codex or Claude')
|
|
85
|
+
.option('--target <target>', 'Install into the standard codex or claude skill directory')
|
|
86
|
+
.option('--directory <path>', 'Install beneath a custom skills directory')
|
|
87
|
+
.option('--force', 'Replace a locally modified installed skill')
|
|
88
|
+
.action(async (name, options) => action(async () => printJson(await installSkill(name, options))));
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=skills.js.map
|
package/dist/main.js
CHANGED
|
@@ -20,6 +20,7 @@ import { registerTaskCommentCommand } from './commands/task-comment.js';
|
|
|
20
20
|
import { registerTaskCommand } from './commands/task.js';
|
|
21
21
|
import { registerTeamCommand } from './commands/team.js';
|
|
22
22
|
import { registerPageCommand } from './commands/page.js';
|
|
23
|
+
import { registerSkillsCommand } from './commands/skills.js';
|
|
23
24
|
import { configureApiUrlOverride, currentEnvironment } from './environments.js';
|
|
24
25
|
import { handleError } from './utils/errors.js';
|
|
25
26
|
const program = new Command();
|
|
@@ -41,8 +42,10 @@ program
|
|
|
41
42
|
configureApiUrlOverride(opts.apiUrl);
|
|
42
43
|
if (actionCommand.name() === 'zl' ||
|
|
43
44
|
actionCommand.name() === 'schema' ||
|
|
45
|
+
actionCommand.name() === 'skills' ||
|
|
44
46
|
(actionCommand.name() === 'validate' && actionCommand.parent?.name() === 'workflow') ||
|
|
45
|
-
actionCommand.parent?.name() === 'schema'
|
|
47
|
+
actionCommand.parent?.name() === 'schema' ||
|
|
48
|
+
actionCommand.parent?.name() === 'skills')
|
|
46
49
|
return;
|
|
47
50
|
try {
|
|
48
51
|
currentEnvironment();
|
|
@@ -65,6 +68,7 @@ registerCredentialCommand(program);
|
|
|
65
68
|
registerFileCommand(program);
|
|
66
69
|
registerTeamCommand(program);
|
|
67
70
|
registerPageCommand(program);
|
|
71
|
+
registerSkillsCommand(program);
|
|
68
72
|
registerSchemaCommand(program);
|
|
69
73
|
registerStateCommand(program);
|
|
70
74
|
registerLabelCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zalosai/zalos-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
4
|
"description": "API-only product command-line interface for Zalos",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,11 +15,21 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"dist/**/*.js",
|
|
17
17
|
"README.md",
|
|
18
|
-
"PUBLISHING.md"
|
|
18
|
+
"PUBLISHING.md",
|
|
19
|
+
"skills/**/*.md"
|
|
19
20
|
],
|
|
20
21
|
"engines": {
|
|
21
22
|
"node": ">=22"
|
|
22
23
|
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc --build",
|
|
26
|
+
"clean": "tsc --build --clean && rm -rf dist",
|
|
27
|
+
"dev": "tsx src/main.ts",
|
|
28
|
+
"prepack": "pnpm clean && pnpm build",
|
|
29
|
+
"smoke:package": "node scripts/smoke-package.mjs",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"typecheck": "tsgo --noEmit --types node --incremental --tsBuildInfoFile dist/tsconfig.typecheck.tsbuildinfo"
|
|
32
|
+
},
|
|
23
33
|
"dependencies": {
|
|
24
34
|
"@tiptap/core": "3.27.1",
|
|
25
35
|
"@tiptap/extension-heading": "3.27.1",
|
|
@@ -41,13 +51,5 @@
|
|
|
41
51
|
"publishConfig": {
|
|
42
52
|
"access": "public",
|
|
43
53
|
"registry": "https://registry.npmjs.org"
|
|
44
|
-
},
|
|
45
|
-
"scripts": {
|
|
46
|
-
"build": "tsc --build",
|
|
47
|
-
"clean": "tsc --build --clean && rm -rf dist",
|
|
48
|
-
"dev": "tsx src/main.ts",
|
|
49
|
-
"smoke:package": "node scripts/smoke-package.mjs",
|
|
50
|
-
"test": "vitest run",
|
|
51
|
-
"typecheck": "tsgo --noEmit --types node --incremental --tsBuildInfoFile dist/tsconfig.typecheck.tsbuildinfo"
|
|
52
54
|
}
|
|
53
|
-
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zl-ops
|
|
3
|
+
description: Operate Zalos production workflows, executions, Team Files, Pages, and Motion work through the public Zalos CLI.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Zalos CLI Operations
|
|
7
|
+
|
|
8
|
+
Use this skill when an operator needs to inspect or safely change Zalos data through `zl`.
|
|
9
|
+
The CLI works against one production region at a time. Ask whether the task is in
|
|
10
|
+
`us-prod` or `eu-prod` when it is not already specified; never infer a region.
|
|
11
|
+
|
|
12
|
+
## Set up and verify access
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node --version
|
|
16
|
+
npm install --global @zalosai/zalos-cli@latest
|
|
17
|
+
zl --environment <us-prod|eu-prod> auth login
|
|
18
|
+
zl --environment <us-prod|eu-prod> auth status
|
|
19
|
+
zl --environment <us-prod|eu-prod> team list
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
A current Zalos browser session completes login automatically. Only ask the user to
|
|
23
|
+
interact with the browser if the browser itself requires sign-in or consent. Do not
|
|
24
|
+
print credentials, profile files, or API tokens.
|
|
25
|
+
|
|
26
|
+
Run `zl --version` and the relevant `--help` command before saying that a command or
|
|
27
|
+
option is unavailable. An absent documented command usually means the global CLI needs
|
|
28
|
+
an update.
|
|
29
|
+
|
|
30
|
+
## Select the correct team
|
|
31
|
+
|
|
32
|
+
`team list` returns the active memberships available to the signed-in user in the
|
|
33
|
+
chosen region. Use its opaque `publicId` value, such as `tm_4ERk9QxW`:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
zl --environment <us-prod|eu-prod> team switch <team-ref>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Switch the selected team before a change. A switch only works for a team the user can
|
|
40
|
+
access and preserves the session expiry. For permitted read-only file inspection, use
|
|
41
|
+
an explicit `--team-id <team-ref>` where the command supports it. Never treat a `tm_`
|
|
42
|
+
reference as a UUID.
|
|
43
|
+
|
|
44
|
+
## Inspect before changing
|
|
45
|
+
|
|
46
|
+
Start with a small read and use fields to keep output focused:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
zl --environment <us-prod|eu-prod> workflow list --fields id,name,active
|
|
50
|
+
zl --environment <us-prod|eu-prod> workflow view <workflow-id>
|
|
51
|
+
zl --environment <us-prod|eu-prod> execution list --limit 20
|
|
52
|
+
zl --environment <us-prod|eu-prod> execution summary <execution-id>
|
|
53
|
+
zl --environment <us-prod|eu-prod> page list --fields id,title,updatedAt
|
|
54
|
+
zl --environment <us-prod|eu-prod> file tree --team-id <team-ref>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use the IDs from command output. For an execution artifact, inspect the execution first,
|
|
58
|
+
then download the immutable artifact through the authenticated CLI:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
zl --environment <us-prod|eu-prod> execution artifact download <artifact-id> --output /tmp/artifact
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Make controlled changes
|
|
65
|
+
|
|
66
|
+
For a supported mutation, preview it first. Review the response, then repeat the same
|
|
67
|
+
command with `--apply` only when the intended team, object, and paths are confirmed.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
zl --environment <us-prod|eu-prod> workflow update <workflow-id> --input /tmp/workflow.json --dry-run
|
|
71
|
+
zl --environment <us-prod|eu-prod> workflow update <workflow-id> --input /tmp/workflow.json --apply
|
|
72
|
+
zl --environment <us-prod|eu-prod> workflow publish <workflow-id> --apply
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
A workflow update saves a draft. Publish the workflow after reviewing its draft and
|
|
76
|
+
live-version response; executions continue using the published version until then.
|
|
77
|
+
|
|
78
|
+
For Team Files seeding, preview first, then use exactly the checksum returned by that
|
|
79
|
+
preview:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
zl --environment <us-prod|eu-prod> file seed --source-team-id <source-team-ref> --source-path /Fixtures --target-path /Rehearsal
|
|
83
|
+
zl --environment <us-prod|eu-prod> file seed --source-team-id <source-team-ref> --source-path /Fixtures --target-path /Rehearsal --apply --expected-checksum <sha256>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Pages and Motion work
|
|
87
|
+
|
|
88
|
+
Pages use Markdown files with a revision marker. Export before editing, then preview
|
|
89
|
+
and apply the update using that file:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
zl --environment <us-prod|eu-prod> page export <page-id> --output /tmp/process.md
|
|
93
|
+
zl --environment <us-prod|eu-prod> page update <page-id> --input /tmp/process.md --dry-run
|
|
94
|
+
zl --environment <us-prod|eu-prod> page update <page-id> --input /tmp/process.md --apply
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For Motion work, inspect the project and valid state IDs first. Use `--dry-run` for task
|
|
98
|
+
creation, updates, moves, and comments whenever the command offers it.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
zl --environment <us-prod|eu-prod> project list --fields id,name
|
|
102
|
+
zl --environment <us-prod|eu-prod> state list --project-id <project-id> --fields id,name,type
|
|
103
|
+
zl --environment <us-prod|eu-prod> task create --project-id <project-id> --json '{"title":"Example"}' --dry-run
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Get current command help
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
zl --help
|
|
110
|
+
zl <resource> --help
|
|
111
|
+
zl schema <resource>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Successful product commands emit JSON on stdout. Errors emit structured JSON on stderr
|
|
115
|
+
and exit nonzero. Keep operational output focused on the requested object and report
|
|
116
|
+
what was inspected, previewed, applied, and published.
|