Skip to content
Merged
21 changes: 19 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ jobs:
permissions:
contents: read
id-token: write
packages: write

steps:
- name: Check out repository
Expand All @@ -36,6 +37,22 @@ jobs:
run: npm run pack:check

- name: Publish to npm
run: npm publish --access public --provenance
run: npm publish --access public

- name: Set up Node.js for GitHub Packages
uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://npm.pkg.github.com
scope: "@${{ github.repository_owner }}"

- name: Prepare GitHub Packages mirror metadata
run: |
npm pkg set name="@${{ github.repository_owner }}/screenstage"
npm pkg set repository.type="git"
npm pkg set repository.url="https://github.com/${{ github.repository }}.git"

- name: Publish mirror to GitHub Packages
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ The format is based on Keep a Changelog, and this project aims to follow Semanti

- Nothing unreleased yet.

## [0.2.0] - 2026-03-09

- Added a machine-readable CLI contract for `run` and `record`, including JSON event streams, stable exit codes, manifest typing, and output/headless overrides.
- Added a portable `skills/screenstage/` skill with config and troubleshooting references for agent-oriented workflows.
- Rewrote the README into a shorter landing page and moved dense reference material into dedicated docs.
- Added dedicated docs for agent integration, CLI contracts, config reference, authoring guidance, and the Screenstage agent tooling plan.
- Clarified the distinction between scripted `run` captures and human-headed `record` studio captures, including framing and preset tradeoff guidance.

## [0.1.0] - 2026-03-08

- Initial public release of Screenstage.
Expand Down
30 changes: 27 additions & 3 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Releasing

This repo is set up to be published as the `screenstage` npm package.
This repo is set up to be published as the `screenstage` npm package on npmjs.org, with a scoped GitHub Packages mirror published from tags.

## Before The First Public Release

1. Confirm the npm package name is still available.
2. Create an npm automation token and store it as `NPM_TOKEN` in GitHub Actions secrets.
2. Configure npm trusted publishing for this repo and its `release.yml` workflow.
3. Make sure the public repo metadata in `package.json` matches the live GitHub repo.

## Local Release Checklist
Expand Down Expand Up @@ -56,6 +56,30 @@ It will:
1. install dependencies
2. run `npm run check`
3. run `npm run build`
4. run `npm publish --access public`
4. publish to npmjs.org through npm trusted publishing
5. publish a scoped mirror to GitHub Packages as `@<owner>/screenstage`

If you prefer release notes first, create the GitHub release from the pushed tag after CI passes.

## GitHub Packages Mirror

The release workflow also publishes a mirror package to GitHub Packages so the repo can show a package entry under its Packages area.

Mirror package shape:

- npmjs.org: `screenstage`
- GitHub Packages: `@<owner>/screenstage`

The workflow rewrites the package name only inside CI before the GitHub Packages publish step. The source `package.json` remains the unscoped npmjs package definition.

## Authentication Model

This repo now uses two different publish auth paths:

- npmjs.org publish: npm trusted publishing through GitHub Actions OIDC
- GitHub Packages mirror: the built-in `GITHUB_TOKEN` with `packages: write`

That means:

- no `NPM_TOKEN` repository secret is required for npmjs releases
- no manually-added `GITHUB_TOKEN` secret is required for GitHub Packages
33 changes: 20 additions & 13 deletions docs/authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ If you want to avoid hand-building scene arrays for every launch asset, you can

The repo ships with one public example under [../examples/quickstart/README.md](../examples/quickstart/README.md).

Treat authoring choices as framing decisions:

- scene arrays are good when you want explicit structure and deliberate beats
- freeform demo functions are good when you want custom motion and interaction logic
- more camera follow and zoom create emphasis
- less camera follow and lower zoom preserve more context

## Demo Runtime API

