@edd_remonts/create-hermes-workspace 0.1.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eduardo Inerarte
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,132 @@
1
+ # @edd_remonts/create-hermes-workspace
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@edd_remonts/create-hermes-workspace.svg)](https://www.npmjs.com/package/@edd_remonts/create-hermes-workspace)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
5
+ [![Node ≥ 18](https://img.shields.io/badge/node-%E2%89%A518-brightgreen.svg)](https://nodejs.org)
6
+ [![Docker](https://img.shields.io/badge/docker-required-blue.svg)](https://www.docker.com)
7
+
8
+ > Bootstrap a [Hermes Agent](https://github.com/nousresearch/hermes-agent) workspace with one command. Clones the canonical `create-hermes-workspace` repo, copies `.env.example` → `.env`, and prints what to do next.
9
+
10
+ ## Install
11
+
12
+ You don't install it — you run it. The whole point is a single `npx` invocation.
13
+
14
+ ```bash
15
+ npx @edd_remonts/create-hermes-workspace
16
+ ```
17
+
18
+ The first run downloads the package, executes the CLI, and exits. There's nothing to add to your `package.json` and nothing to remove.
19
+
20
+ ## Usage
21
+
22
+ ```bash
23
+ # Default — creates ./hermes-workspace
24
+ npx @edd_remonts/create-hermes-workspace
25
+
26
+ # Custom folder
27
+ npx @edd_remonts/create-hermes-workspace my-projects
28
+
29
+ # Absolute path
30
+ npx @edd_remonts/create-hermes-workspace /opt/workspaces/hermes
31
+
32
+ # Help
33
+ npx @edd_remonts/create-hermes-workspace --help
34
+
35
+ # Version
36
+ npx @edd_remonts/create-hermes-workspace --version
37
+ ```
38
+
39
+ ### What it does
40
+
41
+ 1. Verifies you have Node 18 or higher.
42
+ 2. Validates the target folder name (POSIX-safe characters only).
43
+ 3. Refuses to overwrite a non-empty folder.
44
+ 4. Shallow-clones [`eddremonts86/create-hermes-workspace`](https://github.com/eddremonts86/create-hermes-workspace) from GitHub.
45
+ 5. Copies the cloned `.env.example` to `.env` so you can start editing.
46
+ 6. Prints a "what to do next" panel pointing you at `docker compose up -d`.
47
+
48
+ No telemetry, no analytics, no network calls beyond the `git clone`.
49
+
50
+ ## Requirements
51
+
52
+ - **Node.js 18 or higher** — to run the CLI itself.
53
+ - **Git** — to clone the workspace repo (`brew install git`, `apt install git`, etc.).
54
+ - **SSH access to GitHub** — the CLI uses `git@github.com:...` so the repo must be reachable over SSH. Run `ssh -T git@github.com` once to confirm. (If you only have HTTPS auth, see [FAQ](#faq).)
55
+ - **Docker** — only required *after* the CLI finishes, to start the workspace container.
56
+
57
+ ## Programmatic API
58
+
59
+ This package is a CLI, not a library. It has no exported JavaScript API. If you need to script workspace creation, run the CLI from your shell:
60
+
61
+ ```bash
62
+ npx --yes @edd_remonts/create-hermes-workspace "$WORKSPACE_NAME"
63
+ ```
64
+
65
+ Exit codes:
66
+
67
+ | Code | Meaning |
68
+ |------|---------|
69
+ | `0` | Success. |
70
+ | `2` | Pre-flight failure (invalid name, target not empty, Node < 18). |
71
+ | `3` | `git` not found on `PATH`. |
72
+ | `4` | `git clone` failed (network, auth, repo missing). |
73
+ | other | Bubbled up from `git clone`. |
74
+
75
+ ## What gets cloned
76
+
77
+ The CLI pulls [`eddremonts86/create-hermes-workspace`](https://github.com/eddremonts86/create-hermes-workspace), which contains:
78
+
79
+ - `Dockerfile` + `docker-compose.yml` — pre-wired for the Hermes agent.
80
+ - `.env.example` — annotated, with only the keys a colleague must set.
81
+ - `AGENTS.md` — the workflow rules (superpowers methodology, 4 hard gates).
82
+ - `Makefile` — `make up`, `make shell`, `make new-project NAME=foo`, `make reset`.
83
+ - `scripts/bootstrap.sh` — non-Docker one-shot installer.
84
+ - `skills/` — a curated subset of reusable skills.
85
+ - `README.md` — the world-class onboarding doc (this is the one to read next).
86
+
87
+ After cloning, **`cd` into the folder and read its README**. That's where the workspace workflow lives.
88
+
89
+ ## FAQ
90
+
91
+ **Q: I have a "Permission denied (publickey)" error.**
92
+ A: The CLI uses SSH. Set up an SSH key on GitHub: https://docs.github.com/en/authentication/connecting-to-github-with-ssh. Or clone the repo manually with HTTPS first, then re-run the CLI.
93
+
94
+ **Q: I already have a folder called `hermes-workspace`.**
95
+ A: The CLI refuses to overwrite a non-empty folder. Either remove it (`rm -rf hermes-workspace`) or pass a different name (`npx @edd_remonts/create-hermes-workspace my-v2-ws`).
96
+
97
+ **Q: Can I run this on Windows?**
98
+ A: Yes — use [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) (Windows Subsystem for Linux). Run the CLI from inside your WSL distribution. Native PowerShell works for the `git clone` but Docker Desktop's WSL2 backend is the supported path for the container.
99
+
100
+ **Q: Why isn't this just `npm install -g`?**
101
+ A: Because you don't want it globally — you want it on-demand, always at the latest version, and never on your `package.json`. `npx` is exactly the right tool for "run this once, then forget about it."
102
+
103
+ **Q: How is this different from `@edd_remonts/create-edd-app`?**
104
+ A: They solve different problems:
105
+ - `@edd_remonts/create-hermes-workspace` (this package) → **the dev environment**: agent, skills, Dockerfile, env config. One per machine.
106
+ - `@edd_remonts/create-edd-app` → **a single application**: TanStack Start + Drizzle + shadcn stack. One per project.
107
+
108
+ You'll usually run this once, then run `create-edd-app` many times inside it.
109
+
110
+ **Q: My .env was overwritten!**
111
+ A: The CLI only copies `.env.example` → `.env` if `.env` doesn't already exist (or if the target folder was just created by the clone). It will not overwrite an existing `.env`. If you want to re-copy, `cp .env.example .env` manually.
112
+
113
+ **Q: How do I publish a new version?**
114
+ A: Inside this package's repo: `npm version patch` (or `minor` / `major`), then `npm publish --access public`. The package's `scripts/publish.sh` (in the workspace repo, not here) wraps that with a token-prompt dance.
115
+
116
+ **Q: Is telemetry collected?**
117
+ A: No. The CLI makes exactly one network call: `git clone`. No analytics, no phone-home, no error reporting.
118
+
119
+ ## See also
120
+
121
+ - [`eddremonts86/create-hermes-workspace`](https://github.com/eddremonts86/create-hermes-workspace) — the repo this CLI clones. **Read its README after running the CLI.**
122
+ - [`@edd_remonts/create-edd-app`](https://www.npmjs.com/package/@edd_remonts/create-edd-app) — bootstrap a new app from the edd-app-template.
123
+ - [`nousresearch/hermes-agent`](https://github.com/nousresearch/hermes-agent) — the underlying agent runtime.
124
+ - [`eddremonts86/edd-app-template`](https://github.com/eddremonts86/edd-app-template) — the default app scaffold used inside a workspace.
125
+
126
+ ## License
127
+
128
+ MIT © 2026 Eduardo Inerarte. See [LICENSE](./LICENSE) for the full text.
129
+
130
+ ## Contributing
131
+
132
+ Issues and PRs welcome at https://github.com/eddremonts86/create-hermes-workspace/issues.
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ // create-hermes-workspace — bootstrap a Hermes Agent workspace with one command.
3
+ // Tests pass CHW_FAKE_GIT to avoid real network access in CI.
4
+ import { spawnSync } from 'node:child_process';
5
+ import { existsSync, mkdirSync, copyFileSync, statSync, writeFileSync, chmodSync, readFileSync, readdirSync } from 'node:fs';
6
+ import { join, resolve, isAbsolute } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const __dirname = fileURLToPath(new URL('.', import.meta.url));
10
+ const PKG_PATH = join(__dirname, '..', 'package.json');
11
+ const PKG = JSON.parse(readFileSync(PKG_PATH, 'utf8'));
12
+ const REPO_URL = PKG.repository.url.replace(/^git\+/, '').replace(/\.git$/, '') + '.git';
13
+
14
+ // ---- arg parsing -----------------------------------------------------------
15
+ const args = process.argv.slice(2);
16
+ if (args.includes('--help') || args.includes('-h')) {
17
+ printHelp();
18
+ process.exit(0);
19
+ }
20
+ if (args.includes('--version') || args.includes('-V')) {
21
+ process.stdout.write(`${PKG.version}\n`);
22
+ process.exit(0);
23
+ }
24
+ const targetArg = args.find((a) => !a.startsWith('-'));
25
+ const target = resolve(process.cwd(), targetArg || 'hermes-workspace');
26
+
27
+ // ---- preconditions --------------------------------------------------------
28
+ const major = parseInt(process.versions.node.split('.')[0], 10);
29
+ if (major < 18) {
30
+ process.stderr.write(`\u2716 Node 18 or higher required. You are running ${process.versions.node}.\n`);
31
+ process.exit(2);
32
+ }
33
+ if (!/^[A-Za-z0-9._\-/]+$/.test(target)) {
34
+ process.stderr.write(`\u2716 Invalid target folder: ${target}\n`);
35
+ process.exit(2);
36
+ }
37
+ if (existsSync(target)) {
38
+ const st = statSync(target);
39
+ if (st.isDirectory()) {
40
+ // Allow if empty
41
+ if (readdirSync(target).length > 0) {
42
+ process.stderr.write(`\u2716 Target folder already exists and is not empty: ${target}\n`);
43
+ process.stderr.write(` Re-run with a different name, or remove it first: rm -rf ${target}\n`);
44
+ process.exit(2);
45
+ }
46
+ } else {
47
+ process.stderr.write(`\u2716 Target exists and is not a directory: ${target}\n`);
48
+ process.exit(2);
49
+ }
50
+ }
51
+
52
+ // ---- clone -----------------------------------------------------------------
53
+ let clone;
54
+ if (process.env.CHW_FAKE_GIT) {
55
+ // Test mode: simulate clone by mkdir + writing a fake .env.example
56
+ clone = { status: 0, stdout: '', stderr: '' };
57
+ mkdirSync(target, { recursive: true });
58
+ writeFileSync(join(target, '.env.example'), '# test fixture\nFOO=bar\n');
59
+ writeFileSync(join(target, 'README.md'), '# fixture\n');
60
+ } else {
61
+ const git = process.env.CHW_GIT_BIN || 'git';
62
+ // Sanity check: git is on PATH
63
+ const probe = spawnSync(git, ['--version'], { stdio: 'pipe' });
64
+ if (probe.status !== 0) {
65
+ process.stderr.write(`\u2716 git is required but was not found on PATH.\n`);
66
+ process.stderr.write(` Install git: https://git-scm.com/downloads\n`);
67
+ process.exit(3);
68
+ }
69
+ process.stdout.write(`\u2937 Cloning ${REPO_URL} into ${target}\u2026\n`);
70
+ clone = spawnSync(git, ['clone', '--depth', '1', REPO_URL, target], {
71
+ stdio: ['ignore', 'inherit', 'inherit'],
72
+ });
73
+ if (clone.status !== 0) {
74
+ process.stderr.write(`\u2716 git clone failed (exit ${clone.status}).\n`);
75
+ process.exit(clone.status || 4);
76
+ }
77
+ }
78
+
79
+ // ---- .env.example -> .env --------------------------------------------------
80
+ try {
81
+ const envExample = join(target, '.env.example');
82
+ if (existsSync(envExample)) {
83
+ copyFileSync(envExample, join(target, '.env'));
84
+ process.stdout.write(`\u2713 Created .env from .env.example \u2014 open it and fill in your keys.\n`);
85
+ }
86
+ } catch (e) {
87
+ // Warn but don't abort
88
+ process.stderr.write(`\u26a0 Could not copy .env.example to .env: ${e.message}\n`);
89
+ process.stderr.write(` You can copy it manually: cp .env.example .env\n`);
90
+ }
91
+
92
+ // ---- success panel ---------------------------------------------------------
93
+ process.stdout.write(`\n\u2705 Hermes workspace ready in ${target}\n\n`);
94
+ process.stdout.write(` Next steps:\n`);
95
+ process.stdout.write(` 1. cd ${target}\n`);
96
+ process.stdout.write(` 2. Open .env and fill in your AI provider keys (MINIMAX_API_KEY, etc.)\n`);
97
+ process.stdout.write(` 3. docker compose up -d # start the container\n`);
98
+ process.stdout.write(` 4. docker compose exec hermes bash # open a shell inside\n`);
99
+ process.stdout.write(` 5. Inside the container: hermes chat # talk to the agent\n\n`);
100
+ process.stdout.write(` Docs: https://github.com/eddremonts86/create-hermes-workspace\n`);
101
+ process.stdout.write(` Issues: https://github.com/eddremonts86/create-hermes-workspace/issues\n\n`);
102
+ process.exit(0);
103
+
104
+ function printHelp() {
105
+ process.stdout.write(`create-hermes-workspace v${PKG.version}\n\n`);
106
+ process.stdout.write(`Usage: create-hermes-workspace [folder] [options]\n\n`);
107
+ process.stdout.write(`Bootstrap a Hermes Agent workspace by cloning the canonical\n`);
108
+ process.stdout.write(`create-hermes-workspace repo into <folder> (default: ./hermes-workspace).\n\n`);
109
+ process.stdout.write(`Arguments:\n`);
110
+ process.stdout.write(` [folder] Target folder. Relative paths resolve from $PWD.\n`);
111
+ process.stdout.write(` Defaults to ./hermes-workspace.\n\n`);
112
+ process.stdout.write(`Options:\n`);
113
+ process.stdout.write(` -h, --help Show this help.\n`);
114
+ process.stdout.write(` -V, --version Print version and exit.\n\n`);
115
+ process.stdout.write(`Examples:\n`);
116
+ process.stdout.write(` $ create-hermes-workspace\n`);
117
+ process.stdout.write(` $ create-hermes-workspace my-ws\n`);
118
+ process.stdout.write(` $ create-hermes-workspace /tmp/hermes-ws\n\n`);
119
+ process.stdout.write(`Repo: https://github.com/eddremonts86/create-hermes-workspace\n`);
120
+ process.stdout.write(`npm: https://www.npmjs.com/package/@edd_remonts/create-hermes-workspace\n`);
121
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@edd_remonts/create-hermes-workspace",
3
+ "version": "0.1.0",
4
+ "description": "Bootstrap a Hermes Agent workspace with one command.",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-hermes-workspace": "bin/create-hermes-workspace.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "test": "node --test 'test/**/*.test.js'"
16
+ },
17
+ "engines": {
18
+ "node": ">=18"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/eddremonts86/create-hermes-workspace.git"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/eddremonts86/create-hermes-workspace/issues"
26
+ },
27
+ "homepage": "https://github.com/eddremonts86/create-hermes-workspace#readme",
28
+ "keywords": [
29
+ "hermes",
30
+ "hermes-agent",
31
+ "workspace",
32
+ "scaffold",
33
+ "create",
34
+ "cli"
35
+ ],
36
+ "author": "Eduardo Inerarte <eddremonts86@gmail.com>",
37
+ "license": "MIT",
38
+ "publishConfig": {
39
+ "registry": "https://registry.npmjs.org/",
40
+ "access": "public"
41
+ }
42
+ }