@samva/cli 0.3.1 → 0.4.0

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/AGENTS.md CHANGED
@@ -5,7 +5,7 @@ Use `samva --help` and `samva <command> --help` as the command contract. For aut
5
5
  Machine-readable results go to stdout; warnings and typed errors go to stderr.
6
6
 
7
7
  `samva templates export --dir <dir> --out <dir>` renders every local template's fixtures to HTML
8
- and text with the asset manifest, using no Samva credential; `--asset-base <origin>` is for an
8
+ and text with the asset manifest, needing a Samva credential only to resolve a live `samva:brand`; `--asset-base <origin>` is for an
9
9
  export that will be delivered, which cannot carry a relative reference.
10
10
  `samva templates check --watch` is the continuous authoring gate. Human mode prints observations;
11
11
  machine watch output uses `--jsonl`. `--json` remains one-shot.
@@ -15,15 +15,24 @@ machine watch output uses `--jsonl`. `--json` remains one-shot.
15
15
  or the newest publication that still validates input identically. They are mutually exclusive and
16
16
  each requires `--template-id`, because a reference is a statement about one template's history.
17
17
 
18
- `samva templates workspace <open|diff|patch|check|fixture|save|history|publish>` is the
18
+ `samva templates workspace <open|diff|patch|add-asset|check|fixture|save|history|publish>` is the
19
19
  hosted project workspace over the CLI, for a caller with no clone: an agent in a sandbox, a CI job,
20
20
  a script. It reaches the same operations the hosted MCP tools reach, so an agent can start a journey in one
21
- and finish it in the other. Every subcommand prints its complete
21
+ and finish it in the other; `add-asset` alone has no MCP twin, because a chat client holds no file
22
+ bytes to send. Every subcommand prints its complete
22
23
  result as JSON because these outputs — revisions, digests, diagnostics — are inputs to the next
23
24
  call. `open` returns the revision every other subcommand is fenced to; a workspace that moved refuses
24
25
  them, and reopening is the recovery. A source that does not build is a successful call carrying a
25
- null declaration and located findings, not a failed one. The Git commands remain the way to author a
26
- project you have cloned.
26
+ null declaration and located findings, not a failed one. `add-asset <template-id> <file>` writes one
27
+ image or font as unsaved bytes at `assets/<file name>` unless `--path` names another project path;
28
+ `--replace` is required to change a path that already holds a file. The Git commands remain the way
29
+ to author a project you have cloned.
30
+
31
+ `samva brands pull [slug]` writes the brand snapshot `.samva/brands/<slug>.json` that `@samva/vite`
32
+ resolves `samva:brand` from offline; bare `pull` snapshots the default brand, and `theme.css` is
33
+ never written. Keep `.samva` gitignored. `samva brands push <file>` validates brand CSS locally,
34
+ exits `1` with located findings when it is outside the brand grammar, and otherwise replaces the
35
+ CSS of the brand `--brand <slug>` names, or of the default brand. `--dry-run` validates offline.
27
36
 
28
37
  `samva templates types --out <file>` writes one TypeScript module from the authenticated template
29
38
  catalog: the input each published template accepts, and the reference a send carries. The default
@@ -34,14 +43,17 @@ catalog, naming what moved. A schema the generator cannot express as a checking
34
43
  with the template and the JSON pointer rather than generated as `unknown`.
35
44
 
36
45
  `samva templates init --name <name>` creates a starter-backed Artifact project and clones its Git
37
- repository. `samva templates clone <template-id>` clones an existing project. Both configure a
46
+ repository. `samva templates clone <project-or-template-id>` clones an existing project. Both configure a
38
47
  repository-local credential helper that exchanges Samva authorization for a short-lived,
39
48
  repository-scoped credential; the token is never stored in the remote URL or Git config. Normal
40
49
  `git fetch`, `git pull`, `git add`, `git commit`, and `git push` remain the synchronization commands.
41
50
  Install from the project's lockfile (`bun install --frozen-lockfile` or `npm ci`) before `samva templates check` or `samva templates build`, then
42
51
  publish a clean, pushed commit with `samva templates publish`. Publish checks that the selected
43
52
  commit is an ancestor of the fetched `origin/<default-branch>` and creates an immutable receipt; it
