@iamsaroj/replicax 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +337 -190
  3. package/dist/index.js +823 -61
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -1,62 +1,75 @@
1
1
  <div align="center">
2
2
 
3
- # ReplicaX
3
+ <h1>ReplicaX</h1>
4
+
5
+ <h3><em>Copy the setup, not the code.</em></h3>
6
+
7
+ <p>
8
+ Extract a project's entire development environment — <strong>tooling, folder structure, and conventions</strong> —
9
+ into a portable profile, then recreate it anywhere in seconds.<br/>
10
+ None of your business code. None of your secrets. Just the setup.
11
+ </p>
12
+
13
+ [![npm](https://img.shields.io/badge/npm-%40iamsaroj%2Freplicax-CB3837?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@iamsaroj/replicax)
14
+ [![Node](https://img.shields.io/badge/Node-%E2%89%A5%2020-339933?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org)
15
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org)
16
+ ![ESM](https://img.shields.io/badge/Module-ESM-F7DF1E?style=flat-square&logo=javascript&logoColor=black)
17
+ [![License](https://img.shields.io/badge/License-MIT-3FB950?style=flat-square)](LICENSE)
18
+
19
+ <sub>
20
+ <a href="#quick-start"><b>Quick start</b></a> &nbsp;•&nbsp;
21
+ <a href="#commands"><b>Commands</b></a> &nbsp;•&nbsp;
22
+ <a href="#what-gets-captured"><b>What gets captured</b></a> &nbsp;•&nbsp;
23
+ <a href="#security"><b>Security</b></a> &nbsp;•&nbsp;
24
+ <a href="#how-it-works"><b>How it works</b></a> &nbsp;•&nbsp;
25
+ <a href="#faq"><b>FAQ</b></a>
26
+ </sub>
4
27
 
5
- ### _Copy the setup, not the code._
28
+ </div>
6
29
 
7
- Extract a project's development environment — tooling config, folder structure, and
8
- conventions — into a reusable profile, then recreate it in seconds anywhere.
30
+ ---
9
31
 
10
- ![Node](https://img.shields.io/badge/node-%3E%3D20-43853d)
11
- ![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178c6)
12
- ![Module](https://img.shields.io/badge/module-ESM-f7df1e)
13
- ![License](https://img.shields.io/badge/license-MIT-blue)
32
+ > **ReplicaX captures the _setup_ of a project — the parts you copy‑paste between every new repo — and leaves
33
+ the _implementation_ behind.**
14
34
 
15
- </div>
35
+ Every new project starts the same way: copy `tsconfig.json`, port the ESLint and Prettier config, recreate the
36
+ Dockerfiles, re‑add the CI workflow, rebuild `src/`'s folder layout. It's slow, error‑prone, and quietly drifts out of
37
+ sync across a team.
16
38
 
17
- ---
39
+ ReplicaX captures that ritual **once** and replays it **on demand** — locally, or straight from any GitHub repo.
18
40
 
19
- ReplicaX captures the **setup** of a project the parts you copy-paste between every
20
- new repo — and leaves the **implementation** behind. New projects start with your
21
- exact tooling and folder layout, and **zero** of your business code, secrets, or
22
- build artifacts.
41
+ > It is **not** a code generator, a project cloner, or a backup tool.
23
42
 
24
- It is **not** a code generator, a project cloner, or a backup tool.
43
+ ---
25
44
 
26
- ## Why
45
+ ## Why ReplicaX
27
46
 
28
- Every new project repeats the same ritual: copy `tsconfig.json`, port the ESLint and
29
- Prettier setup, recreate the Docker files, re-add the CI workflow, rebuild `src/`'s
30
- folder layout. It's slow, error-prone, and drifts out of sync across a team.
47
+ | | Without ReplicaX | With ReplicaX |
48
+ |-----------------------|--------------------------------------------|---------------------------------|
49
+ | **New project setup** | 30+ minutes of copy‑paste from an old repo | `replicax create my-app` |
50
+ | **What you copy** | Whatever you remember to grab | A complete, validated profile |
51
+ | **Secrets** | One stray `.env` away from a leak | Blocked unconditionally |
52
+ | **Team consistency** | Drifts repo to repo | One shareable `.tar.gz` profile |
53
+ | **Source code** | Tangled up with the config | Never touched |
31
54
 
32
- ReplicaX captures that ritual once and replays it on demand.
55
+ ---
33
56
 
34
57
  ## Features
35
58
 
36
- - **One-command capture** — `init` scans the current project into a profile.
37
- - **One-command scaffold** — `create` reproduces it in a new directory.
38
- - **`.ts` _and_ `.js` configs** copied byte-for-byte, never compiled or executed.
39
- - **Secret-safe by design** `.env`, keys, and certs can never enter a profile; `.npmrc` auth tokens are stripped
40
- automatically.
41
- - **No business code** folders are recreated empty; source files are never copied.
42
- - **Stays in sync** — `sync --diff` shows what drifted; `validate` checks integrity via SHA-256.
43
- - **Portable & shareable** `export`/`import` a profile as a single `.tar.gz`.
44
- - **`.replicaxignore`** gitignore-style control over what gets exported.
45
-
46
- ## Table of contents
47
-
48
- - [Installation](#installation)
49
- - [Quick start](#quick-start)
50
- - [Worked example](#worked-example)
51
- - [Commands](#commands)
52
- - [What gets captured](#what-gets-captured)
53
- - [Security](#security)
54
- - [replicaxignore](#replicaxignore)
55
- - [Profile format](#profile-format)
56
- - [How it works](#how-it-works)
57
- - [Development](#development)
58
- - [FAQ](#faq)
59
- - [License](#license)
59
+ | | |
60
+ |-------------------------------|------------------------------------------------------------------------------------------------------------------|
61
+ | **One‑command capture** | `init` scans the current project into a reusable profile. |
62
+ | **Capture any GitHub repo** | `extract owner/repo` profiles a remote repo no clone, no `git` required. |
63
+ | **One‑command scaffold** | `create` reproduces the setup in a fresh directory. |
64
+ | **AI assistant skills** | `init-skill` uses your own AI (Claude · Codex · Gemini) to author a ready‑to‑use skill for agentic coding tools. |
65
+ | **`.ts` _and_ `.js` configs** | Copied byte‑for‑byte never compiled, never executed. |
66
+ | **Secret‑safe by design** | `.env`, keys, and certs can never enter a profile; `.npmrc` tokens are stripped automatically. |
67
+ | **No business code** | Folders are recreated empty; source files are never read. |
68
+ | **Stays in sync** | `sync --diff` shows what drifted; `validate` verifies integrity via SHA‑256. |
69
+ | **Portable & shareable** | `export` / `import` a whole profile as a single `.tar.gz`. |
70
+ | **`.replicaxignore`** | gitignore‑style control over exactly what gets captured. |
71
+
72
+ ---
60
73
 
61
74
  ## Installation
62
75
 
@@ -66,26 +79,81 @@ npm install -g @iamsaroj/replicax
66
79
  pnpm add -g @iamsaroj/replicax
67
80
  ```
68
81
 
69
- Requires **Node.js 20+**. ReplicaX is a standalone CLI with no external services.
82
+ > **Requires Node.js 20+.** ReplicaX is a standalone CLI with zero external services.
83
+
84
+ ---
70
85
 
71
86
  ## Quick start
72
87
 
73
88
  ```bash
74
- # 1. In an existing, well-configured project:
89
+ # 1 In an existing, well-configured project
75
90
  cd my-project
76
91
  replicax init # → writes a profile to .replicax/
77
92
 
78
- # 2. Anywhere the profile lives, scaffold a fresh project:
93
+ # 2 Anywhere the profile lives, scaffold a fresh project
79
94
  replicax create my-new-app # → same setup, none of the code
80
95
  ```
81
96
 
82
- > Tip: try `replicax init --dry-run` first to preview exactly what would be captured.
97
+ …and here's what `init` actually shows you:
98
+
99
+ ```console
100
+ $ replicax init
101
+
102
+ ✔ Scanned 14 config file(s) and 9 director(ies)
103
+
104
+ ℹ Captured setup
105
+ language typescript
106
+ framework react
107
+ packageManager npm
108
+ nodeVersion 20.x
109
+
110
+ ℹ Tooling (14 files)
111
+ Build Tools 1
112
+ CI/CD 1
113
+ Docker 2
114
+ Editor 1
115
+ Formatting 1
116
+ Git 1
117
+ Git Hooks 1
118
+ Language & Type Checking 3
119
+ Linting 1
120
+ Testing 1
121
+ package.json 1
122
+
123
+ ℹ Structure (9 directories)
124
+ my-app/
125
+ ├── .github/
126
+ │ └── workflows/
127
+ ├── .husky/
128
+ ├── public/
129
+ └── src/
130
+ ├── components/
131
+ ├── hooks/
132
+ ├── pages/
133
+ └── services/
134
+
135
+ ✔ Profile "my-app" written to .replicax/
136
+ Create a project from it with: replicax create <project-name>
137
+ ```
138
+
139
+ > 💡 **Tip:** run `replicax init --dry-run` first to preview exactly what would be captured — nothing is written.
83
140
 
84
- ## Worked example
141
+ ---
85
142
 
86
- Starting from a typical Vite + React + TypeScript project:
143
+ ## Before & After
87
144
 
88
- ```text
145
+ Starting from a typical **Vite + React + TypeScript** project, `replicax init && replicax create my-new-app` produces a
146
+ clean skeleton — same tooling, zero application code, zero secrets.
147
+
148
+ <table>
149
+ <tr>
150
+ <th align="left">📁 Source project</th>
151
+ <th align="left">✨ Generated by ReplicaX</th>
152
+ </tr>
153
+ <tr>
154
+ <td valign="top">
155
+
156
+ <pre>
89
157
  my-project/
90
158
  ├── vite.config.ts
91
159
  ├── tsconfig.json
@@ -96,46 +164,64 @@ my-project/
96
164
  ├── docker-compose.yml
97
165
  ├── .github/workflows/ci.yml
98
166
  ├── .husky/pre-commit
99
- ├── .env # ← secret
100
- ├── package.json # incl. runtime deps
167
+ ├── .env ← secret
168
+ ├── package.json ← runtime deps
101
169
  └── src/
102
- ├── components/Button.tsx # ← business code
170
+ ├── components/
171
+ │ └── Button.tsx ← business code
103
172
  ├── hooks/
104
- ├── services/UserService.ts # ← business code
173
+ ├── services/
174
+ │ └── UserService.ts ← business code
105
175
  └── pages/
106
- ```
107
-
108
- ```bash
109
- replicax init
110
- replicax create my-new-app --skip-install
111
- ```
176
+ </pre>
112
177
 
113
- ReplicaX produces:
178
+ </td>
179
+ <td valign="top">
114
180
 
115
- ```text
181
+ <pre>
116
182
  my-new-app/
117
- ├── vite.config.ts # copied verbatim
118
- ├── tsconfig.json
119
- ├── tsconfig.node.json
120
- ├── .prettierrc
121
- ├── eslint.config.js
122
- ├── Dockerfile
123
- ├── docker-compose.yml
183
+ ├── vite.config.ts verbatim
184
+ ├── tsconfig.json
185
+ ├── tsconfig.node.json
186
+ ├── .prettierrc
187
+ ├── eslint.config.js
188
+ ├── Dockerfile
189
+ ├── docker-compose.yml
124
190
  ├── .github/workflows/ci.yml
125
- ├── .husky/pre-commit
126
- ├── package.json # name renamed; scripts/devDeps kept, runtime deps dropped
191
+ ├── .husky/pre-commit
192
+ ├── package.json curated
127
193
  └── src/
128
- ├── components/ # recreated, but EMPTY
129
- ├── hooks/
130
- ├── services/ # recreated, but EMPTY
131
- └── pages/
132
- ```
194
+ ├── components/ EMPTY
195
+
196
+ ├── hooks/ EMPTY
197
+ ├── services/ ✓ EMPTY
198
+
199
+ └── pages/ ✓ EMPTY
200
+ </pre>
201
+
202
+ </td>
203
+ </tr>
204
+ </table>
205
+
206
+ No `.env`. No `Button.tsx`. No `UserService.ts`. No `react` runtime dependency. **Only the setup.**
133
207
 
134
- No `.env`, no `Button.tsx`, no `UserService.ts`, no `react` runtime dependency — only
135
- the setup.
208
+ ---
136
209
 
137
210
  ## Commands
138
211
 
212
+ | Command | What it does |
213
+ |--------------------------------------------------------------------------------------|----------------------------------------------------|
214
+ | [`replicax init`](#replicax-init) | Scan the current project → profile in `.replicax/` |
215
+ | [`replicax extract <repo>`](#replicax-extract-repo) | Profile a **remote GitHub repo** (no clone) |
216
+ | [`replicax create <name>`](#replicax-create-project-name) | Scaffold a new project from a profile |
217
+ | [`replicax sync`](#replicax-sync) | Update the profile from the current project |
218
+ | [`replicax inspect`](#replicax-inspect) | Display captured config & structure |
219
+ | [`replicax validate`](#replicax-validate) | Schema + integrity (SHA‑256) check — CI‑friendly |
220
+ | [`replicax export`](#replicax-export--import) / [`import`](#replicax-export--import) | Portable `.tar.gz` profile in/out |
221
+ | [`replicax init-skill`](#replicax-init-skill) | Author an AI‑assistant skill from your stack |
222
+
223
+ > Every write operation accepts `--dry-run` (preview, touch nothing) and `--verbose` (list every file).
224
+
139
225
  ### `replicax init`
140
226
 
141
227
  Scan the current project and write a profile to `.replicax/`.
@@ -146,10 +232,34 @@ replicax init --dry-run # preview, write nothing
146
232
  replicax init --verbose # list every detected file
147
233
  ```
148
234
 
235
+ ### `replicax extract <repo>`
236
+
237
+ Capture a profile from a **remote GitHub repository** instead of the current directory — the same scan as `init`,
238
+ pointed at a repo you don't even have checked out. The repo is downloaded as a tarball over the GitHub API (no `git`
239
+ required) into a temp directory, scanned, then discarded; only the profile is kept.
240
+
241
+ ```bash
242
+ replicax extract khanalsaroj/typegen-ui # owner/repo shorthand
243
+ replicax extract https://github.com/khanalsaroj/typegen-ui # or a full URL
244
+ replicax extract owner/repo --ref develop # a branch, tag, or commit
245
+ replicax extract owner/repo#v1.2.3 # ref via #fragment / @tag too
246
+ replicax extract owner/repo --name react-enterprise # name the profile
247
+ replicax extract owner/repo --out ./profiles/react # write .replicax elsewhere
248
+ replicax extract owner/repo --dry-run # preview, write nothing
249
+ ```
250
+
251
+ Accepts `owner/repo`, a `github.com` URL (including `/tree/<branch>` links), an ssh remote, or a `#branch` / `@tag`
252
+ suffix.
253
+
254
+ > **Private repos & rate limits:** set `GITHUB_TOKEN` (or `GH_TOKEN`) in your environment — it's read from the
255
+ > environment, used for the one request, and **never stored**. The same secret guard applies, so a remote repo's
256
+ `.env` /
257
+ > keys are never captured.
258
+
149
259
  ### `replicax create <project-name>`
150
260
 
151
- Create a new project from a profile. Existing files trigger an interactive
152
- overwrite/skip prompt (auto-skips when non-interactive).
261
+ Create a new project from a profile. Existing files trigger an interactive overwrite/skip prompt (auto‑skips when
262
+ noninteractive).
153
263
 
154
264
  ```bash
155
265
  replicax create my-app
@@ -161,7 +271,7 @@ replicax create my-app --dry-run # preview the file plan
161
271
 
162
272
  ### `replicax sync`
163
273
 
164
- Re-scan and update the profile to match the current project.
274
+ Rescan and update the profile to match the current project.
165
275
 
166
276
  ```bash
167
277
  replicax sync # update, print a change summary
@@ -193,8 +303,7 @@ Tooling (14 file(s))
193
303
 
194
304
  ### `replicax validate`
195
305
 
196
- Check the profile's schema and integrity (SHA-256 checksums + path safety). Exits
197
- non-zero on failure — handy in CI.
306
+ Check the profile's schema and integrity (SHA256 checksums + path safety). Exits non‑zero on failure — handy in CI.
198
307
 
199
308
  ```bash
200
309
  replicax validate
@@ -210,7 +319,39 @@ replicax import ./react-enterprise.tar.gz # validates before adopting
210
319
  replicax import ./react-enterprise.tar.gz --force # overwrite an existing profile
211
320
  ```
212
321
 
213
- > `--dry-run` is available on every write operation and never touches disk.
322
+ ### `replicax init-skill`
323
+
324
+ Generate an AI‑assistant **skill** from the current project — a ready‑to‑use bundle (an entry `SKILL.md` plus optional
325
+ `references/`) that teaches an assistant the tech stack, the install/build/test/lint commands, the tooling, and the
326
+ folder layout, written where your assistant looks for skills.
327
+
328
+ It uses **whatever AI you already have configured**. ReplicaX prefers a locally installed CLI (reusing its login) and
329
+ falls back to a provider API key from your environment — it never stores credentials:
330
+
331
+ | Provider | CLI (preferred) | API key (fallback) | API model default |
332
+ |----------|-----------------|-------------------------------------|--------------------|
333
+ | `claude` | `claude -p` | `ANTHROPIC_API_KEY` | `claude-opus-4-8` |
334
+ | `openai` | `codex exec` | `OPENAI_API_KEY` | `gpt-5.5` |
335
+ | `gemini` | `gemini` | `GEMINI_API_KEY` / `GOOGLE_API_KEY` | `gemini-3.5-flash` |
336
+
337
+ ```bash
338
+ replicax init-skill --target claude # auto-detect provider, author the skill
339
+ replicax init-skill --target codex --provider gemini # force a specific provider
340
+ replicax init-skill --target claude --model claude-sonnet-4-6 # override the API model
341
+ replicax init-skill --target claude --no-ai # skip AI; use the built-in template
342
+ replicax init-skill --target claude --dry-run # preview (no AI call, nothing written)
343
+ replicax init-skill --target claude --force # overwrite existing skill files
344
+ ```
345
+
346
+ **Targets** (`--target`, required) control the on‑disk _format/location_: `claude` → `.claude/skills/<name>/SKILL.md`,
347
+ `codex` → `.codex/skills/<name>/SKILL.md`, `antigravity` → `.agents/skills/<name>.md`. The **provider** (auto‑detected,
348
+ or forced with `--provider`) is the AI that _authors_ it — the two are independent.
349
+
350
+ > **Privacy:** only the project's _setup_ is sent to the provider — the same safe surface ReplicaX captures (config
351
+ > files, structure, `package.json` scripts/deps). Source code and secrets are never sent. With `--no-ai` (or no provider
352
+ > configured), ReplicaX falls back to a deterministic, fully offline template.
353
+
354
+ ---
214
355
 
215
356
  ## What gets captured
216
357
 
@@ -222,35 +363,40 @@ replicax import ./react-enterprise.tar.gz --force # overwrite an existing profi
222
363
  | Docker, CI/CD (Actions, GitLab, CircleCI, Jenkins) | `node_modules/`, `dist/`, `build/`, `coverage/`, `.next/`, … |
223
364
  | `.editorconfig`, Husky hooks | IDE folders (`.vscode/`, `.idea/`, `.vs/`, `.fleet/`, `.zed/`) |
224
365
  | Test configs (Vitest/Jest/Playwright/Cypress) | Anything matched by `.replicaxignore` |
225
- | Monorepo files, commitlint/lint-staged/release/knip | |
366
+ | Monorepo files, commitlint/lintstaged/release/knip | |
226
367
  | Folder hierarchy (directories only) | Folder _contents_ |
227
368
 
228
- **`package.json`** is curated, not copied: only `scripts`, `devDependencies`,
229
- `engines`, `type`, `packageManager`, and config blocks like `lint-staged` are kept.
230
- Runtime `dependencies` are deliberately dropped, and the new project's name is
231
- stamped in on `create`.
369
+ **`package.json` is curated, not copied.** Only `scripts`, `devDependencies`, `engines`, `type`, `packageManager`, and
370
+ config blocks like `lint-staged` are kept. Runtime `dependencies` are deliberately dropped (that's your application),
371
+ and the new project's name is stamped in on `create`.
372
+
373
+ Both `.ts` and `.js` config variants work because ReplicaX copies them **verbatim** — it never needs to compile or
374
+ execute a config to capture it.
232
375
 
233
- Both `.ts` and `.js` config variants are supported because ReplicaX copies them
234
- **verbatim** — it never needs to compile or execute a config to capture it.
376
+ ---
235
377
 
236
378
  ## Security
237
379
 
238
- ReplicaX treats secret exclusion as a hard guarantee, not a best effort:
380
+ ReplicaX treats secret exclusion as a **hard guarantee, not a best effort.**
239
381
 
240
- - **Secrets are never captured.** `.env`, `.env.*`, `*.pem`, `*.key`, `*.crt`,
241
- SSH keys, and friends are blocked unconditionally — this cannot be overridden by
242
- configuration.
243
- - **`.npmrc` is sanitized.** It's a legitimate setup file, but auth tokens
244
- (`_authToken`, `_password`, …) are stripped out before it enters a profile.
245
- - **No path escapes.** Every path read from a profile is validated against traversal
246
- (`..`) and absolute paths before anything is written, so a malicious profile can't
247
- write outside its target directory.
382
+ > 🛡️ **Secrets are never captured.** `.env`, `.env.*`, `*.pem`, `*.key`, `*.crt`, SSH keys, and friends are blocked *
383
+ *unconditionally** — this cannot be overridden by configuration.
248
384
 
249
- ## `.replicaxignore`
385
+ > 🧼 **`.npmrc` is sanitized.** It's a legitimate setup file, but auth tokens (`_authToken`, `_password`, …) are stripped
386
+ > out before it enters a profile.
250
387
 
251
- Control what gets exported with gitignore syntax. `init` can scaffold a starter for
252
- you. Ignored files are excluded from the profile but their parent directories are
253
- still captured for structure.
388
+ > 🚧 **No path escapes.** Every path read from a profile (or from an AI response) is validated against traversal (`..`)
389
+ > and absolute paths before anything is written, so a malicious profile can never write outside its target directory.
390
+ `validate` re‑checks this.
391
+
392
+ The same guarantees apply to `extract` — a remote repo's secrets are filtered exactly as a local project's are.
393
+
394
+ ---
395
+
396
+ ## Configuration — `.replicaxignore`
397
+
398
+ Control what gets exported with **gitignore syntax**. `init` can scaffold a starter for you. Ignored files are excluded
399
+ from the profile — but their parent directories are still captured for structure.
254
400
 
255
401
  ```gitignore
256
402
  # Business logic (folders kept, contents dropped)
@@ -262,6 +408,8 @@ src/**/*.ts
262
408
  *.log
263
409
  ```
264
410
 
411
+ ---
412
+
265
413
  ## Profile format
266
414
 
267
415
  A profile is five JSON files under `.replicax/`:
@@ -275,120 +423,119 @@ A profile is five JSON files under `.replicax/`:
275
423
  └── checksum.json # SHA-256 integrity hashes
276
424
  ```
277
425
 
278
- All five are schema-validated (zod) on load; `validate` additionally re-checks
279
- checksums and rejects unsafe paths.
426
+ All five are schemavalidated (zod) on load; `validate` additionally rechecks checksums and rejects unsafe paths.
427
+
428
+ ---
280
429
 
281
430
  ## How it works
282
431
 
283
- ```text
284
- ┌─────────┐ ┌──────────────────┐ ┌──────────────┐
285
- init/sync │ Scanner ───▶ Profile Generator│ ───▶ .replicax/ │
286
- └─────────┘ └──────────────────┘ └──────────────┘
287
- │ │
288
- ignore engine + secret guard load + zod validate
289
-
290
- ┌──────────────────┐ ▼
291
- create Project Generator│ ◀─────────────────── ProfileBundle
292
- └──────────────────┘
293
-
294
- conflict resolver (overwrite/skip)
432
+ ```mermaid
433
+ flowchart LR
434
+ A["📁 Local project"] -- "init / sync" --> S["🔎 Scanner"]
435
+ G["🌐 GitHub repo"] -- "extract" --> S
436
+ S --> F{"Ignore engine<br/>+ secret guard"}
437
+ F -- "safe setup only" --> P["🧬 Profile Generator"]
438
+ P --> D[("📦 .replicax/<br/>5 JSON files")]
439
+ D -- "load + zod validate" --> B["ProfileBundle"]
440
+ B -- "create" --> PG["🏗️ Project Generator"]
441
+ PG --> N["✨ New project<br/>setup, no code"]
442
+
443
+ style F fill:#1f2937,stroke:#f59e0b,color:#fff
444
+ style D fill:#0f172a,stroke:#38bdf8,color:#fff
295
445
  ```
296
446
 
297
- - **Scanner** detects config files (via a glob catalogue), the folder hierarchy, and
298
- project metadata (package manager, framework, language).
299
- - **Ignore engine** layers default ignores + `.replicaxignore`, with a separate,
300
- non-overridable **secret guard**.
447
+ - **Scanner** detects config files (via a glob catalogue), the folder hierarchy, and project metadata (package manager,
448
+ framework, language).
449
+ - **Ignore engine** layers default ignores + `.replicaxignore`, with a separate, **non‑overridable secret guard**.
301
450
  - **Profile generator** assembles the bundle and computes checksums.
302
- - **Project generator** reproduces the setup, adapting names/paths, with a
303
- **conflict resolver** for existing files.
451
+ - **Project generator** reproduces the setup, adapting names/paths, with a **conflict resolver** for existing files.
452
+
453
+ ---
304
454
 
305
455
  ## Development
306
456
 
307
457
  ```bash
308
458
  npm install
309
459
  npm run build # tsup → dist/index.js (single ESM file, with shebang)
310
- npm run typecheck # tsc --noEmit
311
- npm test # vitest (32 tests, real temp-dir fixtures)
460
+ npm run typecheck # tsc --noEmit (covers src AND tests)
461
+ npm test # vitest (real temp-dir fixtures, no mocks)
312
462
  npm run format # prettier --write .
313
463
  npm run dev # tsup --watch
314
464
  ```
315
465
 
316
- > **Lockfile:** `package-lock.json` is maintained with **npm 10** (the version CI's
317
- > Node 20/22 ship with). If you're on npm 11+, regenerate it with `npx npm@10 install`
318
- > when changing dependencies — npm 11 resolves a different tree and will desync `npm ci`.
319
-
320
- Imports use a `@/*` → `src/*` alias resolved by tsc, tsup/esbuild, and the
321
- `vite-tsconfig-paths` vitest plugin. The build bundles to one file, so the alias
322
- never reaches the published output.
323
-
324
- **Stack:** TypeScript 5 · Node 20+ · ESM · commander · fast-glob · fs-extra ·
325
- ignore · zod · tar · picocolors · ora · @inquirer/prompts · cli-table3 · vitest ·
326
- tsup · prettier.
327
-
328
- > **Audit note:** `npm audit` flags `esbuild` (a build-time transitive of `tsup`).
329
- > The advisory concerns esbuild's dev server, which ReplicaX never runs, and
330
- > esbuild is not part of the published runtime (`dist/`). Fixing it requires a
331
- > breaking tsup downgrade, so the toolchain is left intact.
466
+ ```bash
467
+ # Run a single test file, or by name:
468
+ npx vitest run tests/scanner.test.ts
469
+ npx vitest run -t "sanitizes a captured .npmrc"
470
+ ```
332
471
 
333
- ## Releasing
472
+ <details>
473
+ <summary><b>Toolchain notes &amp; gotchas</b></summary>
334
474
 
335
- Publishing is **fully automated** by [`.github/workflows/release.yml`](.github/workflows/release.yml):
336
- bump the version, push to `main`, and the workflow tags the commit, runs the full
337
- CI gate (format, types, tests, build, CLI smoke test), publishes to npm with
338
- [provenance](https://docs.npmjs.com/generating-provenance-statements), and opens a
339
- GitHub Release with generated notes. You never create the tag by hand.
475
+ <br/>
340
476
 
341
- **One-time setup:**
477
+ **Lockfile.** `package-lock.json` is maintained with **npm 10** (what CI's Node 20/22 ship with). On npm 11+, regenerate
478
+ with `npx npm@10 install` when changing dependencies — npm 11 resolves a different tree and will desync `npm ci`.
342
479
 
343
- 1. Create a **classic Automation token** on npm (Access Tokens Generate New
344
- Token Classic Token **Automation**). If your account has 2FA enabled for
345
- writes, this is the token type that can publish from CI — it bypasses the
346
- interactive 2FA prompt. (A granular or classic _Publish_ token still requires
347
- an OTP and will fail in CI with a `403`.)
348
- 2. Add it to the repo as a secret named `NPM_TOKEN`
349
- (Settings → Secrets and variables → Actions). Scoping it to a `npm`
350
- environment is optional but recommended for required-reviewer protection.
480
+ **Path alias.** Imports use a `@/*` `src/*` alias resolved by tsc, tsup/esbuild, and the `vite-tsconfig-paths` vitest
481
+ plugin. The build bundles to one file, so the alias never reaches the published output.
351
482
 
352
- **Cut a release** bump and push, that's it:
483
+ **Stack.** TypeScript 5 · Node 20+ · ESM · commander · fast‑glob · fs‑extra · ignore · zod · tar · picocolors · ora ·
484
+ @inquirer/prompts · cli‑table3 · vitest · tsup · prettier.
353
485
 
354
- ```bash
355
- npm version patch --no-git-tag-version # minor / major too; bumps package.json + lock
356
- git commit -am "Release v0.1.0"
357
- git push # → workflow tags v0.1.0 and publishes
358
- ```
486
+ **Audit note.** `npm audit` flags `esbuild` (a build‑time transitive of `tsup`). The advisory concerns esbuild's dev
487
+ server, which ReplicaX never runs, and esbuild is not part of the published runtime (`dist/`). Fixing it requires a
488
+ breaking tsup downgrade, so the toolchain is left intact.
359
489
 
360
- The release gate is "is this version already on npm?", so:
490
+ </details>
361
491
 
362
- - A normal push with no version change is a **no-op**.
363
- - Re-running never double-publishes (npm already has the version → skipped).
364
- - The git tag (`vX.Y.Z`) is created **after** a successful publish, so a failed
365
- publish stays retryable.
366
- - Prerelease versions (e.g. `0.2.0-beta.1`) publish under a matching dist-tag
367
- (`beta`) instead of `latest`.
368
-
369
- > Don't push tags manually — let the workflow own tagging. Every push and PR is
370
- > also checked by [`.github/workflows/ci.yml`](.github/workflows/ci.yml) across Node 20 and 22.
492
+ ---
371
493
 
372
494
  ## FAQ
373
495
 
374
- **Does it copy my source code?** No. Only configuration files and the empty folder
375
- hierarchy. Application code is never read into a profile.
376
-
377
- **What about `.ts` config files like `vite.config.ts`?** Fully supported they're
378
- copied as text, so both `.ts` and `.js` variants work without any compile step.
379
-
380
- **Can a profile leak a secret?** No. Secret exclusion is unconditional and `.npmrc`
381
- tokens are stripped; `validate` will fail if a secret ever appears in a profile.
382
-
383
- **Why are runtime `dependencies` dropped from `package.json`?** They're part of your
384
- application, not your setup. `devDependencies`, `scripts`, and `engines` are kept.
496
+ <details>
497
+ <summary><b>Does it copy my source code?</b></summary>
498
+ <br/>
499
+ No. Only configuration files and the empty folder hierarchy. Application code is never read into a profile.
500
+ </details>
501
+
502
+ <details>
503
+ <summary><b>What about <code>.ts</code> config files like <code>vite.config.ts</code>?</b></summary>
504
+ <br/>
505
+ Fully supported they're copied as text, so both <code>.ts</code> and <code>.js</code> variants work without any compile step.
506
+ </details>
507
+
508
+ <details>
509
+ <summary><b>Can a profile leak a secret?</b></summary>
510
+ <br/>
511
+ No. Secret exclusion is unconditional and <code>.npmrc</code> tokens are stripped; <code>validate</code> will fail if a secret ever appears in a profile.
512
+ </details>
513
+
514
+ <details>
515
+ <summary><b>Why are runtime <code>dependencies</code> dropped from <code>package.json</code>?</b></summary>
516
+ <br/>
517
+ They're part of your application, not your setup. <code>devDependencies</code>, <code>scripts</code>, and <code>engines</code> are kept.
518
+ </details>
519
+
520
+ <details>
521
+ <summary><b>Does <code>extract</code> need <code>git</code> installed?</b></summary>
522
+ <br/>
523
+ No. It downloads the repo as a tarball over the GitHub API using Node's built-in <code>fetch</code> — no <code>git</code> binary, no full clone.
524
+ </details>
525
+
526
+ <details>
527
+ <summary><b>Is it cross-platform?</b></summary>
528
+ <br/>
529
+ Yes — Windows (native + WSL), macOS, and Linux.
530
+ </details>
385
531
 
386
- **Is it cross-platform?** Yes — Windows (native + WSL), macOS, and Linux.
532
+ ---
387
533
 
388
534
  ## License
389
535
 
390
- MIT — see [LICENSE](LICENSE).
391
-
392
- ---
536
+ **MIT** — see [LICENSE](LICENSE).
393
537
 
394
- <div align="center"><sub><i>ReplicaX — copy the setup, not the code.</i></sub></div>
538
+ <div align="center">
539
+ <br/>
540
+ <sub><i>ReplicaX — copy the setup, not the code.</i></sub>
541
+ </div>