setup-cc-room 0.2.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/dist/chunk-5NTML4PF.js +78 -0
- package/dist/chunk-GWZOELT5.js +111 -0
- package/dist/chunk-NJES6PZ3.js +165 -0
- package/dist/chunk-QK2ZG445.js +105 -0
- package/dist/chunk-QOXK3LB2.js +108 -0
- package/dist/chunk-R5BAC4BK.js +22 -0
- package/dist/chunk-UWFC4FU6.js +129 -0
- package/dist/chunk-WCEABGOA.js +10 -0
- package/dist/chunk-XFCYRKG6.js +117 -0
- package/dist/daemon-resolver.d.ts +8 -0
- package/dist/daemon-resolver.js +8 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +57 -0
- package/dist/installer.d.ts +3 -0
- package/dist/installer.js +10 -0
- package/dist/paths.d.ts +4 -0
- package/dist/paths.js +6 -0
- package/dist/register-service.d.ts +3 -0
- package/dist/register-service.js +7 -0
- package/dist/settings-merger.d.ts +3 -0
- package/dist/settings-merger.js +6 -0
- package/dist/validators.d.ts +12 -0
- package/dist/validators.js +8 -0
- package/package.json +35 -0
- package/vendor/commands/room/private.md +75 -0
- package/vendor/commands/room/room.md +475 -0
- package/vendor/commands/room/show.md +149 -0
- package/vendor/daemon/dist/index.js +53984 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// src/settings-merger.ts
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, copyFileSync, mkdirSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
var SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
6
|
+
var CC_ROOM_HOOKS = {
|
|
7
|
+
UserPromptSubmit: [
|
|
8
|
+
{
|
|
9
|
+
hooks: [
|
|
10
|
+
{
|
|
11
|
+
type: "command",
|
|
12
|
+
command: "cc-room-daemon hook user-prompt-submit"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
PostToolUse: [
|
|
18
|
+
{
|
|
19
|
+
matcher: "Write|Edit",
|
|
20
|
+
hooks: [
|
|
21
|
+
{
|
|
22
|
+
type: "command",
|
|
23
|
+
command: "cc-room-daemon hook post-tool-use"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
Stop: [
|
|
29
|
+
{
|
|
30
|
+
hooks: [
|
|
31
|
+
{
|
|
32
|
+
type: "command",
|
|
33
|
+
command: "cc-room-daemon hook session-stop"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
var CC_ROOM_MCP = {
|
|
40
|
+
"cc-room": {
|
|
41
|
+
type: "stdio",
|
|
42
|
+
command: "cc-room-daemon",
|
|
43
|
+
args: ["mcp"]
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
function mergeSettings() {
|
|
47
|
+
let settings = {};
|
|
48
|
+
mkdirSync(join(homedir(), ".claude"), { recursive: true });
|
|
49
|
+
if (existsSync(SETTINGS_PATH)) {
|
|
50
|
+
try {
|
|
51
|
+
settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
|
|
52
|
+
} catch {
|
|
53
|
+
console.log(" \x1B[33m\u26A0 settings.json \u306E\u30D1\u30FC\u30B9\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u3092\u4F5C\u6210\u3057\u3066\u4E0A\u66F8\u304D\u3057\u307E\u3059\u3002\x1B[0m");
|
|
54
|
+
copyFileSync(SETTINGS_PATH, SETTINGS_PATH + ".backup");
|
|
55
|
+
settings = {};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const existingHooks = settings.hooks ?? {};
|
|
59
|
+
const mergedHooks = { ...existingHooks };
|
|
60
|
+
for (const [event, newEntries] of Object.entries(CC_ROOM_HOOKS)) {
|
|
61
|
+
const existing = mergedHooks[event] ?? [];
|
|
62
|
+
const filtered = existing.filter((e) => {
|
|
63
|
+
const entry = e;
|
|
64
|
+
return !entry.hooks?.some((h) => h.command?.startsWith("cc-room-daemon hook"));
|
|
65
|
+
});
|
|
66
|
+
mergedHooks[event] = [...filtered, ...newEntries];
|
|
67
|
+
}
|
|
68
|
+
const existingMcp = settings.mcpServers ?? {};
|
|
69
|
+
const mergedMcp = { ...existingMcp, ...CC_ROOM_MCP };
|
|
70
|
+
settings.hooks = mergedHooks;
|
|
71
|
+
settings.mcpServers = mergedMcp;
|
|
72
|
+
writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + "\n", { mode: 420 });
|
|
73
|
+
console.log(` ${SETTINGS_PATH} \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export {
|
|
77
|
+
mergeSettings
|
|
78
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
registerService
|
|
3
|
+
} from "./chunk-XFCYRKG6.js";
|
|
4
|
+
import {
|
|
5
|
+
mergeSettings
|
|
6
|
+
} from "./chunk-5NTML4PF.js";
|
|
7
|
+
|
|
8
|
+
// src/installer.ts
|
|
9
|
+
import {
|
|
10
|
+
mkdirSync,
|
|
11
|
+
writeFileSync,
|
|
12
|
+
existsSync,
|
|
13
|
+
copyFileSync,
|
|
14
|
+
chmodSync,
|
|
15
|
+
unlinkSync
|
|
16
|
+
} from "fs";
|
|
17
|
+
import { join, dirname } from "path";
|
|
18
|
+
import { homedir } from "os";
|
|
19
|
+
import { execFileSync, spawnSync } from "child_process";
|
|
20
|
+
import { fileURLToPath } from "url";
|
|
21
|
+
import { stringify } from "yaml";
|
|
22
|
+
var CC_ROOM_DIR = join(homedir(), ".cc-room");
|
|
23
|
+
var BIN_DIR = join(CC_ROOM_DIR, "bin");
|
|
24
|
+
var CONFIG_PATH = join(CC_ROOM_DIR, "config.yaml");
|
|
25
|
+
var COMMANDS_DIR = join(homedir(), ".claude", "commands");
|
|
26
|
+
var THIS_DIR = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
function getGitUserName() {
|
|
28
|
+
try {
|
|
29
|
+
return execFileSync("git", ["config", "user.name"], { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
30
|
+
} catch {
|
|
31
|
+
return "unknown";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function findDaemonBin() {
|
|
35
|
+
const candidates = [
|
|
36
|
+
join(THIS_DIR, "..", "vendor", "daemon", "dist", "index.js"),
|
|
37
|
+
join(THIS_DIR, "..", "..", "daemon", "dist", "index.js"),
|
|
38
|
+
join(THIS_DIR, "..", "..", "..", "node_modules", "@cc-room", "daemon", "dist", "index.js")
|
|
39
|
+
];
|
|
40
|
+
for (const c of candidates) {
|
|
41
|
+
if (existsSync(c)) return c;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
async function install() {
|
|
46
|
+
console.log(" [1/5] ~/.cc-room/bin/ \u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7...");
|
|
47
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
48
|
+
const daemonSrc = findDaemonBin();
|
|
49
|
+
const daemonDest = join(BIN_DIR, "cc-room-daemon");
|
|
50
|
+
if (daemonSrc) {
|
|
51
|
+
copyFileSync(daemonSrc, daemonDest);
|
|
52
|
+
chmodSync(daemonDest, 493);
|
|
53
|
+
console.log(` \u30B3\u30D4\u30FC\u5B8C\u4E86: ${daemonDest}`);
|
|
54
|
+
} else {
|
|
55
|
+
const globalBin = spawnSync("which", ["cc-room-daemon"], { encoding: "utf-8" });
|
|
56
|
+
if (globalBin.status === 0) {
|
|
57
|
+
console.log(` \u30B0\u30ED\u30FC\u30D0\u30EB\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u78BA\u8A8D\u6E08\u307F: ${globalBin.stdout.trim()}`);
|
|
58
|
+
} else {
|
|
59
|
+
console.log(" \x1B[33m\u26A0 cc-room-daemon \u30D0\u30A4\u30CA\u30EA\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002npm install -g @cc-room/daemon \u3067\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044\u3002\x1B[0m");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
console.log(" [2/5] ~/.cc-room/config.yaml \u306E\u751F\u6210...");
|
|
63
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
64
|
+
const identity = getGitUserName();
|
|
65
|
+
const config = {
|
|
66
|
+
identity: { name: identity },
|
|
67
|
+
network: { port: 7331, http_port: 7332 },
|
|
68
|
+
trust: [],
|
|
69
|
+
sessions: { default_mode: "approve", share_files: true, share_context: true },
|
|
70
|
+
privacy: {
|
|
71
|
+
public_tools: ["room_context", "room_messages", "room_files", "room_status", "room_invite", "room_share"],
|
|
72
|
+
private_patterns: [],
|
|
73
|
+
redact_after_private_tool: true
|
|
74
|
+
},
|
|
75
|
+
summarizer: { model: "claude-haiku-4-5-20251001", interval_turns: 5, interval_seconds: 30 },
|
|
76
|
+
storage: { max_bytes: 524288e3, artifact_ttl_days: 30, context_ttl_days: 7, message_ttl_days: 14 }
|
|
77
|
+
};
|
|
78
|
+
writeFileSync(CONFIG_PATH, stringify(config), { mode: 384 });
|
|
79
|
+
console.log(` \u751F\u6210\u5B8C\u4E86: ${CONFIG_PATH} (identity: ${identity})`);
|
|
80
|
+
} else {
|
|
81
|
+
console.log(` \u30B9\u30AD\u30C3\u30D7: ${CONFIG_PATH} \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);
|
|
82
|
+
}
|
|
83
|
+
console.log(" [3/5] \u30B3\u30DE\u30F3\u30C9\u30D5\u30A1\u30A4\u30EB\u306E\u914D\u7F6E...");
|
|
84
|
+
mkdirSync(COMMANDS_DIR, { recursive: true });
|
|
85
|
+
const commandFiles = ["room.md", "private.md", "show.md"];
|
|
86
|
+
const legacyFiles = ["invite.md", "join.md", "leave.md", "files.md", "remember.md", "share.md"];
|
|
87
|
+
for (const cmd of commandFiles) {
|
|
88
|
+
const src = [
|
|
89
|
+
join(THIS_DIR, "..", "vendor", "commands", "room", cmd),
|
|
90
|
+
join(THIS_DIR, "..", "..", "commands", "room", cmd),
|
|
91
|
+
join(THIS_DIR, "..", "commands", "room", cmd)
|
|
92
|
+
].find(existsSync);
|
|
93
|
+
if (!src) throw new Error(`Command source file not found: ${cmd}`);
|
|
94
|
+
copyFileSync(src, join(COMMANDS_DIR, cmd));
|
|
95
|
+
}
|
|
96
|
+
for (const legacy of legacyFiles) {
|
|
97
|
+
const dest = join(COMMANDS_DIR, legacy);
|
|
98
|
+
if (existsSync(dest)) {
|
|
99
|
+
unlinkSync(dest);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
console.log(` ${commandFiles.length} \u30D5\u30A1\u30A4\u30EB\u3092 ${COMMANDS_DIR} \u306B\u914D\u7F6E\u3057\u307E\u3057\u305F`);
|
|
103
|
+
console.log(" [4/5] .claude/settings.json \u306E\u66F4\u65B0...");
|
|
104
|
+
mergeSettings();
|
|
105
|
+
console.log(" [5/5] OS\u81EA\u52D5\u8D77\u52D5\u306E\u767B\u9332...");
|
|
106
|
+
await registerService();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export {
|
|
110
|
+
install
|
|
111
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// src/validators.ts
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
3
|
+
import { existsSync, readFileSync, accessSync, constants } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
function validateAll() {
|
|
7
|
+
const checks = [
|
|
8
|
+
checkNodeVersion(),
|
|
9
|
+
checkClaudeCodeInstalled(),
|
|
10
|
+
checkClaudeDir(),
|
|
11
|
+
checkSettingsWritable(),
|
|
12
|
+
checkHooksNotDisabled(),
|
|
13
|
+
checkMcpNotBlocked(),
|
|
14
|
+
checkSessionDir(),
|
|
15
|
+
checkGitUser()
|
|
16
|
+
];
|
|
17
|
+
const passed = checks.every((r) => r.ok);
|
|
18
|
+
return { passed, results: checks };
|
|
19
|
+
}
|
|
20
|
+
function printResults(results) {
|
|
21
|
+
console.log("\n Preflight checks:\n");
|
|
22
|
+
for (const r of results) {
|
|
23
|
+
const icon = r.ok ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
|
|
24
|
+
console.log(` ${icon} ${r.message}`);
|
|
25
|
+
if (!r.ok && r.hint) {
|
|
26
|
+
console.log(` \x1B[33m\u2192 ${r.hint}\x1B[0m`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
console.log("");
|
|
30
|
+
}
|
|
31
|
+
function checkNodeVersion() {
|
|
32
|
+
const major = parseInt(process.versions.node.split(".")[0], 10);
|
|
33
|
+
if (major >= 20) {
|
|
34
|
+
return { ok: true, message: `Node.js ${process.versions.node}` };
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
ok: false,
|
|
38
|
+
message: `Node.js ${process.versions.node} (20+ \u304C\u5FC5\u8981)`,
|
|
39
|
+
hint: "Node.js 20 \u4EE5\u4E0A\u306B\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044: https://nodejs.org/"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function checkClaudeCodeInstalled() {
|
|
43
|
+
try {
|
|
44
|
+
execFileSync("claude", ["--version"], { encoding: "utf-8", stdio: "pipe" });
|
|
45
|
+
return { ok: true, message: "Claude Code \u304C\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6E08\u307F" };
|
|
46
|
+
} catch {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
message: "Claude Code \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
|
|
50
|
+
hint: "Claude Code \u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044: https://claude.ai/code"
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function checkClaudeDir() {
|
|
55
|
+
const claudeDir = join(homedir(), ".claude");
|
|
56
|
+
if (existsSync(claudeDir)) {
|
|
57
|
+
return { ok: true, message: "~/.claude/ \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728" };
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
message: "~/.claude/ \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
|
|
62
|
+
hint: "Claude Code \u3092\u4E00\u5EA6\u8D77\u52D5\u3057\u3066\u30BB\u30C3\u30B7\u30E7\u30F3\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function checkSettingsWritable() {
|
|
66
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
67
|
+
const settingsDir = join(homedir(), ".claude");
|
|
68
|
+
if (existsSync(settingsPath)) {
|
|
69
|
+
try {
|
|
70
|
+
accessSync(settingsPath, constants.W_OK);
|
|
71
|
+
return { ok: true, message: "settings.json \u306B\u66F8\u304D\u8FBC\u307F\u53EF\u80FD" };
|
|
72
|
+
} catch {
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
message: "settings.json \u306B\u66F8\u304D\u8FBC\u307F\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
76
|
+
hint: `chmod 644 ${settingsPath} \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044`
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
accessSync(settingsDir, constants.W_OK);
|
|
82
|
+
return { ok: true, message: "settings.json \u3092\u4F5C\u6210\u53EF\u80FD" };
|
|
83
|
+
} catch {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
message: "~/.claude/ \u306B\u66F8\u304D\u8FBC\u307F\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
87
|
+
hint: `chmod 755 ${settingsDir} \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function checkHooksNotDisabled() {
|
|
92
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
93
|
+
if (!existsSync(settingsPath)) {
|
|
94
|
+
return { ok: true, message: "Hooks: \u5236\u9650\u306A\u3057\uFF08settings.json \u672A\u4F5C\u6210\uFF09" };
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
98
|
+
if (settings.hooks === false || settings.disableHooks === true) {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
message: "Hooks \u304C\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059",
|
|
102
|
+
hint: "cc-room \u306F\u30D5\u30A1\u30A4\u30EB\u5171\u6709\u306B PostToolUse hook \u3092\u4F7F\u7528\u3057\u307E\u3059\u3002settings.json \u304B\u3089 hooks \u306E\u7121\u52B9\u5316\u8A2D\u5B9A\u3092\u524A\u9664\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return { ok: true, message: "Hooks: \u6709\u52B9" };
|
|
106
|
+
} catch {
|
|
107
|
+
return { ok: true, message: "Hooks: \u5236\u9650\u306A\u3057" };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function checkMcpNotBlocked() {
|
|
111
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
112
|
+
if (!existsSync(settingsPath)) {
|
|
113
|
+
return { ok: true, message: "MCP Server: \u767B\u9332\u53EF\u80FD" };
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
117
|
+
if (settings.mcpServers === false || settings.disableMcp === true) {
|
|
118
|
+
return {
|
|
119
|
+
ok: false,
|
|
120
|
+
message: "MCP Server \u306E\u767B\u9332\u304C\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059",
|
|
121
|
+
hint: "cc-room \u306F MCP Server \u7D4C\u7531\u3067 Claude Code \u3068\u9023\u643A\u3057\u307E\u3059\u3002settings.json \u304B\u3089 MCP \u306E\u7121\u52B9\u5316\u8A2D\u5B9A\u3092\u524A\u9664\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return { ok: true, message: "MCP Server: \u767B\u9332\u53EF\u80FD" };
|
|
125
|
+
} catch {
|
|
126
|
+
return { ok: true, message: "MCP Server: \u767B\u9332\u53EF\u80FD" };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function checkSessionDir() {
|
|
130
|
+
const projectsDir = join(homedir(), ".claude", "projects");
|
|
131
|
+
if (existsSync(projectsDir)) {
|
|
132
|
+
return { ok: true, message: "\u30BB\u30C3\u30B7\u30E7\u30F3\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728" };
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
ok: true,
|
|
136
|
+
message: "\u30BB\u30C3\u30B7\u30E7\u30F3\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u672A\u4F5C\u6210\uFF08\u521D\u56DE\u30BB\u30C3\u30B7\u30E7\u30F3\u5F8C\u306B\u751F\u6210\u3055\u308C\u308B\uFF09"
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function checkGitUser() {
|
|
140
|
+
try {
|
|
141
|
+
const name = execFileSync("git", ["config", "user.name"], {
|
|
142
|
+
encoding: "utf-8",
|
|
143
|
+
stdio: "pipe"
|
|
144
|
+
}).trim();
|
|
145
|
+
if (name) {
|
|
146
|
+
return { ok: true, message: `Git \u30E6\u30FC\u30B6\u30FC: ${name}` };
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
ok: false,
|
|
150
|
+
message: "git user.name \u304C\u672A\u8A2D\u5B9A",
|
|
151
|
+
hint: 'git config --global user.name "Your Name" \u3067\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08cc-room \u306E identity \u306B\u4F7F\u7528\uFF09'
|
|
152
|
+
};
|
|
153
|
+
} catch {
|
|
154
|
+
return {
|
|
155
|
+
ok: false,
|
|
156
|
+
message: "git \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
|
|
157
|
+
hint: "git \u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export {
|
|
163
|
+
validateAll,
|
|
164
|
+
printResults
|
|
165
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DAEMON_MISSING_HINT,
|
|
3
|
+
resolveDaemonSource
|
|
4
|
+
} from "./chunk-R5BAC4BK.js";
|
|
5
|
+
import {
|
|
6
|
+
registerService
|
|
7
|
+
} from "./chunk-XFCYRKG6.js";
|
|
8
|
+
import {
|
|
9
|
+
mergeSettings
|
|
10
|
+
} from "./chunk-5NTML4PF.js";
|
|
11
|
+
|
|
12
|
+
// src/installer.ts
|
|
13
|
+
import {
|
|
14
|
+
mkdirSync,
|
|
15
|
+
writeFileSync,
|
|
16
|
+
existsSync,
|
|
17
|
+
copyFileSync,
|
|
18
|
+
chmodSync,
|
|
19
|
+
unlinkSync
|
|
20
|
+
} from "fs";
|
|
21
|
+
import { join, dirname } from "path";
|
|
22
|
+
import { homedir } from "os";
|
|
23
|
+
import { execFileSync, spawnSync } from "child_process";
|
|
24
|
+
import { fileURLToPath } from "url";
|
|
25
|
+
import { stringify } from "yaml";
|
|
26
|
+
var CC_ROOM_DIR = join(homedir(), ".cc-room");
|
|
27
|
+
var BIN_DIR = join(CC_ROOM_DIR, "bin");
|
|
28
|
+
var CONFIG_PATH = join(CC_ROOM_DIR, "config.yaml");
|
|
29
|
+
var COMMANDS_DIR = join(homedir(), ".claude", "commands");
|
|
30
|
+
var THIS_DIR = dirname(fileURLToPath(import.meta.url));
|
|
31
|
+
var SETUP_PACKAGE_ROOT = join(THIS_DIR, "..");
|
|
32
|
+
function getGitUserName() {
|
|
33
|
+
try {
|
|
34
|
+
return execFileSync("git", ["config", "user.name"], { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
35
|
+
} catch {
|
|
36
|
+
return "unknown";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function install() {
|
|
40
|
+
console.log(" [1/5] ~/.cc-room/bin/ \u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7...");
|
|
41
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
42
|
+
const daemonSrc = resolveDaemonSource(SETUP_PACKAGE_ROOT);
|
|
43
|
+
const daemonDest = join(BIN_DIR, "cc-room-daemon");
|
|
44
|
+
if (daemonSrc) {
|
|
45
|
+
copyFileSync(daemonSrc, daemonDest);
|
|
46
|
+
chmodSync(daemonDest, 493);
|
|
47
|
+
console.log(` \u30B3\u30D4\u30FC\u5B8C\u4E86: ${daemonDest}`);
|
|
48
|
+
} else {
|
|
49
|
+
const globalBin = spawnSync("which", ["cc-room-daemon"], { encoding: "utf-8" });
|
|
50
|
+
if (globalBin.status === 0) {
|
|
51
|
+
console.log(` \u30B0\u30ED\u30FC\u30D0\u30EB\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u78BA\u8A8D\u6E08\u307F: ${globalBin.stdout.trim()}`);
|
|
52
|
+
} else {
|
|
53
|
+
console.log(` \x1B[33m\u26A0 ${DAEMON_MISSING_HINT}\x1B[0m`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
console.log(" [2/5] ~/.cc-room/config.yaml \u306E\u751F\u6210...");
|
|
57
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
58
|
+
const identity = getGitUserName();
|
|
59
|
+
const config = {
|
|
60
|
+
identity: { name: identity },
|
|
61
|
+
network: { port: 7331, http_port: 7332 },
|
|
62
|
+
trust: [],
|
|
63
|
+
sessions: { default_mode: "approve", share_files: true, share_context: true },
|
|
64
|
+
privacy: {
|
|
65
|
+
public_tools: ["room_context", "room_messages", "room_files", "room_status", "room_invite", "room_share"],
|
|
66
|
+
private_patterns: [],
|
|
67
|
+
redact_after_private_tool: true
|
|
68
|
+
},
|
|
69
|
+
summarizer: { model: "claude-haiku-4-5-20251001", interval_turns: 5, interval_seconds: 30 },
|
|
70
|
+
storage: { max_bytes: 524288e3, artifact_ttl_days: 30, context_ttl_days: 7, message_ttl_days: 14 }
|
|
71
|
+
};
|
|
72
|
+
writeFileSync(CONFIG_PATH, stringify(config), { mode: 384 });
|
|
73
|
+
console.log(` \u751F\u6210\u5B8C\u4E86: ${CONFIG_PATH} (identity: ${identity})`);
|
|
74
|
+
} else {
|
|
75
|
+
console.log(` \u30B9\u30AD\u30C3\u30D7: ${CONFIG_PATH} \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);
|
|
76
|
+
}
|
|
77
|
+
console.log(" [3/5] \u30B3\u30DE\u30F3\u30C9\u30D5\u30A1\u30A4\u30EB\u306E\u914D\u7F6E...");
|
|
78
|
+
mkdirSync(COMMANDS_DIR, { recursive: true });
|
|
79
|
+
const commandFiles = ["room.md", "private.md", "show.md"];
|
|
80
|
+
const legacyFiles = ["invite.md", "join.md", "leave.md", "files.md", "remember.md", "share.md"];
|
|
81
|
+
for (const cmd of commandFiles) {
|
|
82
|
+
const src = [
|
|
83
|
+
join(THIS_DIR, "..", "vendor", "commands", "room", cmd),
|
|
84
|
+
join(THIS_DIR, "..", "..", "commands", "room", cmd),
|
|
85
|
+
join(THIS_DIR, "..", "commands", "room", cmd)
|
|
86
|
+
].find(existsSync);
|
|
87
|
+
if (!src) throw new Error(`Command source file not found: ${cmd}`);
|
|
88
|
+
copyFileSync(src, join(COMMANDS_DIR, cmd));
|
|
89
|
+
}
|
|
90
|
+
for (const legacy of legacyFiles) {
|
|
91
|
+
const dest = join(COMMANDS_DIR, legacy);
|
|
92
|
+
if (existsSync(dest)) {
|
|
93
|
+
unlinkSync(dest);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
console.log(` ${commandFiles.length} \u30D5\u30A1\u30A4\u30EB\u3092 ${COMMANDS_DIR} \u306B\u914D\u7F6E\u3057\u307E\u3057\u305F`);
|
|
97
|
+
console.log(" [4/5] .claude/settings.json \u306E\u66F4\u65B0...");
|
|
98
|
+
mergeSettings();
|
|
99
|
+
console.log(" [5/5] OS\u81EA\u52D5\u8D77\u52D5\u306E\u767B\u9332...");
|
|
100
|
+
await registerService();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
install
|
|
105
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DAEMON_MISSING_HINT,
|
|
3
|
+
resolveDaemonSource
|
|
4
|
+
} from "./chunk-R5BAC4BK.js";
|
|
5
|
+
import {
|
|
6
|
+
registerService
|
|
7
|
+
} from "./chunk-UWFC4FU6.js";
|
|
8
|
+
import {
|
|
9
|
+
resolveCcRoomDir
|
|
10
|
+
} from "./chunk-WCEABGOA.js";
|
|
11
|
+
import {
|
|
12
|
+
mergeSettings
|
|
13
|
+
} from "./chunk-5NTML4PF.js";
|
|
14
|
+
|
|
15
|
+
// src/installer.ts
|
|
16
|
+
import {
|
|
17
|
+
mkdirSync,
|
|
18
|
+
writeFileSync,
|
|
19
|
+
existsSync,
|
|
20
|
+
copyFileSync,
|
|
21
|
+
chmodSync,
|
|
22
|
+
unlinkSync
|
|
23
|
+
} from "fs";
|
|
24
|
+
import { join, dirname } from "path";
|
|
25
|
+
import { homedir } from "os";
|
|
26
|
+
import { execFileSync, spawnSync } from "child_process";
|
|
27
|
+
import { fileURLToPath } from "url";
|
|
28
|
+
import { stringify } from "yaml";
|
|
29
|
+
var CC_ROOM_DIR = resolveCcRoomDir();
|
|
30
|
+
var BIN_DIR = join(CC_ROOM_DIR, "bin");
|
|
31
|
+
var CONFIG_PATH = join(CC_ROOM_DIR, "config.yaml");
|
|
32
|
+
var COMMANDS_DIR = join(homedir(), ".claude", "commands");
|
|
33
|
+
var THIS_DIR = dirname(fileURLToPath(import.meta.url));
|
|
34
|
+
var SETUP_PACKAGE_ROOT = join(THIS_DIR, "..");
|
|
35
|
+
function getGitUserName() {
|
|
36
|
+
try {
|
|
37
|
+
return execFileSync("git", ["config", "user.name"], { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
38
|
+
} catch {
|
|
39
|
+
return "unknown";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function install() {
|
|
43
|
+
console.log(` [1/5] ${CC_ROOM_DIR}/bin/ \u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7...`);
|
|
44
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
45
|
+
const daemonSrc = resolveDaemonSource(SETUP_PACKAGE_ROOT);
|
|
46
|
+
const daemonDest = join(BIN_DIR, "cc-room-daemon");
|
|
47
|
+
if (daemonSrc) {
|
|
48
|
+
copyFileSync(daemonSrc, daemonDest);
|
|
49
|
+
chmodSync(daemonDest, 493);
|
|
50
|
+
console.log(` \u30B3\u30D4\u30FC\u5B8C\u4E86: ${daemonDest}`);
|
|
51
|
+
} else {
|
|
52
|
+
const globalBin = spawnSync("which", ["cc-room-daemon"], { encoding: "utf-8" });
|
|
53
|
+
if (globalBin.status === 0) {
|
|
54
|
+
console.log(` \u30B0\u30ED\u30FC\u30D0\u30EB\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u78BA\u8A8D\u6E08\u307F: ${globalBin.stdout.trim()}`);
|
|
55
|
+
} else {
|
|
56
|
+
console.log(` \x1B[33m\u26A0 ${DAEMON_MISSING_HINT}\x1B[0m`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
console.log(` [2/5] ${CONFIG_PATH} \u306E\u751F\u6210...`);
|
|
60
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
61
|
+
const identity = getGitUserName();
|
|
62
|
+
const config = {
|
|
63
|
+
identity: { name: identity },
|
|
64
|
+
network: { port: 7331, http_port: 7332 },
|
|
65
|
+
trust: [],
|
|
66
|
+
sessions: { default_mode: "approve", share_files: true, share_context: true },
|
|
67
|
+
privacy: {
|
|
68
|
+
public_tools: ["room_context", "room_messages", "room_files", "room_status", "room_invite", "room_share"],
|
|
69
|
+
private_patterns: [],
|
|
70
|
+
redact_after_private_tool: true
|
|
71
|
+
},
|
|
72
|
+
summarizer: { model: "claude-haiku-4-5-20251001", interval_turns: 5, interval_seconds: 30 },
|
|
73
|
+
storage: { max_bytes: 524288e3, artifact_ttl_days: 30, context_ttl_days: 7, message_ttl_days: 14 }
|
|
74
|
+
};
|
|
75
|
+
writeFileSync(CONFIG_PATH, stringify(config), { mode: 384 });
|
|
76
|
+
console.log(` \u751F\u6210\u5B8C\u4E86: ${CONFIG_PATH} (identity: ${identity})`);
|
|
77
|
+
} else {
|
|
78
|
+
console.log(` \u30B9\u30AD\u30C3\u30D7: ${CONFIG_PATH} \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);
|
|
79
|
+
}
|
|
80
|
+
console.log(" [3/5] \u30B3\u30DE\u30F3\u30C9\u30D5\u30A1\u30A4\u30EB\u306E\u914D\u7F6E...");
|
|
81
|
+
mkdirSync(COMMANDS_DIR, { recursive: true });
|
|
82
|
+
const commandFiles = ["room.md", "private.md", "show.md"];
|
|
83
|
+
const legacyFiles = ["invite.md", "join.md", "leave.md", "files.md", "remember.md", "share.md"];
|
|
84
|
+
for (const cmd of commandFiles) {
|
|
85
|
+
const src = [
|
|
86
|
+
join(THIS_DIR, "..", "vendor", "commands", "room", cmd),
|
|
87
|
+
join(THIS_DIR, "..", "..", "commands", "room", cmd),
|
|
88
|
+
join(THIS_DIR, "..", "commands", "room", cmd)
|
|
89
|
+
].find(existsSync);
|
|
90
|
+
if (!src) throw new Error(`Command source file not found: ${cmd}`);
|
|
91
|
+
copyFileSync(src, join(COMMANDS_DIR, cmd));
|
|
92
|
+
}
|
|
93
|
+
for (const legacy of legacyFiles) {
|
|
94
|
+
const dest = join(COMMANDS_DIR, legacy);
|
|
95
|
+
if (existsSync(dest)) {
|
|
96
|
+
unlinkSync(dest);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
console.log(` ${commandFiles.length} \u30D5\u30A1\u30A4\u30EB\u3092 ${COMMANDS_DIR} \u306B\u914D\u7F6E\u3057\u307E\u3057\u305F`);
|
|
100
|
+
console.log(" [4/5] .claude/settings.json \u306E\u66F4\u65B0...");
|
|
101
|
+
mergeSettings();
|
|
102
|
+
console.log(" [5/5] OS\u81EA\u52D5\u8D77\u52D5\u306E\u767B\u9332...");
|
|
103
|
+
await registerService();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
install
|
|
108
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/daemon-resolver.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
function resolveDaemonSource(setupPackageRoot) {
|
|
5
|
+
const candidates = [
|
|
6
|
+
join(setupPackageRoot, "vendor", "daemon", "dist", "index.js"),
|
|
7
|
+
join(setupPackageRoot, "..", "daemon", "dist-bundle", "index.js"),
|
|
8
|
+
// モノレポ開発時のフォールバック(チャンク分割あり・単体コピーでは動かないことがある)
|
|
9
|
+
join(setupPackageRoot, "..", "daemon", "dist", "index.js"),
|
|
10
|
+
join(setupPackageRoot, "..", "..", "node_modules", "@cc-room", "daemon", "dist", "index.js")
|
|
11
|
+
];
|
|
12
|
+
for (const c of candidates) {
|
|
13
|
+
if (existsSync(c)) return c;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
var DAEMON_MISSING_HINT = "cc-room-daemon \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30EA\u30DD\u30B8\u30C8\u30EA\u3067\u306F `pnpm --filter setup-cc-room run pack:vendor` \u3092\u5B9F\u884C\u3059\u308B\u304B\u3001npm \u306E setup-cc-room \u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002";
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
resolveDaemonSource,
|
|
21
|
+
DAEMON_MISSING_HINT
|
|
22
|
+
};
|