44
- does not push or rewrite history. The CLI loads the project's installed authoring toolchain so its
53
+ does not push or rewrite history. A project holds several emails: `samva templates add
54
+ <emails/x.tsx>` registers another entry under its `defineEmail` id, `samva templates publish --all`
55
+ publishes every active entry at one commit and exits non-zero if any failed, and `samva templates
56
+ move <old> <new>` follows a `git mv`. The CLI loads the project's installed authoring toolchain so its
45
57
  compiler and editor versions stay pinned by the project lockfile.
46
58
  Template authoring commands run that toolchain under Node.js and name the Node.js version they need
47
59
  when it is missing; other CLI commands are self-contained.
package/README.md CHANGED
@@ -108,9 +108,6 @@ samva email doctor --json
108
108
  samva email tracking defaults get
109
109
  samva email tracking defaults set --opens on --clicks off
110
110
 
111
- # Pull and push the organization email design kit as Tailwind `@theme` CSS.
112
- samva email design pull
113
- samva email design push --dry-run
114
111
  ```
115
112
 
116
113
  ## DKIM rotation
@@ -135,7 +132,7 @@ identity and Artifact repository; Git owns the local checkout and synchronizatio
135
132
 
136
133
  ```sh
137
134
  samva templates init --name "Welcome email" --dir welcome-email
138
- # samva templates clone tmpl_abc123 --dir welcome-email
135
+ # samva templates clone tproj_abc123 --dir welcome-email
139
136
  cd welcome-email
140
137
  bun install --frozen-lockfile
141
138
  bun run dev
@@ -160,6 +157,22 @@ git push origin main
160
157
  samva templates publish --commit HEAD --json
161
158
  ```
162
159
 
160
+ A project holds as many emails as you need, sharing its components, theme, and lockfile. Write
161
+ another entry, register it, then publish every entry at one commit:
162
+
163
+ ```sh
164
+ samva templates add emails/reset.tsx
165
+ git add emails && git commit -m "feat: add password reset" && git push origin main
166
+ samva templates publish --all
167
+ ```
168
+
169
+ `add` uses the entry's `defineEmail` id as the template's handle; pass `--slug` and `--name` to
170
+ choose others or to register an entry before the file exists. `publish --all` publishes every
171
+ active template in the project, reports each result, exits non-zero when any entry failed, and
172
+ lists `defineEmail` files that are not registered. Rerunning it after a partial failure is safe.
173
+ After `git mv`, `samva templates move <old-path> <new-path>` points the template at the new file
174
+ and keeps its id, handle, and publications.
175
+
163
176
  Email entries default-export `defineEmail` with an input schema and declared fixtures. `check`
164
177
  typechecks the project and renders every fixture; `build` writes those rendered fixtures, the input
165
178
  schema, and the compiled executable module graph. Helper modules without a default export are not
@@ -174,13 +187,14 @@ For imported email assets, pass their actual serving base to `check` or `build`,
174
187
  `samva templates build --out dist/templates.json --asset-base https://cdn.example.com/email`.
175
188
  These commands require an HTTPS base for delivery; they do not invent a URL or upload assets.
176
189
  `templates export --dir emails --out dist/email` remains the way to write a local HTML/text export
177
- with relative asset URLs.
190
+ with relative asset URLs. Like `check` and `build`, it treats the current directory as the project:
191
+ its `theme.css` themes the export and `samva:brand` resolves live or from `.samva/brands`.
178
192
 
179
193
  `git fetch`, `git pull`, `git add`, `git commit`, and `git push` are ordinary Git operations. The
180
194
  CLI's `init` and `clone` commands configure the repository-local helper; `publish` does not push
181
195
  for you. It accepts a clean commit that is reachable from the fetched `origin/<default-branch>`
182
- and publishes that exact commit and entry path. Use `--template-id` and `--entry` when publishing
183
- from a checkout that was not created by `samva templates init` or `clone`.
196
+ and publishes that exact commit. A clone records its project in `samva.projectId`; pass
197
+ `--project-id` from a checkout that `samva templates init` or `clone` did not create.
184
198
 
185
199
  The helper is invoked by Git using its credential protocol. It accepts only an HTTPS host and path
