@@ -16,8 +16,9 @@ import { HttpRecorder } from "@opencode-ai/http-recorder"
1616## Quickstart
1717
1818Provide ` cassetteLayer(name) ` in place of (or layered over) your ` HttpClient ` .
19- The first run records to ` test/fixtures/recordings/<name>.json ` ; subsequent
20- runs replay from it.
19+ By default the layer records on first run and replays on subsequent runs —
20+ no env-var ternary at the call site, and ` CI=true ` forces strict replay so
21+ missing cassettes fail loudly in CI rather than silently re-recording.
2122
2223``` ts
2324import { Effect } from " effect"
@@ -30,28 +31,22 @@ const program = Effect.gen(function* () {
3031 return yield * response .json
3132})
3233
33- // Replay (default). Fails if the cassette is missing.
34+ // Records if the cassette is missing, replays if it exists.
35+ // In CI (CI=true) always replays — fails loudly on missing fixtures.
3436Effect .runPromise (program .pipe (Effect .provide (HttpRecorder .cassetteLayer (" users/get-one" ))))
3537
36- // Record. Hits the upstream and writes the cassette .
38+ // Force a refresh — always hits upstream and overwrites .
3739Effect .runPromise (program .pipe (Effect .provide (HttpRecorder .cassetteLayer (" users/get-one" , { mode: " record" }))))
3840```
3941
40- Set the mode from the environment in your test setup:
41-
42- ``` ts
43- HttpRecorder .cassetteLayer (" users/get-one" , {
44- mode: process .env .RECORD === " true" ? " record" : " replay" ,
45- })
46- ```
47-
4842## Modes
4943
50- | Mode | Behavior |
51- | ------------- | -------------------------------------------------------------------- |
52- | ` replay ` | Default. Match the request to a recorded interaction; error if none. |
53- | ` record ` | Execute upstream, append the interaction, write the cassette. |
54- | ` passthrough ` | Bypass the recorder entirely — just call upstream. |
44+ | Mode | Behavior |
45+ | ------------- | ----------------------------------------------------------------------------------- |
46+ | ` auto ` | Default. Replay if the cassette exists; record if missing. ` CI=true ` forces replay. |
47+ | ` replay ` | Strict — match the request to a recorded interaction; error if none. |
48+ | ` record ` | Execute upstream, append the interaction, write the cassette. |
49+ | ` passthrough ` | Bypass the recorder entirely — just call upstream. |
5550
5651## Cassette format
5752
@@ -101,7 +96,6 @@ secrets escape. Redaction is configured by composing a `Redactor`:
10196import { HttpRecorder , Redactor } from " @opencode-ai/http-recorder"
10297
10398HttpRecorder .cassetteLayer (" anthropic/messages" , {
104- mode: process .env .RECORD === " true" ? " record" : " replay" ,
10599 redactor: Redactor .defaults ({
106100 requestHeaders: { allow: [" content-type" , " anthropic-version" ] },
107101 url: { transform : (url ) => url .replace (/ \/ accounts\/ [^ /] + / , " /accounts/{account}" ) },
@@ -157,7 +151,6 @@ const program = Effect.gen(function* () {
157151 const cassette = yield * HttpRecorder .Cassette .Service
158152 const executor = yield * HttpRecorder .makeWebSocketExecutor ({
159153 name: " ws/subscribe" ,
160- mode: process .env .RECORD === " true" ? " record" : " replay" ,
161154 cassette ,
162155 live: liveExecutor ,
163156 })
@@ -188,7 +181,7 @@ const audit = Effect.gen(function* () {
188181
189182``` ts
190183type RecordReplayOptions = {
191- mode? : " record " | " replay" | " passthrough" // default: "replay"
184+ mode? : " auto " | " replay" | " record " | " passthrough" // default: "auto" (CI=true forces " replay")
192185 directory? : string // default: <cwd>/test/fixtures/recordings
193186 metadata? : Record <string , unknown > // merged into cassette.metadata
194187 redactor? : Redactor // default: Redactor.defaults()
0 commit comments