workspace-manager-cli
v1.2.2
Published
Cross-platform CLI to assemble project workspaces from shared core boilerplate plus custom folders
Maintainers
Readme
workspace-manager-cli
A cross-platform Node/TypeScript CLI that assembles a project workspace from a shared core boilerplate plus a project's custom folder.
Features
- Smart caching: Clones core repositories to local cache (
.wmc-cache/) - Update notifications: Shows when new commits are available with
wmc status - Overlay system: Layer your custom code on top of core boilerplate
- Cross-platform: Pure Node.js APIs, no shell dependencies
- Automation-friendly:
--jsonflag for machine-readable output
Quick Start
# Initialize cache and build workspace
wmc init --build
# Skip npm install after build
wmc init --build --no-install
# If not installed globally, use: npx workspace-manager-cli init --buildInstallation
Global Installation
npm install -g workspace-manager-cliConfiguration
Run wmc init (or wmc init -i or wmc init --interactive) in a folder without a config and the CLI will generate workspace.config.json for you, prompting for project type plus core/base URLs. It also writes a minimal .gitignore covering the generated workspace and cache.
Example of a generated workspace.config.json (base-core-custom):
{
"projectType": "base-core-custom",
"base": {
"name": "base",
"url": "https://github.com/example/base.git",
"ref": "main"
},
"core": {
"name": "core",
"url": "https://github.com/example/core.git",
"ref": "main"
},
"custom": {
"path": "custom"
},
"install": {
"command": "npm install"
}
}Configuration Options
| Field | Type | Default | Description |
| ----------------- | -------- | --------------- | ---------------------------------------------------------------------------------------------------------------- |
| projectType | enum | required | One of core-custom, base-core, base-core-custom; determines which repos are required and how they overlay. |
| base.name | string | _required* | Base repo name (cache dir). Required when the project type includes base. |
| base.url | string | _required* | Git URL of base repo. |
| base.ref | string | "main" | Branch/tag/commit for base. |
| base.from | string | n/a | Set by wmc init to the friendly branch/tag if the input ref was a hash; otherwise matches the ref used. |
| core.name | string | required | Core repo name (cache dir). |
| core.url | string | _required** | Git URL of core repo (required for core-custom and base-core-custom; omit for base-core). |
| core.path | string | "core" | Local path to core folder (only for base-core type). |
| core.ref | string | "main" | Branch/tag/commit for core (only used when core.url is set). |
| core.from | string | n/a | Set by wmc init to the friendly branch/tag if the input ref was a hash; otherwise matches the ref used. |
| (fixed) workspace | string | "workspace" | The workspace directory is fixed to ./workspace and is not configurable |
| custom.path | string | "custom" | Path to your custom code directory |
| install.command | string | "npm install" | Command to run inside workspace after copying (skipped with --no-install) |
| excludes | string[] | [] | Additional glob patterns to exclude when copying |
* Required when the selected projectType includes a base repository.
** Required for core-custom and base-core-custom; omit for base-core (use core.path instead).
Excludes & dry-run visibility 🛑
- Use
excludesto skip copying files or directories into the assembledworkspacefolder (./workspace). - Examples:
excludes: ["**/*.log", "dist/**", "node_modules/**", "**/*.tmp"]will prevent matching files from being copied. - Use
--dry-run(or--dry-runoption) to preview actions — the build will add an actionExcludes: <patterns>and logEffective excludes: ...so you can verify which globs will be applied before any copying occurs.
Project Types
core-custom: Remote core + local custom overlay (no base). Core is cached in.wmc-cache/<core>and copied toworkspace; custom overlays intoworkspace/src/core/custom.base-core: Remote base + local core folder. Base comes from cache; core is taken from a local path; custom is optional.base-core-custom: Remote base + remote core + local custom. Both base and core are cached; core replaces base's core area; custom overlays on top.
Commands
init
Initialize repositories (core/base) by cloning to local cache, optionally build.
wmc init [options]Options:
--ref <ref>: Override core ref (branch/tag/commit)--base-ref <ref>: Override base ref--core-latest: Checkout latest commit on core branch--base-latest: Checkout latest commit on base branch--interactive: Pick refs interactively (non-JSON mode)--build: Build workspace after initialization--no-install: Skip runningnpm installinsideworkspace(only applies when--buildis used)
What it does:
- Clones configured repos to
.wmc-cache/<name>(behavior depends on project type):core-custom: Clones core onlybase-core: Clones base only (core is local)base-core-custom: Clones both base and core
- Checks out the chosen refs
- Persists the resolved hashes/refs to
workspace.config.json- If you pass a commit hash,
wmcwill try to resolve a friendly branch/tag and store it inbase.from/core.from; otherwise it stores the ref you provided.
- If you pass a commit hash,
- (Optional) Builds the workspace when
--buildis provided
build (alias: sync)
Build the workspace by assembling repositories and overlaying custom code based on project type.
wmc build [options]Options:
--no-install: Skip runningnpm installinsideworkspace--dry-run: Preview what will happen without actually making any changes. Useful for testing your config before committing to the build.Example:
wmc build --dry-runWhat happens:
- Reads your config and checks what files will be copied/excluded
- Logs each action it would perform (copy, overlay, install, etc.)
- Does NOT create or modify any files
- Exits without touching
workspace/or runningnpm install
Real-world scenario: You just updated your
excludeslist and want to verify the right files will be copied before actually running the build. Runwmc build --dry-runfirst to see the preview, then if it looks good, runwmc buildto execute it.
What it does (varies by project type):
core-custom:- Copy core from
.wmc-cache/<core>toworkspace - Overlay
custom/intoworkspace/src/core/custom - Run
install.commandinworkspace
- Copy core from
base-core:- Copy base from
.wmc-cache/<base>toworkspace - Copy local core from
config.core.pathtoworkspace/src/core - Run
install.commandinworkspace
- Copy base from
base-core-custom:- Copy base from
.wmc-cache/<base>toworkspace - Copy core from
.wmc-cache/<core>toworkspace/src/core(replacing base's core) - Overlay
custom/intoworkspace/src/core/custom - Run
install.commandinworkspace
- Copy base from
status
Print current status of repositories and directories based on project type.
wmc statusShows (varies by project type):
core-custom:- Core repo cache status (cloned, commit, branch)
- Core ref/
from(shows friendly branch/tag if initialized with a hash) - Core updates available (if any)
- Custom directory uncommitted changes
base-core:- Base repo cache status (cloned, commit, branch)
- Base ref/
from(shows friendly branch/tag if initialized with a hash) - Base updates available (if any)
- Local core directory location
- Custom directory uncommitted changes (if applicable)
base-core-custom:- Base repo cache status (cloned, commit, branch)
- Base ref/
from(shows friendly branch/tag if initialized with a hash) - Base updates available (if any)
- Core repo cache status (cloned, commit, branch)
- Core ref/
from(shows friendly branch/tag if initialized with a hash) - Core updates available (if any)
- Custom directory uncommitted changes
Global Options
| Option | Description |
| ----------- | ---------------------------------------------------- |
| --json | Output machine-readable JSON (useful for automation) |
| --version | Show version number |
| --help | Show help |
What to Commit
✅ Commit these:
workspace.config.jsoncustom/directory (your custom code)
❌ Don't commit:
workspace/(generated).wmc-cache/(local cache)workspace/node_modules/(dependencies)
How It Works
Core repository is cloned to a local cache directory and reused across builds:
- Cache location:
.wmc-cache/<name>(in project root) - Fast builds: Reuses cached repositories, only fetches when needed
- Update notifications:
wmc statusshows when new commits are available
Workflow Diagram
graph TD
A["wmc init --build"] --> B{Project Type?}
B -->|core-custom| C["Clone core to<br/>.wmc-cache/"]
B -->|base-core| D["Clone base to<br/>.wmc-cache/"]
B -->|base-core-custom| E["Clone base & core<br/>to .wmc-cache/"]
C --> F["Copy core →<br/>workspace/"]
D --> G["Copy base →<br/>workspace/"]
E --> H["Copy base →<br/>workspace/"]
F --> I["Overlay custom/ →<br/>workspace/src/custom"]
G --> J["Overlay local core →<br/>workspace/src/core"]
H --> K["Copy ./wmc-cache/{core}/src/core →<br/>workspace/src/core"]
I --> L["Run npm install"]
J --> L
K --> M["Overlay custom/ →<br/>workspace/src/core/custom"]
M --> L
L --> N["✅ Workspace Ready"]Project Structure:
┌─────────────────────────────────────────────────────────────────┐
│ Your Project │
├─────────────────────────────────────────────────────────────────┤
│ workspace.config.json │
│ custom/ │
│ .wmc-cache/ ← Git repos cloned here │
│ └── CORE-Project/ │
│ ├── .git/ │
│ └── src/ │
│ workspace/ (generated) ← Files copied here │
└─────────────────────────────────────────────────────────────────┘Workflow:
# Developer A initializes and builds
wmc init --build # Clones to local .wmc-cache and builds workspace
# Developer A commits their work
git add custom/ workspace.config.json
git commit -m "Add feature X"
git push
# Developer B pulls and builds
git pull
wmc init --build # Populates their own .wmc-cache and rebuilds workspace
# Note: .wmc-cache is local per developer, not shared
# Check for updates
wmc status # Shows if new commits are available
wmc init --core-latest --build # Fetch latest core, then rebuildNote on sharing:
- Each developer has their own
.wmc-cache/(not committed to git) - Developers share:
workspace.config.json,custom/folder, andcore/folder (if local) - After
git pull, runwmc init --buildto populate your local cache and rebuild workspace
Automation (not tested)
CI/CD Pipeline Example
# GitHub Actions example
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Initialize core
run: wmc init --json
- name: Build workspace
run: wmc build --json
- name: Build project
run: cd workspace && npm run buildJSON Output
Use --json for machine-readable output:
wmc status --json # or: npx workspace-manager-cli status --json{
"command": "status",
"config": { ... },
"status": {
"coreInitialized": true,
"coreCommit": "abc123...",
"customHasChanges": false
}
}Troubleshooting
"Could not find workspace.config.json"
Make sure you're running the CLI from a directory that has workspace.config.json or one of its parent directories.
"Core repository not found"
Run wmc init (or npx workspace-manager-cli init if not installed globally).
"Failed to checkout ref"
Ensure the ref (branch/tag/commit) exists in the core repository. Try:
wmc init --ref main --build # or: npx workspace-manager-cli init --ref main --buildBuild fails with permission errors
On Windows, ensure no processes are using files in the workspace directory.
License
MIT