Async demo functions receive:
Expand Down Expand Up @@ -65,10 +72,10 @@ await cursor.moveToSelector("[data-demo='search']", {

Built-in move timing presets:

- `"continuous"`
- `"late-arrival"`
- `"depart-reveal"`
- `"settle"`
- `"continuous"`: follow and zoom through the whole move
- `"late-arrival"`: stay broader early, then tighten near arrival
- `"depart-reveal"`: widen earlier as the cursor departs, then travel broader
- `"settle"`: slower handoff suited to smaller local corrections or hover-heavy beats

## Scene API

Expand Down Expand Up @@ -145,9 +152,9 @@ Supported scene types:

Template helpers generate scene arrays for common flows:

- `createFeatureTour()`
- `createFormFillCapture()`
- `createHeroWalkthrough()`
- `createFeatureTour()`: guided multi-step product tours with travel between selectors
- `createFormFillCapture()`: steadier form-entry and submit flows
- `createHeroWalkthrough()`: a more presentation-led landing-page or hero sequence

### Hero Walkthrough Example

Expand Down Expand Up @@ -240,16 +247,16 @@ camera: {
}
```

## Recommended Workflow
## Framing Guidance

For strong release-style captures:
Use these as tradeoffs, not defaults:

- use a source viewport around `1440x900` and render at `1920x1080`
- use a source viewport around `1440x900` and render at `1920x1080` when you want a normal desktop capture baseline
- use `output.preset` for repeatable delivery targets instead of hand-tuning every config
- pause deliberately with `cursor.wait()` or `camera.wait()` so the camera has time to settle
- use `camera.focusSelector()` before important interactions instead of letting every shot be cursor-led
- increase `camera.smoothingMs` if a cursor-led sequence still feels twitchy, or reduce it if the camera feels too lazy
- switch `camera.mode` to `"static"` when you want a composed showcase clip that behaves like a normal screen recording
- use `camera.focusSelector()` when a specific interaction deserves emphasis
- increase `camera.smoothingMs` if cursor-led motion feels too twitchy, or reduce it if it feels too slow
- switch `camera.mode` to `"static"` when the goal is full-page readability rather than cursor-led motion
- use `cursor.typeSelector()` for form entries so the footage reads like a real person using the app
- export `prores` when the clip is headed into Motion or Final Cut for finishing

Expand Down
33 changes: 25 additions & 8 deletions docs/config-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,25 @@ export default {
- `browser.cursor.hideSelectors` lets you hide custom DOM cursor layers when you want Screenstage's cursor but the app also renders its own follower elements.
- `setup` lets you put the app into the right pre-record state before capture starts.

## How To Choose Camera Settings

Camera options control taste and emphasis, not correctness.

Use them based on what the viewer needs:

- more context: lower zoom, calmer preset, or `camera.mode: "static"`
- more emphasis: higher zoom and cursor-led follow behavior
- balanced motion: a follow preset with moderate zoom

The preset names are descriptive, not normative. They are not ranked from best to worst.

## Presets

### Camera Presets

- `"showcase-follow"`: balanced default for release-style motion with calmer hover behavior
- `"tight-follow"`: more responsive for compact UI and faster travel
- `"lazy-follow"`: slower, calmer tracking for broad navigation or hover-heavy sequences
- `"showcase-follow"`: moderate cursor-led framing for guided demos where you want motion without making every move feel aggressive
- `"tight-follow"`: faster, tighter framing for compact UI, small controls, and interaction-heavy beats
- `"lazy-follow"`: slower, broader tracking for flows where page context should stay visible longer
- `"static"`: fixed framing with no follow-cam movement

### Output Presets
Expand Down Expand Up @@ -113,6 +125,15 @@ export default {
- `"minimal"`: quieter shell with less glow and ornament
- `"glass"`: brighter, more luminous shell treatment

## Common Intent Mapping

These are guidance patterns, not hard rules.

- product walkthrough with lots of page context: `camera.mode: "static"` or a calmer follow preset
- cinematic feature emphasis: follow preset plus a higher zoom
- dashboard or broad navigation: `lazy-follow` or `static`
- form fill or CTA focus: `showcase-follow` or `tight-follow`

## Examples

### Shell Customization
Expand Down Expand Up @@ -257,11 +278,7 @@ On machines with `ffmpeg` installed, manual recordings can use one of three path
- `balanced`: JPEG frames plus a high-quality intermediate
- `rgb-frames`: PNG frames plus a lossless RGB intermediate for maximum fidelity

For real local apps, the current recommendation is:

- `browser.capture.mode: "video"`
- a larger source viewport like `1728x1080` on desktop
- `output.preset: "motion-edit"` with both `mp4` and `prores`
Choose among those based on fidelity and runtime tradeoffs, not because one is universally correct.

Built-in shot markers:

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "screenstage",
"version": "0.1.0",
"version": "0.2.0",
"description": "TypeScript CLI for cursor-following product demo videos with Playwright and FFmpeg.",
"repository": {
"type": "git",
Expand All @@ -15,7 +15,7 @@
"node": ">=22"
},
"bin": {
"screenstage": "./dist/cli.js"
"screenstage": "dist/cli.js"
},
"exports": {
".": {
Expand Down
17 changes: 13 additions & 4 deletions skills/screenstage/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,24 @@ When a run fails, inspect:

For common fixes, read [troubleshooting.md](./references/troubleshooting.md).

## Good Defaults
## Choosing Visual Style

Prefer these defaults unless the task suggests otherwise:
Do not assume the user wants either maximum follow-cam motion or maximum static readability by default.

Choose based on what the video is for:

- use more follow-cam motion when the point is to emphasize a specific interaction, field, CTA, or compact workflow beat
- use calmer or wider framing when the point is to preserve page context, layout understanding, or broader navigation
- use `camera.mode: "static"` when the user wants a composed screen recording feel rather than cursor-led reframing
- use camera presets and zoom values as style controls, not as mandatory defaults

If the user clearly wants one style, follow that direction. If the intent is ambiguous and the framing choice materially affects clarity, ask for clarification or make the smallest reasonable assumption and keep the choice easy to revise.

Operational defaults that are still safe:

- `run` over `record` for repeatable feature demos
- `record` when the user explicitly wants to drive the browser live in studio mode
- `--json` for agent execution
- `--output-dir` to keep artifacts isolated from user-owned folders during iteration
- `--headless` for automated runs
- the manifest over ad hoc file guessing

When the user asks for a polished clip but does not specify styling, keep the existing Screenstage presets rather than inventing a custom visual treatment.
27 changes: 27 additions & 0 deletions skills/screenstage/references/config-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,30 @@ Good starting points:
- `studio-browser` for a polished browser-shell presentation

Avoid hand-tuning widths, heights, and camera parameters unless the preset is clearly wrong for the task.

## 8. Camera Choice Guidance

Treat camera options as tradeoffs, not quality rankings.

Use more cursor-led follow behavior when:

- the user wants a cinematic, guided product demo
- the action happens in small UI regions
- the point is to emphasize specific controls or form fields

Use calmer or more static framing when:

- the user needs more page context
- the app layout matters as much as the interaction
- the flow includes broad navigation, dashboards, or large page sections

Useful controls:

- `camera.mode: "follow"`: cursor-led reframing
- `camera.mode: "static"`: fixed framing
- lower `camera.zoom`: more context
- higher `camera.zoom`: more emphasis
- calmer presets like `lazy-follow`: slower reframing
- tighter presets like `tight-follow`: more aggressive reframing

If the user did not specify taste and the choice will materially change how understandable the video is, ask or make the smallest reasonable assumption instead of treating a preset name as a universal best practice.