@iamsaroj/replicax 0.0.1
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 +21 -0
- package/README.md +394 -0
- package/dist/index.js +1562 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ReplicaX contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ReplicaX
|
|
4
|
+
|
|
5
|
+
### _Copy the setup, not the code._
|
|
6
|
+
|
|
7
|
+
Extract a project's development environment — tooling config, folder structure, and
|
|
8
|
+
conventions — into a reusable profile, then recreate it in seconds anywhere.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
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.
|
|
23
|
+
|
|
24
|
+
It is **not** a code generator, a project cloner, or a backup tool.
|
|
25
|
+
|
|
26
|
+
## Why
|
|
27
|
+
|
|
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.
|
|
31
|
+
|
|
32
|
+
ReplicaX captures that ritual once and replays it on demand.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
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)
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm install -g @iamsaroj/replicax
|
|
65
|
+
# or
|
|
66
|
+
pnpm add -g @iamsaroj/replicax
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Requires **Node.js 20+**. ReplicaX is a standalone CLI with no external services.
|
|
70
|
+
|
|
71
|
+
## Quick start
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# 1. In an existing, well-configured project:
|
|
75
|
+
cd my-project
|
|
76
|
+
replicax init # → writes a profile to .replicax/
|
|
77
|
+
|
|
78
|
+
# 2. Anywhere the profile lives, scaffold a fresh project:
|
|
79
|
+
replicax create my-new-app # → same setup, none of the code
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> Tip: try `replicax init --dry-run` first to preview exactly what would be captured.
|
|
83
|
+
|
|
84
|
+
## Worked example
|
|
85
|
+
|
|
86
|
+
Starting from a typical Vite + React + TypeScript project:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
my-project/
|
|
90
|
+
├── vite.config.ts
|
|
91
|
+
├── tsconfig.json
|
|
92
|
+
├── tsconfig.node.json
|
|
93
|
+
├── .prettierrc
|
|
94
|
+
├── eslint.config.js
|
|
95
|
+
├── Dockerfile
|
|
96
|
+
├── docker-compose.yml
|
|
97
|
+
├── .github/workflows/ci.yml
|
|
98
|
+
├── .husky/pre-commit
|
|
99
|
+
├── .env # ← secret
|
|
100
|
+
├── package.json # ← incl. runtime deps
|
|
101
|
+
└── src/
|
|
102
|
+
├── components/Button.tsx # ← business code
|
|
103
|
+
├── hooks/
|
|
104
|
+
├── services/UserService.ts # ← business code
|
|
105
|
+
└── pages/
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
replicax init
|
|
110
|
+
replicax create my-new-app --skip-install
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
ReplicaX produces:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
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
|
|
124
|
+
├── .github/workflows/ci.yml
|
|
125
|
+
├── .husky/pre-commit
|
|
126
|
+
├── package.json # name renamed; scripts/devDeps kept, runtime deps dropped
|
|
127
|
+
└── src/
|
|
128
|
+
├── components/ # recreated, but EMPTY
|
|
129
|
+
├── hooks/
|
|
130
|
+
├── services/ # recreated, but EMPTY
|
|
131
|
+
└── pages/
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
No `.env`, no `Button.tsx`, no `UserService.ts`, no `react` runtime dependency — only
|
|
135
|
+
the setup.
|
|
136
|
+
|
|
137
|
+
## Commands
|
|
138
|
+
|
|
139
|
+
### `replicax init`
|
|
140
|
+
|
|
141
|
+
Scan the current project and write a profile to `.replicax/`.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
replicax init --name "react-enterprise" # name the profile
|
|
145
|
+
replicax init --dry-run # preview, write nothing
|
|
146
|
+
replicax init --verbose # list every detected file
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `replicax create <project-name>`
|
|
150
|
+
|
|
151
|
+
Create a new project from a profile. Existing files trigger an interactive
|
|
152
|
+
overwrite/skip prompt (auto-skips when non-interactive).
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
replicax create my-app
|
|
156
|
+
replicax create my-app --profile ./shared/.replicax # use a profile elsewhere
|
|
157
|
+
replicax create my-app --skip-install # don't run the package manager
|
|
158
|
+
replicax create my-app --force # overwrite conflicts, no prompt
|
|
159
|
+
replicax create my-app --dry-run # preview the file plan
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### `replicax sync`
|
|
163
|
+
|
|
164
|
+
Re-scan and update the profile to match the current project.
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
replicax sync # update, print a change summary
|
|
168
|
+
replicax sync --diff # detailed per-file added/changed/removed list
|
|
169
|
+
replicax sync --force # rewrite even if nothing changed
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `replicax inspect`
|
|
173
|
+
|
|
174
|
+
Display the captured configuration and structure.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
replicax inspect
|
|
178
|
+
replicax inspect --json # machine-readable (stdout only)
|
|
179
|
+
replicax inspect --section tooling # profile | tooling | structure | metadata
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```text
|
|
183
|
+
Tooling (14 file(s))
|
|
184
|
+
┌────────────────────────────────┬──────────────────────────┬─────────┬──────────┐
|
|
185
|
+
│ Category │ File │ Variant │ Size │
|
|
186
|
+
├────────────────────────────────┼──────────────────────────┼─────────┼──────────┤
|
|
187
|
+
│ Language & Type Checking │ tsconfig.json │ json │ 226 B │
|
|
188
|
+
│ Build Tools │ vite.config.ts │ ts │ 98 B │
|
|
189
|
+
│ Formatting │ .prettierrc │ other │ 63 B │
|
|
190
|
+
│ … │ … │ … │ … │
|
|
191
|
+
└────────────────────────────────┴──────────────────────────┴─────────┴──────────┘
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### `replicax validate`
|
|
195
|
+
|
|
196
|
+
Check the profile's schema and integrity (SHA-256 checksums + path safety). Exits
|
|
197
|
+
non-zero on failure — handy in CI.
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
replicax validate
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### `replicax export` / `import`
|
|
204
|
+
|
|
205
|
+
Package a profile into a portable archive and adopt it elsewhere.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
replicax export --out ./react-enterprise.tar.gz
|
|
209
|
+
replicax import ./react-enterprise.tar.gz # validates before adopting
|
|
210
|
+
replicax import ./react-enterprise.tar.gz --force # overwrite an existing profile
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
> `--dry-run` is available on every write operation and never touches disk.
|
|
214
|
+
|
|
215
|
+
## What gets captured
|
|
216
|
+
|
|
217
|
+
| Captured ✅ | Left behind ❌ |
|
|
218
|
+
|-----------------------------------------------------|----------------------------------------------------------------|
|
|
219
|
+
| TS/JS configs, ESLint, Prettier | Application source (components, services, controllers) |
|
|
220
|
+
| Vite / Webpack / Rollup / esbuild | Runtime `dependencies` in `package.json` |
|
|
221
|
+
| Tailwind / PostCSS | `.env*`, `*.pem`, `*.key`, certificates |
|
|
222
|
+
| Docker, CI/CD (Actions, GitLab, CircleCI, Jenkins) | `node_modules/`, `dist/`, `build/`, `coverage/`, `.next/`, … |
|
|
223
|
+
| `.editorconfig`, Husky hooks | IDE folders (`.vscode/`, `.idea/`, `.vs/`, `.fleet/`, `.zed/`) |
|
|
224
|
+
| Test configs (Vitest/Jest/Playwright/Cypress) | Anything matched by `.replicaxignore` |
|
|
225
|
+
| Monorepo files, commitlint/lint-staged/release/knip | |
|
|
226
|
+
| Folder hierarchy (directories only) | Folder _contents_ |
|
|
227
|
+
|
|
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`.
|
|
232
|
+
|
|
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.
|
|
235
|
+
|
|
236
|
+
## Security
|
|
237
|
+
|
|
238
|
+
ReplicaX treats secret exclusion as a hard guarantee, not a best effort:
|
|
239
|
+
|
|
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.
|
|
248
|
+
|
|
249
|
+
## `.replicaxignore`
|
|
250
|
+
|
|
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.
|
|
254
|
+
|
|
255
|
+
```gitignore
|
|
256
|
+
# Business logic (folders kept, contents dropped)
|
|
257
|
+
src/services/**
|
|
258
|
+
src/**/*.ts
|
|
259
|
+
|
|
260
|
+
# Extra secrets / noise
|
|
261
|
+
.env
|
|
262
|
+
*.log
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Profile format
|
|
266
|
+
|
|
267
|
+
A profile is five JSON files under `.replicax/`:
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
.replicax/
|
|
271
|
+
├── profile.json # identity & metadata (name, version, timestamps)
|
|
272
|
+
├── tooling.json # every captured config file (verbatim) + the package.json template
|
|
273
|
+
├── structure.json # folder hierarchy (sorted POSIX directory paths)
|
|
274
|
+
├── metadata.json # node version, package manager, framework, language, platform
|
|
275
|
+
└── checksum.json # SHA-256 integrity hashes
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
All five are schema-validated (zod) on load; `validate` additionally re-checks
|
|
279
|
+
checksums and rejects unsafe paths.
|
|
280
|
+
|
|
281
|
+
## How it works
|
|
282
|
+
|
|
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)
|
|
295
|
+
```
|
|
296
|
+
|
|
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**.
|
|
301
|
+
- **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.
|
|
304
|
+
|
|
305
|
+
## Development
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
npm install
|
|
309
|
+
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)
|
|
312
|
+
npm run format # prettier --write .
|
|
313
|
+
npm run dev # tsup --watch
|
|
314
|
+
```
|
|
315
|
+
|
|
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.
|
|
332
|
+
|
|
333
|
+
## Releasing
|
|
334
|
+
|
|
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.
|
|
340
|
+
|
|
341
|
+
**One-time setup:**
|
|
342
|
+
|
|
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.
|
|
351
|
+
|
|
352
|
+
**Cut a release** — bump and push, that's it:
|
|
353
|
+
|
|
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
|
+
```
|
|
359
|
+
|
|
360
|
+
The release gate is "is this version already on npm?", so:
|
|
361
|
+
|
|
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.
|
|
371
|
+
|
|
372
|
+
## FAQ
|
|
373
|
+
|
|
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.
|
|
385
|
+
|
|
386
|
+
**Is it cross-platform?** Yes — Windows (native + WSL), macOS, and Linux.
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT — see [LICENSE](LICENSE).
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
<div align="center"><sub><i>ReplicaX — copy the setup, not the code.</i></sub></div>
|