versioncam 0.4.1 → 0.5.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/CHANGELOG.md +56 -0
- package/README.md +160 -8
- package/dist/cli/commands/cloud.d.ts +59 -0
- package/dist/cli/commands/cloud.js +891 -0
- package/dist/cli/commands/cloud.js.map +1 -0
- package/dist/cli/commands/publish.d.ts +17 -1
- package/dist/cli/commands/publish.js +34 -15
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/main.js +2 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/usage.d.ts +4 -3
- package/dist/cli/usage.js +19 -2
- package/dist/cli/usage.js.map +1 -1
- package/dist/cloud/client.d.ts +54 -0
- package/dist/cloud/client.js +133 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/cloud/credentials.d.ts +35 -0
- package/dist/cloud/credentials.js +126 -0
- package/dist/cloud/credentials.js.map +1 -0
- package/dist/cloud/protocol.d.ts +220 -0
- package/dist/cloud/protocol.js +32 -0
- package/dist/cloud/protocol.js.map +1 -0
- package/dist/cloud/repository.d.ts +21 -0
- package/dist/cloud/repository.js +97 -0
- package/dist/cloud/repository.js.map +1 -0
- package/dist/cloud/wait.d.ts +43 -0
- package/dist/cloud/wait.js +110 -0
- package/dist/cloud/wait.js.map +1 -0
- package/dist/env.d.ts +6 -0
- package/dist/env.js +16 -3
- package/dist/env.js.map +1 -1
- package/package.json +1 -1
- package/plugin/README.md +25 -5
- package/plugin/skills/versioncam/SKILL.md +17 -5
- package/plugin/skills/versioncam/platform.md +201 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,62 @@ and versions follow [semantic versioning](https://semver.org/). While the
|
|
|
6
6
|
major version is 0, a minor version may change the config or the clip DSL,
|
|
7
7
|
and its entry here says how.
|
|
8
8
|
|
|
9
|
+
## 0.5.0 (2026-10-07)
|
|
10
|
+
|
|
11
|
+
A minor version: commands for version.cam, and the skill learns to use them.
|
|
12
|
+
Nothing records or renders differently, and the config and the clip DSL are
|
|
13
|
+
as they were.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **`versioncam cloud`** does from a terminal, or from an agent's shell, what
|
|
18
|
+
the dashboard at app.version.cam does. `cloud login` signs the command
|
|
19
|
+
line in with a code you approve in a browser, on any device, so it works
|
|
20
|
+
over SSH and in a sandbox. The token lasts seven days and is kept in
|
|
21
|
+
`~/.config/versioncam/credentials.json`, or under `$XDG_CONFIG_HOME`: a
|
|
22
|
+
file only you may read, with each API's sign-in apart, so staging and
|
|
23
|
+
production sit side by side. No command prints it, and `cloud logout`
|
|
24
|
+
revokes it. `VERSIONCAM_API` chooses the API from the shell alone: unlike
|
|
25
|
+
`publish`, the `cloud` commands never take it, or `XDG_CONFIG_HOME`, from
|
|
26
|
+
a `.env` file, and say so when one sets it, so a cloned repository cannot
|
|
27
|
+
send a sign-in to a server of its choosing.
|
|
28
|
+
- Reading needs nothing more. `cloud status` says of each clip whether it is
|
|
29
|
+
current or broken, since when, who acknowledged it, and what your pages
|
|
30
|
+
play meanwhile, then the plan and where to manage the project; outside a
|
|
31
|
+
clone it lists every project you can see. `cloud failure <clip>` says
|
|
32
|
+
which step stopped a broken clip and why, and saves the page as it was to
|
|
33
|
+
`.versioncam/failures/<clip>.png`. `cloud ack <clip>` is the dashboard's
|
|
34
|
+
"I know, keep the old one". `cloud embed <clip>` prints the snippets that
|
|
35
|
+
embed a clip, and its files, and `cloud plan` the plan and the pages to
|
|
36
|
+
upgrade and pay on. Each read takes `--json`, and `--project owner/repo`
|
|
37
|
+
names a project when the repository's `origin` on GitHub is not the one.
|
|
38
|
+
- **`cloud set`** changes a project's visibility, retention, "Tell viewers
|
|
39
|
+
when a clip is broken" or alerts, and only once you approve that one change
|
|
40
|
+
in the browser: it prints the change in a sentence, an address and a code,
|
|
41
|
+
and waits up to ten minutes. Paying, deleting a project and tokens for CI
|
|
42
|
+
outside GitHub stay on app.version.cam.
|
|
43
|
+
- **The skill's `platform.md`**, which `versioncam init` installs beside the
|
|
44
|
+
other briefs: `/versioncam status`, `/versioncam fix [clip]` (why a clip
|
|
45
|
+
broke, a repair, and a pull request for it) and `/versioncam embed <clip>`,
|
|
46
|
+
and any question about the project on version.cam. It changes nothing you
|
|
47
|
+
did not ask for, leaves every approval to you, and never touches the
|
|
48
|
+
token. A skill already installed gets it from `versioncam init --force`,
|
|
49
|
+
which also overwrites any brief you edited.
|
|
50
|
+
- The README's **`## version.cam`** section: connecting a repository, what
|
|
51
|
+
happens when a clip breaks on each plan, who can see the clips, the
|
|
52
|
+
`cloud` commands, and a repository whose CI runs elsewhere.
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- `publish --report` writes version.cam's whole answer, not only its
|
|
57
|
+
`project` and `versions`, so a field the service adds reaches the
|
|
58
|
+
Action's job summary without a release of this package to carry it:
|
|
59
|
+
where to manage the project, who can see its clips, whether its plan tells
|
|
60
|
+
anyone when a clip breaks, and what a broken clip's pages play.
|
|
61
|
+
- `publish` calls a clip whose check failed on the default branch "broken",
|
|
62
|
+
not "stale", and says that a project token, `VERSIONCAM_TOKEN`, is for a
|
|
63
|
+
repository outside GitHub.
|
|
64
|
+
|
|
9
65
|
## 0.4.1 (2026-10-06)
|
|
10
66
|
|
|
11
67
|
A patch version: nothing records or renders differently.
|
package/README.md
CHANGED
|
@@ -371,18 +371,18 @@ versioncam render [id…] composite and encode recordings and scenes
|
|
|
371
371
|
Send what the last run recorded to [version.cam](https://version.cam), which
|
|
372
372
|
renders it and keeps it at a living address. `publish` records nothing and
|
|
373
373
|
renders nothing: for each clip the config defines, it sends the recording if
|
|
374
|
-
the clip's last run passed, or the failure if it did not, so
|
|
375
|
-
|
|
376
|
-
not seen are uploaded, so a version that changed one screen
|
|
377
|
-
screen.
|
|
374
|
+
the clip's last run passed, or the failure if it did not, so version.cam
|
|
375
|
+
knows when a clip broke (see *When a clip breaks*). Only the states the
|
|
376
|
+
service has not seen are uploaded, so a version that changed one screen
|
|
377
|
+
sends one screen.
|
|
378
378
|
|
|
379
379
|
It needs a credential in the environment, never on the command line:
|
|
380
380
|
`VERSIONCAM_OIDC_TOKEN`, which the versioncam GitHub Action requests from
|
|
381
381
|
GitHub for the run (no secret to store), or `VERSIONCAM_TOKEN`, a project
|
|
382
|
-
token from version.cam for
|
|
383
|
-
somewhere other than `https://api.version.cam`.
|
|
384
|
-
reads the commit and branch from git;
|
|
385
|
-
`VERSIONCAM_BRANCH` set them outright.
|
|
382
|
+
token from version.cam for a repository outside GitHub (see *Other CI*).
|
|
383
|
+
`VERSIONCAM_API` points it somewhere other than `https://api.version.cam`.
|
|
384
|
+
Outside GitHub Actions it reads the commit and branch from git;
|
|
385
|
+
`VERSIONCAM_COMMIT` and `VERSIONCAM_BRANCH` set them outright.
|
|
386
386
|
|
|
387
387
|
```
|
|
388
388
|
versioncam publish [id…] send the recordings and their checks to version.cam
|
|
@@ -390,6 +390,31 @@ versioncam publish [id…] send the recordings and their checks to ver
|
|
|
390
390
|
--report <file> and write the living URLs there, as JSON
|
|
391
391
|
```
|
|
392
392
|
|
|
393
|
+
### Manage
|
|
394
|
+
|
|
395
|
+
What version.cam knows about a project, and its settings, from the command
|
|
396
|
+
line: what the dashboard shows and does, once you have signed in with a code
|
|
397
|
+
you approve in a browser. A setting changes only when you approve that one
|
|
398
|
+
change in the browser too. These need no `versioncam.config.ts`, and run
|
|
399
|
+
anywhere in a clone of the repository. See *From the command line*.
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
versioncam cloud login sign in to version.cam, with a code you approve in a browser
|
|
403
|
+
--label <name> what the approval page calls this machine
|
|
404
|
+
versioncam cloud logout sign out: revoke the token, and delete it
|
|
405
|
+
versioncam cloud status [project] each clip, current or broken, and what plays meanwhile
|
|
406
|
+
versioncam cloud failure <clip> why a clip broke, and its picture, into .versioncam/failures/
|
|
407
|
+
versioncam cloud ack <clip> "I know, keep the old one": the reminders stop
|
|
408
|
+
versioncam cloud embed <clip> the snippets that embed a clip, and its files
|
|
409
|
+
versioncam cloud set <name> <val> change a setting, once you approve it in a browser:
|
|
410
|
+
visibility public|unlisted|private, retention <days>|off,
|
|
411
|
+
viewers on|off, alerts email|slack <address>|off,
|
|
412
|
+
alerts issues on|off
|
|
413
|
+
versioncam cloud plan [account] the plan, and the pages to upgrade and pay on
|
|
414
|
+
--project <owner/repo> which project, when not this repository's
|
|
415
|
+
--json machine-readable, for status, failure, embed and plan
|
|
416
|
+
```
|
|
417
|
+
|
|
393
418
|
### From another directory
|
|
394
419
|
|
|
395
420
|
In a monorepo the app is one directory among many. A command run from
|
|
@@ -409,6 +434,133 @@ versioncam <command> --cwd <dir> as if run in <dir>, which holds versioncam.co
|
|
|
409
434
|
versioncam --version which versioncam this is
|
|
410
435
|
```
|
|
411
436
|
|
|
437
|
+
## version.cam
|
|
438
|
+
|
|
439
|
+
[version.cam](https://version.cam) renders what `versioncam publish` sends
|
|
440
|
+
and keeps each clip at a living address,
|
|
441
|
+
`clips.version.cam/<owner>/<repo>/<clip>`. It plays the newest version from
|
|
442
|
+
your default branch that passed, so a page that embeds it never needs
|
|
443
|
+
editing. Projects are managed on [app.version.cam](https://app.version.cam).
|
|
444
|
+
|
|
445
|
+
### Connect a repository
|
|
446
|
+
|
|
447
|
+
Sign in at [app.version.cam](https://app.version.cam) with GitHub, and
|
|
448
|
+
install the Versioncam GitHub App on the repositories you choose. Then
|
|
449
|
+
publish from GitHub Actions with the
|
|
450
|
+
[versioncam Action](https://github.com/versioncam/action), which signs in
|
|
451
|
+
with GitHub's own token, so there is no secret to store. A repository's
|
|
452
|
+
project appears the first time it publishes, or when the App is installed
|
|
453
|
+
on it.
|
|
454
|
+
|
|
455
|
+
The App is how version.cam learns from GitHub, each time someone signs in,
|
|
456
|
+
who may do what: whoever may read a repository sees its project, and
|
|
457
|
+
whoever administers the repository changes the project's settings. The App
|
|
458
|
+
also reports each publish on GitHub: a check on its commit, and on a pull
|
|
459
|
+
request a comment naming the clips that look different and the ones that
|
|
460
|
+
failed.
|
|
461
|
+
|
|
462
|
+
### When a clip breaks
|
|
463
|
+
|
|
464
|
+
A clip breaks when its check fails on the default branch: a control it uses
|
|
465
|
+
was renamed or removed, a page moved, a step waited for something that never
|
|
466
|
+
came, or the app would not start. A change in how the app looks never breaks
|
|
467
|
+
a clip. It makes a new version.
|
|
468
|
+
|
|
469
|
+
Your pages keep playing the last version that passed, and say nothing about
|
|
470
|
+
the break. A project that wants its viewers told, open source docs perhaps,
|
|
471
|
+
turns on "Tell viewers when a clip is broken" in its settings.
|
|
472
|
+
|
|
473
|
+
On every plan, CI says so, and so does the dashboard: a pull request's check
|
|
474
|
+
fails and the Action comments on it, the App's check on the commit says the
|
|
475
|
+
clip is broken, and the summary of the job that publishes says what your
|
|
476
|
+
pages play meanwhile.
|
|
477
|
+
|
|
478
|
+
On Pro and Max, version.cam also tells your team, by email, in Slack or with
|
|
479
|
+
a GitHub issue, as the project's settings choose. It reminds them two days
|
|
480
|
+
after a clip broke and then every week, until the clip passes again or
|
|
481
|
+
someone acknowledges it on the dashboard ("I know, keep the old one"). An
|
|
482
|
+
acknowledged clip gets one more reminder a month later if it is still
|
|
483
|
+
broken. When the clip passes again, the team is told it is fixed.
|
|
484
|
+
|
|
485
|
+
### Who can see the clips
|
|
486
|
+
|
|
487
|
+
| Visibility | Who can see the clips |
|
|
488
|
+
|---|---|
|
|
489
|
+
| public | Anyone, and search engines. |
|
|
490
|
+
| unlisted | Anyone with the address, kept out of search. The address is made of names, so unlisted means not listed, not secret. |
|
|
491
|
+
| private | Whoever GitHub lets read the repository, signed in at app.version.cam. |
|
|
492
|
+
|
|
493
|
+
A private repository's clips start private, and a public repository's start
|
|
494
|
+
public. A private clip plays only for the people who may see it, so never on
|
|
495
|
+
a public page: to show a private repository's clips in public docs or on a
|
|
496
|
+
landing page, make them public or unlisted in the project's settings.
|
|
497
|
+
|
|
498
|
+
### From the command line
|
|
499
|
+
|
|
500
|
+
`versioncam cloud` does what the dashboard does, from a terminal, and so
|
|
501
|
+
from an agent working in one:
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
npx versioncam cloud login # a code you approve in a browser, once a week
|
|
505
|
+
npx versioncam cloud status # this repository's clips: current or broken, and what plays
|
|
506
|
+
npx versioncam cloud failure checkout # where a broken clip stopped, and the page as it was
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
**Signing in.** `cloud login` prints an address and a code. Open the address
|
|
510
|
+
on any device, sign in with GitHub, check that the page shows the same code,
|
|
511
|
+
and approve it. Nothing calls back to the machine that runs the command, so
|
|
512
|
+
it works over SSH and in a sandbox. The command line then holds a token that
|
|
513
|
+
lasts seven days, in `~/.config/versioncam/credentials.json`, or under
|
|
514
|
+
`$XDG_CONFIG_HOME` when that is set: a file only you may read, which no
|
|
515
|
+
command prints. `cloud logout` revokes it. `VERSIONCAM_API`, set in the
|
|
516
|
+
shell, points the commands at another version.cam, and each one's sign-in
|
|
517
|
+
is kept apart. Unlike `publish`, they never take it, or `XDG_CONFIG_HOME`,
|
|
518
|
+
from a `.env` file, so a repository you clone cannot send your sign-in to a
|
|
519
|
+
server of its choosing, or have the token written inside it.
|
|
520
|
+
|
|
521
|
+
**Reading** needs nothing more. `status` lists the clips: current or broken,
|
|
522
|
+
since when, who acknowledged a broken one, and the version your pages play
|
|
523
|
+
meanwhile; then the plan, and where to manage the project. `failure <clip>`
|
|
524
|
+
says which step stopped a broken clip and why, and saves the page as it was
|
|
525
|
+
then to `.versioncam/failures/<clip>.png`. `embed <clip>` prints the
|
|
526
|
+
snippets that embed it, and `plan` says which plan, why and until when, and
|
|
527
|
+
where to upgrade and pay. Each takes `--json`. They act on the repository
|
|
528
|
+
they run in, from its `origin` remote on GitHub, or on the one that
|
|
529
|
+
`--project owner/repo` names. `ack <clip>` is the dashboard's "I know, keep
|
|
530
|
+
the old one".
|
|
531
|
+
|
|
532
|
+
**A setting changes only once you approve it in the browser,** one change at
|
|
533
|
+
a time. `cloud set visibility public` prints the change in a sentence, an
|
|
534
|
+
address and a code, and waits up to ten minutes. The page shows exactly that
|
|
535
|
+
change, so an agent running the commands for you cannot change a project
|
|
536
|
+
without you seeing what it asked for. The settings are `visibility`,
|
|
537
|
+
`retention`, `viewers` ("Tell viewers when a clip is broken") and `alerts`,
|
|
538
|
+
by email, in Slack or with a GitHub issue.
|
|
539
|
+
|
|
540
|
+
Three things stay a click on app.version.cam: paying (`cloud plan` prints
|
|
541
|
+
the page), deleting a project, and making a project token for CI outside
|
|
542
|
+
GitHub.
|
|
543
|
+
|
|
544
|
+
The authoring skill runs these commands too: `/versioncam status`,
|
|
545
|
+
`/versioncam fix [clip]` and `/versioncam embed <clip>`.
|
|
546
|
+
|
|
547
|
+
### Other CI
|
|
548
|
+
|
|
549
|
+
A repository on GitHub publishes from GitHub Actions, whatever builds it
|
|
550
|
+
otherwise. GitHub's token says which repository, commit and branch a run is
|
|
551
|
+
of, and version.cam takes them from it. A project token, `VERSIONCAM_TOKEN`,
|
|
552
|
+
would have to say all that itself, with nothing to check it against, so it
|
|
553
|
+
speaks only for a project with no GitHub repository.
|
|
554
|
+
|
|
555
|
+
So when your CI runs elsewhere, run just the clips in GitHub Actions: a
|
|
556
|
+
workflow beside the CI you have, with the versioncam Action checking the
|
|
557
|
+
clips on pull requests and publishing them from your default branch. The
|
|
558
|
+
[Action's README](https://github.com/versioncam/action) has one to copy.
|
|
559
|
+
|
|
560
|
+
A repository outside GitHub publishes with a project token, given to
|
|
561
|
+
`versioncam publish` as `VERSIONCAM_TOKEN` and made on the project's page at
|
|
562
|
+
app.version.cam. Its project is set up by hand: write to hello@version.cam.
|
|
563
|
+
|
|
412
564
|
## What a recording leaves behind
|
|
413
565
|
|
|
414
566
|
`versioncam record` writes each clip to `.versioncam/recordings/<id>/`.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ChangeRequest } from "../../cloud/protocol.js";
|
|
2
|
+
import { type Clock } from "../../cloud/wait.js";
|
|
3
|
+
/**
|
|
4
|
+
* `versioncam cloud`: what the dashboard at app.version.cam does, from a
|
|
5
|
+
* terminal, and so from an agent's shell.
|
|
6
|
+
*
|
|
7
|
+
* `versioncam login` was already taken, by the command that saves the app's
|
|
8
|
+
* own browser session for recording, so the platform's commands live under
|
|
9
|
+
* a name of their own.
|
|
10
|
+
*
|
|
11
|
+
* A person signs in once, with a code they approve in a browser, and the
|
|
12
|
+
* commands then read for them: a project's clips and whether each is
|
|
13
|
+
* broken, why one broke, how to embed one, the plan. Acknowledging a broken
|
|
14
|
+
* clip needs no more than that, as on the dashboard. Every setting change
|
|
15
|
+
* prints a code and waits for the person to approve that one change in the
|
|
16
|
+
* browser, because whoever runs these commands may be an agent, and what an
|
|
17
|
+
* agent reads here (clip titles, failure messages) was written by whoever
|
|
18
|
+
* published. Nothing it is told can change a project without a person seeing
|
|
19
|
+
* the change.
|
|
20
|
+
*
|
|
21
|
+
* The token never reaches the output, whatever the service says: every line
|
|
22
|
+
* written passes through a filter that knows it.
|
|
23
|
+
*
|
|
24
|
+
* And the commands run in the environment the shell gave, never with what
|
|
25
|
+
* the repository's `.env.recording` or `.env` added, which the CLI loads
|
|
26
|
+
* before every command. Those files come with whatever was cloned: one that
|
|
27
|
+
* set VERSIONCAM_API could send a sign-in, and every command holding a
|
|
28
|
+
* token, to a server of the repository's choosing, and one that set
|
|
29
|
+
* XDG_CONFIG_HOME could have the token written into the repository itself.
|
|
30
|
+
* `publish` still reads the files: CI sets its environment itself.
|
|
31
|
+
*/
|
|
32
|
+
/** A variable a file set that these commands read only from the shell. */
|
|
33
|
+
export type Ignored = {
|
|
34
|
+
name: string;
|
|
35
|
+
file: string;
|
|
36
|
+
value: string;
|
|
37
|
+
};
|
|
38
|
+
/** What a cloud command needs from the world, so a test can hand it another one. */
|
|
39
|
+
export type CloudIo = {
|
|
40
|
+
/** The shell's environment, never a repository file's. */
|
|
41
|
+
env: NodeJS.ProcessEnv;
|
|
42
|
+
/** What a file tried to set, said once so that nobody wonders why it did nothing. */
|
|
43
|
+
ignored?: Ignored[];
|
|
44
|
+
/** The directory the command runs in: its repository, and its `.versioncam/`. */
|
|
45
|
+
cwd: string;
|
|
46
|
+
out(text: string): void;
|
|
47
|
+
err(text: string): void;
|
|
48
|
+
fetch: typeof fetch;
|
|
49
|
+
clock: Clock;
|
|
50
|
+
hostname(): string;
|
|
51
|
+
/** The zone dates are written in: the machine's own, unless a test pins one. */
|
|
52
|
+
timeZone?: string;
|
|
53
|
+
};
|
|
54
|
+
/** The environment a cloud command runs in, and what the files tried to add to it. */
|
|
55
|
+
export declare function shellEnvironment(): Pick<CloudIo, "env" | "ignored">;
|
|
56
|
+
export declare function cloud(argv: string[]): Promise<number>;
|
|
57
|
+
export declare function runCloud(argv: string[], io: CloudIo): Promise<number>;
|
|
58
|
+
/** The setting and value as the API takes them, or why not. */
|
|
59
|
+
export declare function changeRequest(args: string[]): ChangeRequest | string;
|