
Security News
Free Certified Patch for Critical Rails Active Storage Vulnerability
Socket has released a free Certified Patch for a critical Rails Active Storage vulnerability, giving developers time to upgrade to a secure Rails version.
@opacityhq/cli
Advanced tools
Opacity CLI: import React components, publish via Opacity, swap local imports
The Opacity CLI. Sign in from your terminal, import first-party React components into Opacity, and (optionally) rewrite local imports to consume the published package.
Published to npm as @opacityhq/cli (bin: opacity).
npm install -g @opacityhq/cli
Installs the opacity command globally. Verify with opacity --version.
opacity login # sign in via your browser
opacity import # scan ./src, import + publish your components
opacity import --swap # also rewrite local imports to the published package
opacity loginOpens your browser to the Opacity sign-in flow, polls for completion, and writes credentials with chmod 600. After login, every other command reuses that token + base URL.
Credentials are layered (same precedence as git config local > global):
~/.opacity/credentials.json. One auth covers every Opacity-aware project on this machine. This is the right choice when you batch-run the CLI across many directories (e.g. a sub-agent traversing examples/apps/*).--local: writes <cwd>/.opacity/credentials.json instead. Use this when you want a different account scoped to a single repo (CI runner, staging vs. prod org, demo recordings). The CLI also writes <cwd>/.opacity/.gitignore so the token doesn't get committed.Reads always check local first; falls back to global.
opacity login # global (default)
opacity login --local # project-scoped override
opacity login --base-url https://opacity.example.com
Defaults to OPACITY_BASE_URL if set, otherwise https://opacity.com. Override with --base-url (or OPACITY_BASE_URL) to target a local or self-hosted instance.
opacity logoutBy default removes the active credentials — project-local if one exists, otherwise global. So opacity logout always signs you out of whatever the next command would have used.
opacity logout — narrow: clear the active layer only.opacity logout --global — force removal of ~/.opacity/credentials.json even when a project-local override is also present.To clear both, run logout twice.
opacity whoamiPrints the active user, which credentials file it came from, and the base URL. Use this to debug "why isn't my login working" — e.g. when a stale .opacity/credentials.json in the project is shadowing the global token.
opacity whoami
# Signed in as you@example.com (global).
# Source: ~/.opacity/credentials.json
# Base URL: https://opacity.com
opacity import [path]Scans a directory of first-party React components, ships an import payload to Opacity, publishes a versioned package, and writes manifests under .opacity/ in your project. Defaults to scanning src.
opacity import # scans ./src
opacity import src/components # scope to a subdirectory
opacity import --swap # also rewrite local imports after publish
opacity import --project-name my-ui # override auto-derived name (first import only)
opacity import --branch main # target a specific branch
opacity import --debug # also write .opacity/debug/payload.json
opacity import --print-issues warn # print per-issue snippet detail at or above level
opacity import --dry-run # preview locally; no API call, no .opacity/ writes
On the first import, the server creates a new project under your account and the assigned IDs are persisted to .opacity/config.json. Subsequent imports re-target that same project automatically.
Notable flags:
--swap — runs opacity swap immediately after a successful import.--project-name <name> — only used the first time you import in a directory; afterward the project ID is locked into .opacity/config.json.--branch <name> — defaults to the project's saved branch (usually main).--base-url <url> — overrides the URL saved at login.--print-issues <level> — also print full snippet + caret detail for every issue at or above info | warn | error. The summary table always prints; this adds the per-issue source context.--dry-run — run the full local pipeline without publishing. The issues snapshot still gets written to .opacity/debug/issues.json so you can preview the file-set delta before a real publish. opacity preflight is the same thing under a more discoverable name.Components imported directly by an entry file (src/main.tsx, src/index.tsx, etc.) are skipped automatically — translating them would blank your running app.
opacity preflight [path]Runs the full import pipeline locally without publishing. Equivalent to opacity import --dry-run — it scans, discovers, builds the payload, collects every issue, and writes .opacity/debug/issues.json — but never calls the API and never touches config.json / components.json / manifest.json. Use this to:
opacity import would do on a checkout you haven't published from yet,opacity preflight # scans ./src
opacity preflight src/components # scope to a subdirectory
opacity preflight --print-issues warn # also print per-issue detail at or above level
The full code list, grouped by what the swap actually does (cleanly / visibly degrades / refuses), is documented in docs/supported-shapes.md in the repo.
opacity swap [path]Installs the published Opacity package, wraps your local components with the published equivalents, and hoists dynamic JSX into slots. Reads .opacity/components.json and .opacity/manifest.json written by opacity import.
opacity swap # install package + rewrite imports
opacity swap --dry-run # print diffs only, no install, no writes
opacity swap --print-issues warn # print per-issue snippet detail at or above level
The dry-run mode is the safe way to preview what swap will do before letting it touch your source tree.
.npmrc management)Published packages carry the project's privacy — private by default for CLI
imports — so the install needs credentials. When the repo's .npmrc (and your
~/.npmrc) has no token for the Opacity registry host, swap mints a registry
API key for the project's organization and manages the file for you:
CLI import · <project> and is revocable there.//<host>/:_authToken=…) is written to <repo>/.npmrc
with owner-only permissions (0600), and .npmrc is added to .gitignore..npmrc is already tracked by git, .gitignore cannot protect it —
swap prints a loud warning telling you to git rm --cached .npmrc before
your next commit.After every opacity import run (success or failure), the CLI prints a per-component status table summarising what happened in each phase:
Component Import Swap
──────────────────── ────── ────
Avatar █ █
Button █ █ 1 error
Card █ ░ █ 2 warnings, 1 info
ToastProvider █ █
File-level:
src/utils.ts █ 1 warning
src/App.tsx ░ 1 info
1 error, 2 warnings, 1 info — see .opacity/debug/issues.json
View in Opacity: https://opacity.com/projects/<id>/design
Each cell is two glyphs: the severity slot on the left summarises the worst outcome for that (row, phase) pair, and the info-note slot on the right lights up when any info-level notes accrued.
| Cell | Meaning |
|---|---|
█ green | Phase ran cleanly (component imported successfully, no issues). |
█ yellow | Phase ran with at least one warning. |
█ red | Phase ran with at least one error. |
░ dim | On a component row, phase didn't reach this row (e.g. swap blocked by an import error). On a File-level row, phase ran with only info-level notes (e.g. an entry file that was intentionally skipped). |
| blank | On a File-level row, phase didn't touch this file at all — those rows are sparse so we leave the unused phases empty rather than printing a redundant shade. |
trailing ░ | Cell accrued at least one info-level note alongside a colored severity block — see the JSON for details. |
The trailing summary line counts errors, warnings, and info notes (zero-counts are omitted, so a clean run with only info notes still shows e.g. 3 info). Full per-issue detail is in the JSON snapshot.
.opacity/debug/issues.jsonEvery run writes a per-run snapshot of all issues to .opacity/debug/issues.json, grouped by phase × severity. Shape:
{
"schemaVersion": 1,
"generatedAt": "2026-05-04T18:00:00.000Z",
"commitSha": "abc1234+dirty",
"summary": { "total": 12 },
"phases": {
"import": { "total": 11, "issues": { "error": [...], "warn": [...], "info": [...] } },
"package": { "total": 0, "issues": { "error": [], "warn": [], "info": [] } },
"swap": { "total": 1, "issues": { "error": [], "warn": [...], "info": [] } }
}
}
Each issue carries a stable code (e.g. DYNAMIC_CLASSNAME_UNRESOLVED, CODEMOD_FILE_REFUSED), a target describing what it applies to (node / component / file / project), an optional location with a 3-line source snippet, and a commitSha stamp. The full code list with severity and phase mappings, grouped by outcome, is documented in docs/supported-shapes.md in the repo.
When the import fails (e.g. the server returns 400 because no components were extractable), the CLI still writes this file and prints the table so you can see exactly which components couldn't be imported and why. Pass --print-issues warn (or info/error) to also print snippet + caret detail inline:
warn Card · import · DYNAMIC_CLASSNAME_UNRESOLVED src/Card.tsx:42:18
Dynamic className expression couldn't be resolved to styles
41 | const cls = `card-${variant}`;
42 | return <div className={cls}>...</div>;
^^^
43 | }
Global (per-machine, never inside a project):
~/.opacity/credentials.json — auth token + base URL (chmod 600). Written by opacity login (default scope). Used by every project unless overridden.Project-local (paths relative to the project where you run opacity). The CLI manages a .opacity/.gitignore for you (created on login --local and refreshed on every import) so secrets and per-run debug output stay out of git while project state is committed.
Commit these — they bind the checkout to the Opacity project:
.opacity/config.json — org + project binding, written on first import..opacity/components.json — component IDs, package exports, slot anchors. Used by swap..opacity/manifest.json — the published package name, version, and registry URL.Ignored automatically via .opacity/.gitignore:
.opacity/credentials.json — only present with login --local; overrides the global token for this project..opacity/debug/issues.json — every issue emitted during the run, grouped by phase × severity. Overwritten on each run; written even if the import fails..opacity/debug/payload.json — only with --debug; the raw import payload sent to the server.OPACITY_BASE_URL — default base URL when --base-url isn't passed and no credentials exist.OPACITY_BRANCH — default branch for import when --branch isn't passed.FAQs
Opacity CLI: import React components, publish via Opacity, swap local imports
The npm package @opacityhq/cli receives a total of 0 weekly downloads. As such, @opacityhq/cli popularity was classified as not popular.
We found that @opacityhq/cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.

Security News
Socket has released a free Certified Patch for a critical Rails Active Storage vulnerability, giving developers time to upgrade to a secure Rails version.

Security News
/Threat Research
A malicious Ruby gem runs a credential-stealing worm during installation, poisons AI coding tools, and can wipe files when a stolen GitHub token is revoked.

Security News
GitHub is tightening GitHub Actions security with new restrictions on privileged pull request workflows. Here's what changes and how maintainers are affected.