@localess/cli 3.0.0-dev.20260313114825 → 3.0.0-dev.20260323211059

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.
Files changed (3) hide show
  1. package/README.md +13 -0
  2. package/SKILL.md +363 -0
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -249,6 +249,19 @@ const content = await client.getContentBySlug<Page>('home', { locale: 'en' });
249
249
 
250
250
  ---
251
251
 
252
+ ## AI Coding Agents
253
+
254
+ This package ships a [`SKILL.md`](./SKILL.md) file that provides AI coding agents (GitHub Copilot, Claude Code, Cursor, and others) with accurate, up-to-date APIs, patterns, and best practices. Most agents automatically read `SKILL.md` when starting a session.
255
+
256
+ When you change the public API of this package, update `SKILL.md` alongside your code:
257
+
258
+ - **New option or parameter** → add it to the relevant options table and usage example
259
+ - **Changed behaviour** → update the description and any affected code snippets
260
+ - **Deprecated API** → mark it clearly and point to the replacement
261
+ - **New command or subcommand** → add a full entry with all flags and examples
262
+
263
+ ---
264
+
252
265
  ## License
253
266
 
254
267
  [MIT](../../LICENSE)
package/SKILL.md ADDED
@@ -0,0 +1,363 @@
1
+ # SKILL: @localess/cli
2
+
3
+ ## Overview
4
+
5
+ `@localess/cli` is the **command-line interface** for the Localess headless CMS platform. It enables:
6
+
7
+ - Authenticating with a Localess instance
8
+ - Pushing and pulling translations (flat JSON; nested format supported for pull only)
9
+ - Generating TypeScript type definitions from the OpenAPI schema
10
+
11
+ **Status:** Early development (v3.0.0). Requires Node.js >= 20.0.0.
12
+
13
+ ---
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install -g @localess/cli
19
+ # or use npx
20
+ npx @localess/cli [command]
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Authentication
26
+
27
+ ### Login
28
+
29
+ Authenticate and persist credentials locally. Interactive prompts fill in any missing options.
30
+
31
+ ```bash
32
+ localess login \
33
+ --origin https://my-localess.web.app \
34
+ --space YOUR_SPACE_ID \
35
+ --token YOUR_API_TOKEN
36
+ ```
37
+
38
+ **Options:**
39
+
40
+ | Flag | Description |
41
+ |------------------------|---------------------------------|
42
+ | `-o, --origin <url>` | Localess instance URL |
43
+ | `-s, --space <id>` | Space ID (from Space settings) |
44
+ | `-t, --token <token>` | API token (masked input prompt) |
45
+
46
+ **Behavior:**
47
+ 1. Checks for existing credentials (env vars or file)
48
+ 2. Prompts interactively for any missing options
49
+ 3. Validates credentials by calling the API
50
+ 4. Saves credentials to `.localess/credentials.json` (mode `0o600`)
51
+
52
+ ### Logout
53
+
54
+ ```bash
55
+ localess logout
56
+ ```
57
+
58
+ - Clears `.localess/credentials.json` (writes `{}`)
59
+ - If authenticated via environment variables, instructs you to unset them manually
60
+
61
+ ---
62
+
63
+ ## Credential Storage
64
+
65
+ Credentials are resolved in this priority order:
66
+
67
+ 1. **Environment variables** (highest priority)
68
+ 2. **`.localess/credentials.json`** (file-based)
69
+
70
+ ### Environment Variables
71
+
72
+ ```bash
73
+ export LOCALESS_ORIGIN=https://my-localess.web.app
74
+ export LOCALESS_SPACE=YOUR_SPACE_ID
75
+ export LOCALESS_TOKEN=YOUR_API_TOKEN
76
+ ```
77
+
78
+ Recommended for **CI/CD pipelines** — no `localess login` step needed.
79
+
80
+ ### File-based Credentials
81
+
82
+ ```json
83
+ // .localess/credentials.json
84
+ {
85
+ "origin": "https://my-localess.web.app",
86
+ "space": "YOUR_SPACE_ID",
87
+ "token": "YOUR_API_TOKEN"
88
+ }
89
+ ```
90
+
91
+ > **Add `.localess/credentials.json` to your `.gitignore`** to avoid committing secrets.
92
+
93
+ ---
94
+
95
+ ## Translations
96
+
97
+ ### Push Translations
98
+
99
+ Upload a local JSON translation file to Localess.
100
+
101
+ ```bash
102
+ localess translations push <locale> --path <file> [options]
103
+ ```
104
+
105
+ **Arguments:**
106
+
107
+ | Argument | Description |
108
+ |------------|-------------------------------------|
109
+ | `<locale>` | ISO 639-1 locale code: `en`, `de`… |
110
+
111
+ **Options:**
112
+
113
+ | Flag | Default | Description |
114
+ |-------------------------|-----------------|-------------------------------------------------------|
115
+ | `-p, --path <path>` | required | Path to the translations JSON file |
116
+ | `-f, --format <format>` | `flat` | File format: `flat` only (**nested not yet implemented**) |
117
+ | `-t, --type <type>` | `add-missing` | Update strategy: `add-missing` or `update-existing` |
118
+ | `--dry-run` | `false` | Preview changes without applying them |
119
+
120
+ **Update Strategies:**
121
+
122
+ | Strategy | Behaviour |
123
+ |--------------------|------------------------------------------------------------|
124
+ | `add-missing` | Only adds keys that don't yet exist in Localess |
125
+ | `update-existing` | Only updates keys that already exist in Localess |
126
+
127
+ **File Formats:**
128
+
129
+ *Flat (default — only supported format for push):*
130
+ ```json
131
+ {
132
+ "common.submit": "Submit",
133
+ "nav.home": "Home",
134
+ "errors.required": "This field is required"
135
+ }
136
+ ```
137
+
138
+ > **⚠️ Nested format is not yet implemented for push.** Passing `--format nested` logs an error and exits without uploading. Use `flat` format only.
139
+
140
+ **Examples:**
141
+
142
+ ```bash
143
+ # Basic push — add missing translations only
144
+ localess translations push en --path ./locales/en.json
145
+
146
+ # Update existing translations (don't add new)
147
+ localess translations push de --path ./locales/de.json --type update-existing
148
+
149
+ # Preview changes without applying
150
+ localess translations push fr --path ./locales/fr.json --dry-run
151
+ ```
152
+
153
+ ---
154
+
155
+ ### Pull Translations
156
+
157
+ Download translations from Localess to a local JSON file.
158
+
159
+ ```bash
160
+ localess translations pull <locale> --path <file> [options]
161
+ ```
162
+
163
+ **Arguments:**
164
+
165
+ | Argument | Description |
166
+ |------------|-------------------------------------|
167
+ | `<locale>` | ISO 639-1 locale code: `en`, `de`… |
168
+
169
+ **Options:**
170
+
171
+ | Flag | Default | Description |
172
+ |-------------------------|-----------|--------------------------------------|
173
+ | `-p, --path <path>` | required | Output file path |
174
+ | `-f, --format <format>` | `flat` | File format: `flat` or `nested` |
175
+
176
+ **Examples:**
177
+
178
+ ```bash
179
+ # Pull as flat JSON
180
+ localess translations pull en --path ./locales/en.json
181
+
182
+ # Pull as nested JSON
183
+ localess translations pull de --path ./locales/de.json --format nested
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Type Generation
189
+
190
+ Generate TypeScript type definitions from your Localess space's OpenAPI schema.
191
+
192
+ ```bash
193
+ localess types generate [--path <output>]
194
+ ```
195
+
196
+ **Options:**
197
+
198
+ | Flag | Default | Description |
199
+ |---------------------|-------------------------------|-------------------------------|
200
+ | `-p, --path <path>` | `.localess/localess.d.ts` | Output file path |
201
+
202
+ > **Prerequisite:** The API token must have the **Development Tools** permission in Localess Space settings.
203
+
204
+ **What it does:**
205
+ 1. Fetches the OpenAPI 3.0 spec from your space
206
+ 2. Extracts schema components
207
+ 3. Generates TypeScript `.d.ts` definitions with `openapi-typescript`
208
+
209
+ **Examples:**
210
+
211
+ ```bash
212
+ # Default output to .localess/localess.d.ts
213
+ localess types generate
214
+
215
+ # Custom output path
216
+ localess types generate --path src/types/localess.d.ts
217
+ ```
218
+
219
+ **Generated output:**
220
+
221
+ ```typescript
222
+ // .localess/localess.d.ts (auto-generated — do not edit)
223
+ export type Page = {
224
+ _id: string;
225
+ _schema: string;
226
+ title: string;
227
+ body: (HeroSection | CardGrid | RichTextBlock)[];
228
+ };
229
+
230
+ export type HeroSection = {
231
+ _id: string;
232
+ _schema: string;
233
+ headline: string;
234
+ subheadline?: string;
235
+ image?: ContentAsset;
236
+ };
237
+
238
+ // ... all schemas from your Localess space
239
+ ```
240
+
241
+ **Using generated types:**
242
+
243
+ ```typescript
244
+ import type { Page, HeroSection } from './.localess/localess';
245
+ import { getLocalessClient } from "@localess/react";
246
+
247
+ const client = getLocalessClient();
248
+ const content = await client.getContentBySlug<Page>('home');
249
+ // content.data is fully typed as Page
250
+ ```
251
+
252
+ ---
253
+
254
+ ## CI/CD Integration
255
+
256
+ ### GitHub Actions Example
257
+
258
+ ```yaml
259
+ # .github/workflows/sync-translations.yml
260
+ name: Sync translations
261
+
262
+ on:
263
+ push:
264
+ paths:
265
+ - 'locales/**'
266
+
267
+ jobs:
268
+ push-translations:
269
+ runs-on: ubuntu-latest
270
+ steps:
271
+ - uses: actions/checkout@v4
272
+ - uses: actions/setup-node@v4
273
+ with:
274
+ node-version: '20'
275
+ - run: npm install -g @localess/cli
276
+ - run: localess translations push en --path ./locales/en.json
277
+ env:
278
+ LOCALESS_ORIGIN: ${{ secrets.LOCALESS_ORIGIN }}
279
+ LOCALESS_SPACE: ${{ secrets.LOCALESS_SPACE_ID }}
280
+ LOCALESS_TOKEN: ${{ secrets.LOCALESS_TOKEN }}
281
+ ```
282
+
283
+ ### Pull Translations in CI
284
+
285
+ ```yaml
286
+ - run: localess translations pull en --path ./locales/en.json
287
+ env:
288
+ LOCALESS_ORIGIN: ${{ secrets.LOCALESS_ORIGIN }}
289
+ LOCALESS_SPACE: ${{ secrets.LOCALESS_SPACE_ID }}
290
+ LOCALESS_TOKEN: ${{ secrets.LOCALESS_TOKEN }}
291
+ - run: git diff --exit-code locales/ || (git commit -am "chore: sync translations" && git push)
292
+ ```
293
+
294
+ ### Generate Types in CI
295
+
296
+ ```yaml
297
+ - run: localess types generate --path src/types/localess.d.ts
298
+ env:
299
+ LOCALESS_ORIGIN: ${{ secrets.LOCALESS_ORIGIN }}
300
+ LOCALESS_SPACE: ${{ secrets.LOCALESS_SPACE_ID }}
301
+ LOCALESS_TOKEN: ${{ secrets.LOCALESS_TOKEN }}
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Local Development Workflow
307
+
308
+ ```bash
309
+ # 1. Authenticate once
310
+ localess login
311
+
312
+ # 2. Pull latest translations
313
+ localess translations pull en --path ./locales/en.json
314
+
315
+ # 3. Edit translations locally...
316
+
317
+ # 4. Push back (dry-run first)
318
+ localess translations push en --path ./locales/en.json --dry-run
319
+ localess translations push en --path ./locales/en.json
320
+
321
+ # 5. Generate types after schema changes in Localess
322
+ localess types generate
323
+ ```
324
+
325
+ ---
326
+
327
+ ## .gitignore Recommendations
328
+
329
+ ```gitignore
330
+ # Localess credentials (contains API token)
331
+ .localess/credentials.json
332
+
333
+ # Generated types are typically committed to the repo
334
+ # but can be excluded if auto-generated in CI:
335
+ # .localess/localess.d.ts
336
+ ```
337
+
338
+ ---
339
+
340
+ ## Files Written by the CLI
341
+
342
+ | File | Created by | Permissions | Purpose |
343
+ |-------------------------------|-----------------------------|----------------|--------------------------------|
344
+ | `.localess/credentials.json` | `localess login` | `0o600` (owner only) | Persisted auth credentials |
345
+ | `.localess/localess.d.ts` | `localess types generate` | Standard | Generated TypeScript types |
346
+
347
+ ---
348
+
349
+ ## Best Practices
350
+
351
+ 1. **Use environment variables in CI/CD** — set `LOCALESS_ORIGIN`, `LOCALESS_SPACE`, `LOCALESS_TOKEN` as secrets. No `login` command needed.
352
+
353
+ 2. **Always dry-run before pushing translations** in automated scripts: add `--dry-run` first, inspect the output, then run without it.
354
+
355
+ 3. **Commit generated types** (`.localess/localess.d.ts`) to your repo so the whole team benefits from type safety without running the CLI.
356
+
357
+ 4. **Re-run `types generate` after any schema change** in the Localess CMS to keep types in sync.
358
+
359
+ 5. **Use `add-missing` strategy (default)** for initial import of translations; switch to `update-existing` when syncing copy changes.
360
+
361
+ 6. **Never commit `.localess/credentials.json`** — add it to `.gitignore` immediately after `localess login`.
362
+
363
+ 7. **Give the token minimum required permissions** — the `types generate` command needs "Development Tools" permission; other commands only need standard API access.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localess/cli",
3
- "version": "3.0.0-dev.20260313114825",
3
+ "version": "3.0.0-dev.20260323211059",
4
4
  "description": "Localess Command Line.",
5
5
  "keywords": [
6
6
  "localess",
@@ -13,7 +13,8 @@
13
13
  "homepage": "https://github.com/Lessify/localess-js",
14
14
  "sideEffects": false,
15
15
  "files": [
16
- "dist"
16
+ "dist",
17
+ "SKILL.md"
17
18
  ],
18
19
  "exports": {
19
20
  ".": {