create-egregore 0.1.0 → 0.1.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.
Files changed (3) hide show
  1. package/lib/auth.js +15 -15
  2. package/lib/setup.js +54 -35
  3. package/package.json +1 -1
package/lib/auth.js CHANGED
@@ -6,7 +6,7 @@
6
6
  const https = require("node:https");
7
7
 
8
8
  const CLIENT_ID = "Ov23lizB4nYEeIRsHTdb";
9
- const SCOPE = "repo,read:org";
9
+ const SCOPE = "repo,admin:org";
10
10
 
11
11
  function post(url, body) {
12
12
  return new Promise((resolve, reject) => {
@@ -46,24 +46,24 @@ function sleep(ms) {
46
46
  }
47
47
 
48
48
  function openBrowser(url) {
49
- const { exec } = require("node:child_process");
50
- const cmd =
51
- process.platform === "darwin"
52
- ? `open "${url}"`
53
- : process.platform === "win32"
54
- ? `start "${url}"`
55
- : `xdg-open "${url}"`;
56
- exec(cmd, () => {});
49
+ const { execFile } = require("node:child_process");
50
+ if (process.platform === "darwin") {
51
+ execFile("open", [url], () => {});
52
+ } else if (process.platform === "win32") {
53
+ execFile("cmd", ["/c", "start", "", url], () => {});
54
+ } else {
55
+ execFile("xdg-open", [url], () => {});
56
+ }
57
57
  }
58
58
 
59
59
  function copyToClipboard(text) {
60
- const { exec } = require("node:child_process");
61
- if (process.platform === "darwin") {
62
- exec(`printf '%s' '${text}' | pbcopy`, () => {});
63
- return true;
64
- }
60
+ const { execSync } = require("node:child_process");
65
61
  try {
66
- exec(`printf '%s' '${text}' | xclip -selection clipboard`, () => {});
62
+ if (process.platform === "darwin") {
63
+ execSync("pbcopy", { input: text, stdio: ["pipe", "ignore", "ignore"] });
64
+ return true;
65
+ }
66
+ execSync("xclip -selection clipboard", { input: text, stdio: ["pipe", "ignore", "ignore"] });
67
67
  return true;
68
68
  } catch {
69
69
  return false;
package/lib/setup.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Zero dependencies — uses node:child_process, node:fs, node:path, node:os.
4
4
  */
5
5
 
6
- const { execSync } = require("node:child_process");
6
+ const { execSync, execFileSync } = require("node:child_process");
7
7
  const fs = require("node:fs");
8
8
  const path = require("node:path");
9
9
  const os = require("node:os");
@@ -20,10 +20,11 @@ function run(cmd, opts = {}) {
20
20
  * @param {string} targetDir - where to install (default: cwd)
21
21
  */
22
22
  async function install(data, ui, targetDir) {
23
- const { fork_url, memory_url, github_token, org_name, github_org, slug } = data;
23
+ const { fork_url, memory_url, github_token, org_name, github_org, slug, api_key } = data;
24
24
  const base = targetDir || process.cwd();
25
25
 
26
- const egregoreDir = path.join(base, "egregore");
26
+ const dirSlug = (github_org || slug || "egregore").toLowerCase();
27
+ const egregoreDir = path.join(base, `egregore-${dirSlug}`);
27
28
  const memoryDirName = memory_url
28
29
  .split("/")
29
30
  .pop()
@@ -41,7 +42,7 @@ async function install(data, ui, targetDir) {
41
42
  ui.warn("egregore/ already exists — pulling latest");
42
43
  run("git pull", { cwd: egregoreDir });
43
44
  } else {
44
- run(`git clone "${fork_url}" "${egregoreDir}"`);
45
+ execFileSync("git", ["clone", fork_url, egregoreDir], { stdio: "pipe", encoding: "utf-8", timeout: 60000 });
45
46
  }
46
47
  ui.success("Cloned egregore");
47
48
 
@@ -51,7 +52,7 @@ async function install(data, ui, targetDir) {
51
52
  ui.warn(`${memoryDirName}/ already exists — pulling latest`);
52
53
  run("git pull", { cwd: memoryDir });
53
54
  } else {
54
- run(`git clone "${memory_url}" "${memoryDir}"`);
55
+ execFileSync("git", ["clone", memory_url, memoryDir], { stdio: "pipe", encoding: "utf-8", timeout: 60000 });
55
56
  }
56
57
  ui.success("Cloned memory");
57
58
 
@@ -66,24 +67,26 @@ async function install(data, ui, targetDir) {
66
67
  }
67
68
  ui.success("Linked");
68
69
 
69
- // 4. Write .env
70
+ // 4. Write .env (secrets only — never committed to git)
70
71
  ui.step(4, totalSteps, "Writing credentials...");
71
72
  const envPath = path.join(egregoreDir, ".env");
72
- const envContent = `GITHUB_TOKEN=${github_token}\n`;
73
- fs.writeFileSync(envPath, envContent, { mode: 0o600 });
73
+ const envLines = [`GITHUB_TOKEN=${github_token}`];
74
+ if (api_key) envLines.push(`EGREGORE_API_KEY=${api_key}`);
75
+ fs.writeFileSync(envPath, envLines.join("\n") + "\n", { mode: 0o600 });
74
76
  ui.success("Credentials saved");
75
77
 
76
- // 5. Shell alias
77
- ui.step(5, totalSteps, "Setting up launch command...");
78
- setupAlias(egregoreDir, ui);
78
+ // 5. Register instance + shell alias
79
+ ui.step(5, totalSteps, "Registering instance...");
80
+ registerInstance(dirSlug, org_name, egregoreDir);
81
+ installShellAlias(egregoreDir, ui);
79
82
 
80
83
  // Done
81
84
  console.log("");
82
85
  ui.success(`Egregore is ready for ${ui.bold(org_name)}`);
83
86
  console.log("");
84
87
  ui.info(`Your workspace:`);
85
- ui.info(` ${ui.cyan("./egregore/")} — Your Egregore instance`);
86
- ui.info(` ${ui.cyan(`./${memoryDirName}/`)} — Shared knowledge`);
88
+ ui.info(` ${ui.cyan(`./egregore-${dirSlug}/`)} — Your Egregore instance`);
89
+ ui.info(` ${ui.cyan(`./${memoryDirName}/`)} — Shared knowledge`);
87
90
  console.log("");
88
91
  ui.info(`Next: type ${ui.bold("egregore")} in any terminal to start.`);
89
92
  console.log("");
@@ -91,7 +94,7 @@ async function install(data, ui, targetDir) {
91
94
 
92
95
  function configureGitCredentials(token) {
93
96
  try {
94
- run("git config --global credential.helper store");
97
+ run("git config credential.helper store");
95
98
  const credentialInput = `protocol=https\nhost=github.com\nusername=x-access-token\npassword=${token}\n`;
96
99
  execSync("git credential-store store", {
97
100
  input: credentialInput,
@@ -103,31 +106,47 @@ function configureGitCredentials(token) {
103
106
  }
104
107
  }
105
108
 
106
- function setupAlias(egregoreDir, ui) {
107
- const profiles = [
108
- path.join(os.homedir(), ".zshrc"),
109
- path.join(os.homedir(), ".bashrc"),
110
- path.join(os.homedir(), ".bash_profile"),
111
- ];
112
-
113
- const profile = profiles.find((p) => fs.existsSync(p));
114
- if (!profile) {
115
- ui.warn("No shell profile found — add this to your shell config:");
116
- ui.info(` alias egregore='cd "${egregoreDir}" && claude start'`);
117
- return;
109
+ function registerInstance(slug, name, egregoreDir) {
110
+ const registryDir = path.join(os.homedir(), ".egregore");
111
+ const registryFile = path.join(registryDir, "instances.json");
112
+
113
+ if (!fs.existsSync(registryDir)) {
114
+ fs.mkdirSync(registryDir, { recursive: true });
115
+ }
116
+
117
+ let instances = [];
118
+ if (fs.existsSync(registryFile)) {
119
+ try {
120
+ instances = JSON.parse(fs.readFileSync(registryFile, "utf-8"));
121
+ } catch {
122
+ instances = [];
123
+ }
118
124
  }
119
125
 
120
- const existing = fs.readFileSync(profile, "utf-8");
121
- // Remove old alias
122
- const cleaned = existing
123
- .split("\n")
124
- .filter((line) => !line.includes("alias egregore=") && !line.match(/^# Egregore$/))
125
- .join("\n");
126
+ const entry = { slug, name, path: egregoreDir };
127
+ // Dedup by path (not slug) so multiple instances from the same org can coexist
128
+ const idx = instances.findIndex((i) => i.path === egregoreDir);
129
+ if (idx >= 0) {
130
+ instances[idx] = entry;
131
+ } else {
132
+ instances.push(entry);
133
+ }
126
134
 
127
- const aliasBlock = `\n# Egregore\nalias egregore='cd "${egregoreDir}" && claude start'\n`;
128
- fs.writeFileSync(profile, cleaned + aliasBlock);
135
+ fs.writeFileSync(registryFile, JSON.stringify(instances, null, 2) + "\n");
136
+ }
129
137
 
130
- ui.success(`Added ${ui.dim("egregore")} alias to ${path.basename(profile)}`);
138
+ function installShellAlias(egregoreDir, ui) {
139
+ const script = path.join(egregoreDir, "bin", "ensure-shell-function.sh");
140
+ if (!fs.existsSync(script)) {
141
+ ui.warn("Shell alias script not found — add alias manually.");
142
+ return;
143
+ }
144
+ try {
145
+ execSync(`bash "${script}"`, { stdio: "pipe", encoding: "utf-8", timeout: 10000 });
146
+ ui.success(`Installed ${ui.dim("egregore")} command`);
147
+ } catch {
148
+ ui.warn("Could not install shell alias — add it manually.");
149
+ }
131
150
  }
132
151
 
133
152
  module.exports = { install };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Set up Egregore for your team in one command",
5
5
  "license": "MIT",
6
6
  "bin": {