Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 8 additions & 17 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ releases are the official developer-shell distribution.
It does not own plugin installation, Players, backend services, the site, or
production deployment.

The workspace [`../AGENTS.md`](../AGENTS.md) is the shared working agreement.
This file outranks it on anything local here.
This is a public maintainer guide. In the internal multi-repository workspace,
the optional parent AGENTS.md adds shared operational rules; this repository
does not require that file for standalone contribution.

## Sources of truth

Expand Down Expand Up @@ -68,27 +69,17 @@ This file outranks it on anything local here.
`media upload`. Presentable page → `media generate` as the whole page.
Slide-deck-like → local `compose render`. Live objects → playlist primitives.
Do not emit native `text`, `box`, or `line`.
- `media generate` is billed per token ($10 / 1M text input, $16 / 1M image
input, $60 / 1M image output). Quality (`low`, `medium`, `high`; default
`medium`) changes how detailed the still is and therefore how many tokens it
uses. Remaining that cannot cover the debit returns payment_required / 402,
including during launch fail-open. Never print the prompt or pixels.
- `media generate` reports billed usage. Server admission determines whether
work proceeds; do not infer refusal from the displayed balance. Keep prompt
and pixels out of logs.
- Compose is local and unauthenticated. Never put PNG bytes in stdout.
- Until 2027-01-01 08:00 UTC, production fails open on empty remaining for
billed `/api/v1` work except `media generate`. Do not add pay, Stripe, or
- During the documented launch window, a displayed zero balance does not
determine admission. Respect server payment_required responses. Do not add pay, Stripe, or
x402 commands.
- `cli/` is public. Never write MCP. Never print credentials, cookies, signed
URLs, object keys, or pixels.
- Root `README.md` must keep the exact `[security policy](SECURITY.md)` link.

## Local workspace logs

When this CLI is started through `rig start` in the developer workspace,
stdout and stderr including request, response, and error lines are
appended to `../logs/YY-MM-DD/cli.log` (example
`../logs/26-09-08/cli.log`). Rig deletes date folders older than 7 days.
The `logs/` directory is not a git repository.

## Follow operation logs

Optional `log_socket` lives in the same 0600 user config as the token. There is
Expand Down
17 changes: 17 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# CLI development

For maintainers testing this checkout. Read [AGENTS.md](AGENTS.md) for
source ownership and verification. Execute `node ./dist/bin.js` after building;
keep installed customer plugins independent of this checkout.

## Local configuration

When `config.local-dev.json`
exists in the normal config directory (`$XDG_CONFIG_HOME/screenrig` or
`~/.config/screenrig` on Unix; `%APPDATA%\screenrig` on Windows), the CLI uses
`http://api.screenrig.localhost:8088` by default. Otherwise the production
default is `https://api.screenrig.ai`. `SCREENRIG_API_URL` and `--api-url`
remain explicit overrides.

Use an explicit test configuration to avoid affecting a customer installation.
Do not print stored credentials. Release steps are in [RELEASING.md](RELEASING.md).
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,8 @@ Choose by what the page is:

User-private config lives outside the replaceable plugin directory
(`$XDG_CONFIG_HOME/screenrig/config.json`, or
`%APPDATA%\screenrig\config.json` on Windows). When `config.local-dev.json`
exists in that directory, the CLI uses
`http://api.screenrig.localhost:8088` by default. Otherwise the production
default is `https://api.screenrig.ai`. `SCREENRIG_API_URL` and `--api-url`
remain explicit overrides.
`%APPDATA%\screenrig\config.json` on Windows). The default service is `https://api.screenrig.ai`.
`SCREENRIG_API_URL` and `--api-url` are explicit overrides.

Optional `log_socket` in that same config enables a side-channel NDJSON
operation log. There is no `--log-socket` flag. Connect failure never fails the
Expand All @@ -66,5 +63,7 @@ npm run smoke:mock

Execute this checkout with `node ./dist/bin.js` after `npm run build`.