186
200
  matching the project's repository, then exchanges the current Samva credential for a read or write
@@ -203,11 +217,12 @@ bounded and reports only the destination, compiler version, and file count.
203
217
 
204
218
  `samva templates publish` resolves the requested revision to an exact commit, verifies the working
205
219
  tree is clean and the commit is an ancestor of the fetched `origin` default branch, then creates an
206
- immutable publication receipt for the project's configured TSX entry. It does not rewrite Git
207
- history or alter the working tree.
220
+ immutable publication receipt for each selected entry: the named entry, every active entry with
221
+ `--all`, or the project's only entry. It does not rewrite Git history or alter the working tree.
208
222
 
209
223
  `templates list`, `get`, `create`, `update`, and `remove` operate on template metadata. They do not
210
- replace the project repository, workspace, or native Git history.
224
+ replace the project repository, workspace, or native Git history. `remove` deactivates a template;
225
+ its file and publications remain.
211
226
 
212
227
  Inline email requires `--subject` and exactly one body source: `--html` or `--text`. Pass `-` as
213
228
  the value to read that body from stdin: `--text -` reads a plain-text body and `--html -` reads an
@@ -220,6 +235,33 @@ to a two-minute timeout. `--timeout` is valid only with `--wait`, and `--wait` c
220
235
  `--dry-run`, since a dry run makes no API call and has nothing to wait on. A timeout or terminal
221
236
  delivery failure returns non-zero after printing the last message state.
222
237
 
238
+ ## Brands
239
+
240
+ A template reaches its organization's brand with `@import "samva:brand";` (the default brand) or
241
+ `"samva:brand/<slug>"` in `theme.css`. The brand lives in Samva, not in the project, and these
242
+ commands work with it:
243
+
244
+ ```sh
245
+ samva brands list
246
+ samva brands get acme --json
247
+ samva brands pull # the default brand
248
+ samva brands pull acme
249
+ samva brands push brand.css --brand acme --dry-run
250
+ samva brands push brand.css # updates the default brand
251
+ ```
252
+
253
+ `samva brands pull [slug]` writes `.samva/brands/<slug>.json` in the project (`--project <dir>`,
254
+ default the current directory). `@samva/vite` resolves `samva:brand` from that snapshot when it
255
+ cannot reach the live brand, so builds and previews work offline. Pull never touches `theme.css`;
256
+ keep `.samva` in `.gitignore`, because the API owns the brand.
257
+
258
+ `samva brands push <file>` validates the file against the brand CSS grammar before uploading:
259
+ `@theme` variables, one dark-mode `@theme` of colors, and `@font-face` rules with https WOFF2
260
+ sources. CSS outside it exits `1` with every finding located at `file:line:column`, and nothing is
261
+ uploaded. `--brand <slug>` names the brand to replace; without it, push updates the organization's
262
+ default brand. `--dry-run` validates without credentials or an API call. Published templates keep
263
+ the brand they were built against until they are republished.
264
+
223
265
  ## Scheduling and campaigns
224
266
 
225
267
  ```sh
@@ -302,7 +344,7 @@ samva email send --help
302
344
  ```
303
345
 
304
346
  Released top-level commands are `login`, `logout`, `org`, `email`, `messages`, `campaigns`,
305
- `scheduled-messages`, `templates`, `webhooks`, `profile`, and `help`. Use `samva <command> --help`
347
+ `scheduled-messages`, `templates`, `brands`, `webhooks`, `profile`, and `help`. Use `samva <command> --help`
306
348
  for flags and runnable examples.
307
349
 
308
350
  Test a configured webhook against its real endpoint with an optional JSON payload. `--data` accepts
package/bin/samva.cjs CHANGED
@@ -53,5 +53,5 @@ try {
53
53
  if (nativeExecutable) {
54
54
  run(nativeExecutable, process.argv.slice(2));
55
55
  } else {
56
- run("bun", [join(__dirname, "..", "dist", "bin.mjs"), ...process.argv.slice(2)]);
56
+ run("bun", ["--no-env-file", join(__dirname, "..", "dist", "bin.mjs"), ...process.argv.slice(2)]);
57
57
  }