workspace-manager-cli
v1.3.5
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": "[email protected]:example/base.git",
"ref": "main"
},
"core": {
"name": "core",
"url": "[email protected]: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.
"Would clobber existing tag"
The commit hash is different for the same tag. Remove the .wmc-cache folder and run wmc init -i.
License
MIT
