Capture a failing environment
twin capture runs your failing command and records the environment it ran in. Nothing is uploaded, no account is needed, and you review the result before it is written.
Run it
Section titled “Run it”-
Open a terminal in the project where the command fails. Anywhere inside the git repository works. twin records the working directory relative to the repository root.
-
Put
twin capture --in front of the failing command:twin capture -- npm testEverything after
--runs as given, with your environment and your terminal, and you see its output live. -
Review the summary. For the capsule in the echarts case study it starts like this:
Commandargv npx jest --config test/ut/jest.config.cjs --coverage=false test/ut/spec/util/time.test.tscwd .result FAIL (exit 1) in 0.8ssignature exit1:0aee0834ac9c4d2dkey lines FAIL test/ut/spec/util/time.test.ts✕ roundTime_localeExpected: 528526800000Received: 528523200000Systemos linux x64 (garuda)libc glibc 2.44time zone America/New_Yorklocale en-USToolchain, Repository, Environment and Redaction sections follow, then the prompt:
Write twin-capsule.json? [y]es / [n]o / [v]iew full JSON:vprints the complete JSON and asks again.ywrites the file. Anything else writes nothing. -
Attach
twin-capsule.jsonto the issue. On GitHub, drag the file into the issue or a comment. It becomes ahttps://github.com/user-attachments/files/…link that maintainers, the MCP server and the GitHub Action can read.
If the command passes, twin says so and still offers to write the capsule. A capsule from a passing run is the --good side of bisect.
Options
Section titled “Options”| Option | Default | What it does |
|---|---|---|
-o, --out <file> |
twin-capsule.json |
Where to write the capsule. |
--include-env <name> |
none | Also record this variable’s value. Repeatable. |
--salt <text> |
none | Record salted hashes of other variables’ values, so a maintainer can compare them without seeing them. |
-y, --yes |
off | Write without the review prompt. Required when there is no terminal. |
Recording a value: --include-env
Section titled “Recording a value: --include-env”twin records every variable’s name and state (set, empty or absent), but values only for a short allowlist (NODE_ENV, TZ, LANG, LC_*, CI, NODE_OPTIONS and a few more, listed in Privacy). If you know a variable matters and its value is not secret, include it:
twin capture --include-env API_URL --include-env FEATURE_FLAGS -- npm testIncluded values still pass through the secret rules. On replay the maintainer’s sandbox gets exactly these values.
Comparing values without revealing them: --salt
Section titled “Comparing values without revealing them: --salt”Some bugs are “same variable, different value” where the value is private. The maintainer posts a salt, for example a random string in the issue, and you capture with it:
twin capture --salt 3f9c2a7e-issue-1234 -- npm testEvery set variable that is not allowlisted or included gets an HMAC-SHA-256 of its value under that salt (the first 32 hex characters). When the maintainer captures with the same salt, twin inspect can tell whether two values are equal without either side seeing the other’s. twin never writes unsalted hashes, because hashes of short values can be guessed.
Without a terminal
Section titled “Without a terminal”In CI or scripts nobody can answer the prompt, so twin refuses unless you pass --yes:
twin capture --yes -o capsule.json -- npm testMaking the capsule useful
Section titled “Making the capsule useful”- Capture the smallest failing command. A single test file replays faster and gives a sharper signature than the whole suite.
- The sandbox fetches the recorded commit from your
originremote, so the commit must exist there. Uncommitted changes travel in the diff. - Install dependencies first. twin reads the installed versions from
node_modulesand your Python environment, which is what the command actually ran against. - Untracked files are recorded by name only. If the failure depends on one, mention it in the issue or commit it.
After writing, twin prints Review it any time with: twin inspect twin-capsule.json. A capsule with 617 installed Node packages is about 37 KB.
Exit status
Section titled “Exit status”| Code | Meaning |
|---|---|
| 0 | Capsule written, whether the command passed or failed. |
| 1 | You declined at the review prompt. |
| 2 | Usage error: no command after --, or no terminal and no --yes. |
| 127 | The command was not found. |
| 130 | Interrupted with Ctrl-C. Nothing was written. |