@elixpo/lixblogs-cli 1.1.2 → 1.3.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/API.md +18 -0
- package/CHANGELOG.md +10 -0
- package/README.md +107 -17
- package/RELEASE.md +30 -0
- package/bin/lixblogs.mjs +343 -44
- package/package.json +8 -2
- package/skills/lixblogs-analytics/SKILL.md +58 -0
- package/skills/lixblogs-analytics/agents/openai.yaml +7 -0
- package/skills/lixblogs-author/SKILL.md +48 -0
- package/skills/lixblogs-author/agents/openai.yaml +7 -0
- package/skills/lixblogs-editorial/SKILL.md +54 -0
- package/skills/lixblogs-editorial/agents/openai.yaml +7 -0
- package/skills/lixblogs-organizations/SKILL.md +44 -0
- package/skills/lixblogs-organizations/agents/openai.yaml +7 -0
- package/skills/lixblogs-publish/SKILL.md +55 -0
- package/skills/lixblogs-publish/agents/openai.yaml +7 -0
- package/src/api/AnalyticsClient.js +40 -0
- package/src/api/BlogClient.js +5 -0
- package/src/api/CollaborationClient.js +73 -0
- package/src/api/OrgClient.js +158 -0
- package/src/auth/AuthenticatedClient.js +15 -0
- package/src/auth/ElixpoAuthProvider.js +1 -1
- package/src/cli/contract.js +46 -0
- package/src/cli/ui.js +52 -0
- package/src/commands/analytics/index.js +57 -0
- package/src/commands/blog/index.js +4 -0
- package/src/commands/collab/index.js +53 -0
- package/src/commands/org/index.js +22 -0
- package/src/commands/skill/index.js +83 -0
- package/src/config/providerFactory.js +1 -1
package/API.md
CHANGED
|
@@ -20,6 +20,7 @@ logged by the resource API.
|
|
|
20
20
|
| Method | Path | Scope | Behavior |
|
|
21
21
|
| --- | --- | --- | --- |
|
|
22
22
|
| `GET` | `/api/v1` | public | API and compatibility metadata |
|
|
23
|
+
| `GET` | `/api/v1/me` | `lixblogs:profile:read` | Current LixBlogs identity |
|
|
23
24
|
| `GET` | `/api/v1/blogs` | `lixblogs:blog:read` | Accessible blog metadata |
|
|
24
25
|
| `GET` | `/api/v1/blogs/{id}` | `lixblogs:blog:read` | One accessible blog and its content |
|
|
25
26
|
| `POST` | `/api/v1/blogs` | `lixblogs:blog:write` | Create a draft |
|
|
@@ -28,6 +29,23 @@ logged by the resource API.
|
|
|
28
29
|
| `POST` | `/api/v1/blogs/{id}/unpublish` | `lixblogs:blog:publish` | Return a post to draft |
|
|
29
30
|
| `DELETE` | `/api/v1/blogs/{id}` | `lixblogs:blog:delete` | Move a post to trash |
|
|
30
31
|
| `POST` | `/api/v1/blogs/{id}/restore` | `lixblogs:blog:delete` | Restore a trashed post |
|
|
32
|
+
| `GET` | `/api/v1/orgs` | `lixblogs:organizations:read` | Organizations the caller belongs to |
|
|
33
|
+
| `GET` | `/api/v1/orgs/{id}` | `lixblogs:organizations:read` | One caller-visible organization and role |
|
|
34
|
+
| `GET` | `/api/v1/orgs/{id}/collections` | `lixblogs:organizations:read` | Collections within a caller membership |
|
|
35
|
+
| `GET` | `/api/v1/orgs/{id}/members` | `lixblogs:organizations:read` | Members and roles within a caller membership |
|
|
36
|
+
| `GET` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:read` | Editorial team and effective role |
|
|
37
|
+
| `POST` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:write` | Invite or reassign a collaborator |
|
|
38
|
+
| `PATCH` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:write` | Change a collaborator role |
|
|
39
|
+
| `DELETE` | `/api/v1/blogs/{id}/collaborators` | `lixblogs:collaboration:write` | Remove a collaborator or leave a team |
|
|
40
|
+
| `GET` | `/api/v1/collaboration/invitations` | `lixblogs:collaboration:read` | Current identity's invitations |
|
|
41
|
+
| `POST` | `/api/v1/collaboration/invitations` | `lixblogs:collaboration:write` | Accept or decline an invitation |
|
|
42
|
+
| `GET` | `/api/v1/analytics` | `lixblogs:analytics:read` | Bounded creator analytics dimensions |
|
|
43
|
+
|
|
44
|
+
`GET /api/v1/analytics` accepts `scope=personal|org:<id>`, `range=7d|30d|90d|12m|custom`,
|
|
45
|
+
`from`, `to`, `dimension=overview|timeline|posts|sources|devices|countries`, `limit=1..100`,
|
|
46
|
+
and an opaque `cursor`. Organization queries additionally require `lixblogs:organizations:read`
|
|
47
|
+
and an owner, admin, or maintain membership. Responses contain aggregate creator data;
|
|
48
|
+
visitor identifiers are never returned.
|
|
31
49
|
|
|
32
50
|
`GET /api/v1/blogs` accepts `status=all|draft|published`, `limit=1..100`, and
|
|
33
51
|
an opaque `cursor`. Results include authored blogs, accepted collaborations,
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Release notes are generated from merged pull requests. This file records contract-level changes that users must see before upgrading.
|
|
4
|
+
|
|
5
|
+
## 1.3.0
|
|
6
|
+
|
|
7
|
+
- Added scoped organization and editorial commands.
|
|
8
|
+
- Added bounded, read-only creator analytics with JSON and CSV export.
|
|
9
|
+
- Bundled five independently installable LixBlogs agent skills.
|
|
10
|
+
- Added packed-artifact, Accounts device-flow, Blogs resource-contract, provenance, and rollback release gates.
|
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
The official CLI for LixBlogs — publish, manage, and inspect blogs through
|
|
4
4
|
the supported API. Built for creators and agent/automation use.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
This package implements production device-flow authentication and the core
|
|
7
|
+
blog lifecycle over the stable LixBlogs API v1 contract. Its output stays
|
|
8
|
+
compact and predictable for both terminals and automation.
|
|
9
9
|
|
|
10
10
|
## Install (local development)
|
|
11
11
|
|
|
@@ -14,7 +14,6 @@ cd packages/lixblogs-cli
|
|
|
14
14
|
npm install
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
There's no published npm release yet. Once available, install will be:
|
|
18
17
|
```bash
|
|
19
18
|
npm install -g @elixpo/lixblogs-cli
|
|
20
19
|
```
|
|
@@ -29,22 +28,32 @@ node bin/lixblogs.mjs --help
|
|
|
29
28
|
|
|
30
29
|
```bash
|
|
31
30
|
# Log in via device authorization
|
|
32
|
-
node bin/lixblogs.mjs
|
|
31
|
+
node bin/lixblogs.mjs login
|
|
32
|
+
|
|
33
|
+
# Save credentials under an explicit local profile name
|
|
34
|
+
node bin/lixblogs.mjs login --profile personal
|
|
33
35
|
|
|
34
36
|
# Check login status
|
|
35
|
-
node bin/lixblogs.mjs
|
|
37
|
+
node bin/lixblogs.mjs whoami
|
|
36
38
|
|
|
37
39
|
# List profiles and choose the active one
|
|
38
|
-
node bin/lixblogs.mjs
|
|
39
|
-
node bin/lixblogs.mjs
|
|
40
|
+
node bin/lixblogs.mjs profiles
|
|
41
|
+
node bin/lixblogs.mjs use work
|
|
40
42
|
|
|
41
43
|
# Log out (clears local credentials only)
|
|
42
|
-
node bin/lixblogs.mjs
|
|
44
|
+
node bin/lixblogs.mjs logout
|
|
43
45
|
|
|
44
46
|
# Revoke the token server-side and clear local credentials (destructive)
|
|
45
47
|
node bin/lixblogs.mjs auth revoke --yes
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
Interactive login shows one compact device card and stays quiet while Accounts
|
|
51
|
+
approval is pending. Press Enter to open the verification URL locally, use
|
|
52
|
+
`--open` to open it immediately, or copy the URL to any browser when connected
|
|
53
|
+
to a VPS. Device authorization does not require a localhost callback or an
|
|
54
|
+
exposed port. Profile names such as `personal`, `work`, or `test` are local
|
|
55
|
+
credential slots; `whoami` reports the actual Accounts identity.
|
|
56
|
+
|
|
48
57
|
### Blog lifecycle
|
|
49
58
|
|
|
50
59
|
Request the permissions needed for the operations you intend to use:
|
|
@@ -63,13 +72,72 @@ lixblogs blog list --status draft
|
|
|
63
72
|
lixblogs blog create --file post.md --title "A new post" --tag engineering
|
|
64
73
|
lixblogs blog get <id> --json
|
|
65
74
|
lixblogs blog edit <id> --editor
|
|
66
|
-
lixblogs blog publish <id>
|
|
67
|
-
lixblogs blog unpublish <id>
|
|
75
|
+
lixblogs blog publish <id> --yes
|
|
76
|
+
lixblogs blog unpublish <id> --yes
|
|
68
77
|
lixblogs blog delete <id> --yes
|
|
69
78
|
lixblogs blog list --status trashed
|
|
70
|
-
lixblogs blog restore <id>
|
|
79
|
+
lixblogs blog restore <id> --yes
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Inspect valid publication targets before assigning organization metadata:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
lixblogs org list
|
|
86
|
+
lixblogs org get ORG_ID
|
|
87
|
+
lixblogs org collections ORG_ID
|
|
88
|
+
lixblogs org members ORG_ID
|
|
89
|
+
lixblogs org targets --json
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Organization lookup is membership-bound. A slug alone never grants access;
|
|
93
|
+
the API resolves the authenticated user's role before returning tenant data.
|
|
94
|
+
|
|
95
|
+
Editorial collaboration stays separate from publishing:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
lixblogs collab invitations
|
|
99
|
+
lixblogs collab list BLOG_ID
|
|
100
|
+
lixblogs collab invite BLOG_ID --user reviewer --role viewer --yes
|
|
101
|
+
lixblogs collab role BLOG_ID --user reviewer --role editor --yes
|
|
102
|
+
lixblogs collab accept BLOG_ID --yes
|
|
103
|
+
lixblogs collab decline BLOG_ID --yes
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Viewer, editor, and admin roles grant different editorial authority. None of
|
|
107
|
+
these commands publishes a post; public-state changes still use `blog publish`
|
|
108
|
+
with the publish scope and a separate confirmation.
|
|
109
|
+
|
|
110
|
+
### Creator analytics
|
|
111
|
+
|
|
112
|
+
Analytics is read-only and uses bounded date ranges and dimensions:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
lixblogs login --scope openid --scope profile --scope lixblogs:analytics:read
|
|
116
|
+
lixblogs analytics query --range 30d --dimension overview --json --no-input
|
|
117
|
+
lixblogs analytics query --scope org:ORG_ID --range custom \
|
|
118
|
+
--from 2026-07-01 --to 2026-07-31 --dimension posts --limit 25 --json --no-input
|
|
119
|
+
lixblogs analytics export --dimension timeline --format csv --output analytics.csv
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Organization analytics also requires `lixblogs:organizations:read`. Results contain
|
|
123
|
+
aggregates only; the API does not expose visitor identifiers or credentials.
|
|
124
|
+
Exports refuse to overwrite an existing file.
|
|
125
|
+
|
|
126
|
+
### Agent skills
|
|
127
|
+
|
|
128
|
+
The npm artifact bundles each skill independently:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
lixblogs skill list
|
|
132
|
+
lixblogs skill inspect lixblogs-author
|
|
133
|
+
lixblogs skill install lixblogs-author --target .agents/skills --dry-run
|
|
134
|
+
lixblogs skill install lixblogs-author --target .agents/skills --yes
|
|
71
135
|
```
|
|
72
136
|
|
|
137
|
+
Install only the skill needed by the current agent. Existing files are not
|
|
138
|
+
replaced unless `--force --yes` is explicit. The bundled skill declares its
|
|
139
|
+
minimum compatible CLI version and scopes.
|
|
140
|
+
|
|
73
141
|
`create`, `edit`, `publish`, `unpublish`, `delete`, and `restore` accept
|
|
74
142
|
`--dry-run`. Content input is mutually exclusive: `--file`, `--stdin`,
|
|
75
143
|
`--content`, or `--editor`. Permanent deletion additionally requires
|
|
@@ -89,7 +157,7 @@ Global flags:
|
|
|
89
157
|
`https://blogs.elixpo.com`
|
|
90
158
|
- `--json` — machine-readable JSON output
|
|
91
159
|
- `--quiet` — suppress non-essential output
|
|
92
|
-
- `--yes`, `-y` —
|
|
160
|
+
- `--yes`, `-y` — confirm publishing and destructive state changes
|
|
93
161
|
- `--allow-insecure-fallback` — explicit opt-in: if the OS keychain is
|
|
94
162
|
unavailable, use a non-persistent in-memory store instead of failing
|
|
95
163
|
|
|
@@ -103,10 +171,34 @@ Global flags:
|
|
|
103
171
|
environment, for example `--env development --auth-provider mock`.
|
|
104
172
|
- The resource contract, scopes, pagination, errors, and mutation guarantees
|
|
105
173
|
are documented in [API.md](API.md).
|
|
174
|
+
- Release compatibility, provenance, smoke gates, and rollback are documented
|
|
175
|
+
in [RELEASE.md](RELEASE.md). Contract changes are summarized in
|
|
176
|
+
[CHANGELOG.md](CHANGELOG.md).
|
|
106
177
|
|
|
107
178
|
The production client is public and has no client secret. Never add one to
|
|
108
179
|
CLI configuration, package files, or GitHub secrets.
|
|
109
180
|
|
|
181
|
+
### Configuration precedence
|
|
182
|
+
|
|
183
|
+
Configuration resolves in this order: command flags, `LIXBLOGS_*` environment
|
|
184
|
+
variables, the selected named profile, then production-safe defaults. Use
|
|
185
|
+
`lixblogs whoami --json --no-input` to verify the active profile, environment,
|
|
186
|
+
granted scopes, and expiry before automation. Flags are best for one command;
|
|
187
|
+
environment values are best for a contained CI job. Credentials remain in the
|
|
188
|
+
OS keychain and are never read from environment variables.
|
|
189
|
+
|
|
190
|
+
### Troubleshooting
|
|
191
|
+
|
|
192
|
+
- `invalid_scope`: Accounts has not registered the requested permission for
|
|
193
|
+
this client; do not substitute a broader token.
|
|
194
|
+
- `insufficient_scope`: log in again with only the reported missing scope.
|
|
195
|
+
- `account_not_provisioned`: sign in to LixBlogs once with the same Accounts
|
|
196
|
+
identity before retrying the CLI.
|
|
197
|
+
- `precondition_failed`: fetch the current post, reconcile the retained
|
|
198
|
+
conflict copy, and retry with the new revision.
|
|
199
|
+
- `rate_limit_exceeded`: honor `Retry-After`; do not fan out retries.
|
|
200
|
+
- Include the returned request ID in a report, never a token or credential.
|
|
201
|
+
|
|
110
202
|
## Development
|
|
111
203
|
|
|
112
204
|
```bash
|
|
@@ -146,10 +238,8 @@ tests.
|
|
|
146
238
|
See [#135](https://github.com/elixpo/blogs.elixpo/issues/135) for the full
|
|
147
239
|
scope. Rough remaining order:
|
|
148
240
|
|
|
149
|
-
1. Media
|
|
150
|
-
2.
|
|
151
|
-
3. Interactive terminal UI and branding in a separate issue
|
|
152
|
-
4. Agent skill packages and cross-repository E2E coverage
|
|
241
|
+
1. Media commands
|
|
242
|
+
2. Interactive terminal UI and branding in a separate issue
|
|
153
243
|
|
|
154
244
|
## Contributing
|
|
155
245
|
|
package/RELEASE.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Release and compatibility policy
|
|
2
|
+
|
|
3
|
+
## Compatibility
|
|
4
|
+
|
|
5
|
+
- CLI `1.x` targets LixBlogs API `/api/v1` and the Accounts OAuth discovery contract.
|
|
6
|
+
- Additive response fields and commands are minor releases. Fixes without contract changes are patch releases.
|
|
7
|
+
- Removing a command, field, scope, or error code requires a CLI major release or API `/api/v2`.
|
|
8
|
+
- The resource metadata `minCliVersion` is authoritative. An older client must stop before authenticated requests and ask the user to upgrade.
|
|
9
|
+
- Node 18 is the supported runtime floor. Release gates run on Node 22.
|
|
10
|
+
|
|
11
|
+
## Release
|
|
12
|
+
|
|
13
|
+
1. Update the package version and `CHANGELOG.md` in a reviewed PR.
|
|
14
|
+
2. Run the manual **LixBlogs CLI release gate**. It tests the package, installs the exact tarball, checks bundled skills, verifies Blogs resource contracts, and runs the Accounts device-flow contract.
|
|
15
|
+
3. Tag the reviewed commit as `lixblogs-cli-vX.Y.Z`.
|
|
16
|
+
4. The publish workflow reruns the gate, checks that tag and package versions match, attests the tarball, publishes it through npm trusted publishing with provenance, and creates generated GitHub release notes.
|
|
17
|
+
|
|
18
|
+
No npm token is stored in this workflow. The npm package must configure this repository and `publish-lixblogs-cli.yml` as a trusted publisher.
|
|
19
|
+
|
|
20
|
+
## Smoke criteria
|
|
21
|
+
|
|
22
|
+
The packed artifact must install into an empty prefix, render `--help`, discover all five scoped skills, and pass auth, blog lifecycle, organization, collaboration, and analytics command tests. Accounts must pass device approval, refresh rotation, replay protection, and revocation. Blogs must pass bearer validation, concurrency/idempotency, analytics, and media request-boundary tests.
|
|
23
|
+
|
|
24
|
+
## Rollback
|
|
25
|
+
|
|
26
|
+
1. Stop a broken release with `npm deprecate @elixpo/lixblogs-cli@X.Y.Z "Do not use; upgrade to X.Y.N"`.
|
|
27
|
+
2. Restore the previous compatible version with `npm dist-tag add @elixpo/lixblogs-cli@GOOD latest`.
|
|
28
|
+
3. Open a patch PR; never reuse or delete the published version.
|
|
29
|
+
4. Re-run the release gate and publish a new patch tag.
|
|
30
|
+
5. If the API contract caused the failure, raise `minCliVersion` only after the compatible patch is available.
|