See [`RELEASING.md`](RELEASING.md) for CalVer stamping and npm publication.
Development profiles are described in [CONTRIBUTING.md](https://github.com/screenrig/cli/blob/main/CONTRIBUTING.md).

See [`RELEASING.md`](https://github.com/screenrig/cli/blob/main/RELEASING.md) for CalVer stamping and npm publication.
Report suspected vulnerabilities through the [security policy](SECURITY.md).
2 changes: 1 addition & 1 deletion assets/playlist-write.schema.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$comment": "Generated by screenrig-protocol-gen from api/openapi.yaml; sha256=ce27b4fed831ef3e97ad216d61383e8598d0a33d3f8666cfc065942b588cb05e. Shape validation only; run canonical playlist-write-semantics.ts next. Reference resolution and DNS remain server checks.",
"$comment": "Generated by screenrig-protocol-gen from api/openapi.yaml; sha256=4b059546fdce814b076959e18746bb88d855bc1d34fbe4dff2aee4fc484a0fe0. Shape validation only; run canonical playlist-write-semantics.ts next. Reference resolution and DNS remain server checks.",
"$defs": {
"CanvasBackground": {
"description": "Solid canonical uppercase #RRGGBBAA, or a top-to-bottom linear gradient.",
Expand Down
2 changes: 0 additions & 2 deletions assets/screenrig.runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@
this.allowOpaqueNativeParent = allowOpaqueNativeParent;
this.unsubscribe = this.host.addMessageListener((event) => this.onMessage(event));
}
nativeParentOrigin;
readyState = "inert";
context = null;
capabilities = { ...EMPTY_CAPABILITIES };
Expand Down Expand Up @@ -662,7 +661,6 @@
this.windowLike = windowLike;
this.parent = windowLike.parent;
}
windowLike;
parent;
addMessageListener(listener) {
const wrapped = (event) => listener(event);
Expand Down
21 changes: 3 additions & 18 deletions src/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3613,24 +3613,9 @@ test("customer-facing credit copy is fail-open until 1 Jan 2027", () => {
}
assert.match(USAGE, /feedback list \[--kind bug\|feature\]/);

const repoRoot = fileURLToPath(new URL("..", import.meta.url));
const agents = readFileSync(path.join(repoRoot, "AGENTS.md"), "utf8");
const readme = readFileSync(path.join(repoRoot, "README.md"), "utf8");
for (const [name, text] of [["AGENTS.md", agents], ["README.md", readme]] as Array<[string, string]>) {
assert.match(text, /whole page/, `${name} must say generate as the whole page`);
assert.match(text, /slide-deck-like/i, `${name} must keep compose for slide-deck-like pages`);
assert.doesNotMatch(text, /\$0\.10 per image/, `${name} must not name a flat still-generation price`);
assert.doesNotMatch(text, /\$0\.06/, `${name} must not name the retired low still price`);
assert.doesNotMatch(text, /\$0\.12/, `${name} must not name the retired medium still price`);
assert.doesNotMatch(text, /\$0\.50/, `${name} must not name the retired high still price`);
assert.doesNotMatch(text, /billed by quality/, `${name} must not say generate is billed by quality tier`);
}
assert.match(agents, /\$10 \/ 1M/, "AGENTS.md must name the text-input token rate");
assert.match(agents, /\$16 \/ 1M/, "AGENTS.md must name the image-input token rate");
assert.match(agents, /\$60 \/ 1M/, "AGENTS.md must name the image-output token rate");
assert.match(agents, /how detailed the still is/, "AGENTS.md must say quality changes how detailed the still is");
assert.match(agents, /fails open/, "AGENTS.md must keep launch fail-open copy");
assert.match(agents, /2027-01-01/, "AGENTS.md must name the 1 Jan 2027 cutoff");
// Maintainer AGENTS.md and README navigation do not duplicate the CLI help
// rate card. Behavior and customer command help are validated above.

});

test("credits_low appends beside generic_filename instead of replacing it", async () => {
Expand Down
12 changes: 6 additions & 6 deletions vendor/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"path": "assets/playlist-write.schema.json",
"source": "packages/protocol/schema/playlist-write.schema.json",
"bytes": 22829,
"sha256": "f197712d4e5433f67c3a70a4232cdbfcb58a3de92fe58f4b0f4f4204536deef4"
"sha256": "4c76e717810cf93ebffa44dce0e382b4bff9111f503acf02278b2ecfc8a78729"
},
{
"path": "src/generated/playlist-write-semantics.ts",
Expand All @@ -18,19 +18,19 @@
"path": "vendor/protocol/openapi.gen.ts",
"source": "packages/protocol/src/openapi.gen.ts",
"bytes": 40758,
"sha256": "6fc05b6ce7971eef414158c3f30226a7752cc1ec6160e846557de7449b0467fd"
"sha256": "740b2107981be837fbcbe78cd3f231e6c5e31fd9c563870968e306c6b66d6ba7"
},
{
"path": "vendor/openapi.yaml",
"source": "api/openapi.yaml",
"bytes": 309833,
"sha256": "ce27b4fed831ef3e97ad216d61383e8598d0a33d3f8666cfc065942b588cb05e"
"bytes": 307468,
"sha256": "4b059546fdce814b076959e18746bb88d855bc1d34fbe4dff2aee4fc484a0fe0"
},
{
"path": "assets/screenrig.runtime.js",
"source": "packages/sdk/dist/screenrig.runtime.js",
"bytes": 30369,
"sha256": "2a514c1892839178599fe90b0fa0f2c6df9d0df661ad93973cab4768b4df3c06"
"bytes": 30329,
"sha256": "2b0e24bd9873e353935f8465c47e8a06d9fa2d7c7cd9fc172d94b35635335990"
}
]
}
Loading
Loading