@iamsaroj/replicax 0.0.1 → 0.0.2
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.
- package/LICENSE +2 -2
- package/README.md +337 -190
- package/dist/index.js +805 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,62 +1,75 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
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
|
+
[](https://www.npmjs.com/package/@iamsaroj/replicax)
|
|
14
|
+
[](https://nodejs.org)
|
|
15
|
+
[](https://www.typescriptlang.org)
|
|
16
|
+

|
|
17
|
+
[](LICENSE)
|
|
18
|
+
|
|
19
|
+
<sub>
|
|
20
|
+
<a href="#quick-start"><b>Quick start</b></a> •
|
|
21
|
+
<a href="#commands"><b>Commands</b></a> •
|
|
22
|
+
<a href="#what-gets-captured"><b>What gets captured</b></a> •
|
|
23
|
+
<a href="#security"><b>Security</b></a> •
|
|
24
|
+
<a href="#how-it-works"><b>How it works</b></a> •
|
|
25
|
+
<a href="#faq"><b>FAQ</b></a>
|
|
26
|
+
</sub>
|
|
4
27
|
|
|
5
|
-
|
|
28
|
+
</div>
|
|
6
29
|
|
|
7
|
-
|
|
8
|
-
conventions — into a reusable profile, then recreate it in seconds anywhere.
|
|
30
|
+
---
|
|
9
31
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-

|
|
13
|
-

|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
43
|
+
---
|
|
25
44
|
|
|
26
|
-
## Why
|
|
45
|
+
## Why ReplicaX
|
|
27
46
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
55
|
+
---
|
|
33
56
|
|
|
34
57
|
## Features
|
|
35
58
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
141
|
+
---
|
|
85
142
|
|
|
86
|
-
|
|
143
|
+
## Before & After
|
|
87
144
|
|
|
88
|
-
|
|
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
|
|
100
|
-
├── package.json
|
|
167
|
+
├── .env ← secret
|
|
168
|
+
├── package.json ← runtime deps
|
|
101
169
|
└── src/
|
|
102
|
-
├── components/
|
|
170
|
+
├── components/
|
|
171
|
+
│ └── Button.tsx ← business code
|
|
103
172
|
├── hooks/
|
|
104
|
-
├── services/
|
|
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
|
-
|
|
178
|
+
</td>
|
|
179
|
+
<td valign="top">
|
|
114
180
|
|
|
115
|
-
|
|
181
|
+
<pre>
|
|
116
182
|
my-new-app/
|
|
117
|
-
├── vite.config.ts
|
|
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
|
|
191
|
+
├── .husky/pre-commit ✓
|
|
192
|
+
├── package.json ✓ curated
|
|
127
193
|
└── src/
|
|
128
|
-
├── components/
|
|
129
|
-
|
|
130
|
-
├──
|
|
131
|
-
|
|
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
|
-
|
|
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
|
-
|
|
261
|
+
Create a new project from a profile. Existing files trigger an interactive overwrite/skip prompt (auto‑skips when
|
|
262
|
+
non‑interactive).
|
|
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
|
|
274
|
+
Re‑scan 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
|
|
197
|
-
non-zero on failure — handy in CI.
|
|
306
|
+
Check the profile's schema and integrity (SHA‑256 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
|
-
|
|
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
|
|
366
|
+
| Monorepo files, commitlint/lint‑staged/release/knip | |
|
|
226
367
|
| Folder hierarchy (directories only) | Folder _contents_ |
|
|
227
368
|
|
|
228
|
-
**`package.json
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
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
|
-
|
|
241
|
-
|
|
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
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
|
279
|
-
|
|
426
|
+
All five are schema‑validated (zod) on load; `validate` additionally re‑checks checksums and rejects unsafe paths.
|
|
427
|
+
|
|
428
|
+
---
|
|
280
429
|
|
|
281
430
|
## How it works
|
|
282
431
|
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
-
|
|
472
|
+
<details>
|
|
473
|
+
<summary><b>Toolchain notes & gotchas</b></summary>
|
|
334
474
|
|
|
335
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
344
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
490
|
+
</details>
|
|
361
491
|
|
|
362
|
-
|
|
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
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
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"
|
|
538
|
+
<div align="center">
|
|
539
|
+
<br/>
|
|
540
|
+
<sub><i>ReplicaX — copy the setup, not the code.</i></sub>
|
|
541
|
+
</div>
|