setup-cc-room 0.2.0 → 0.2.2
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-6SYATEI6.js +108 -0
- package/dist/chunk-AVDOC76K.js +116 -0
- package/dist/chunk-ETJNYBPF.js +116 -0
- package/dist/chunk-KEFBOTQD.js +22 -0
- package/dist/chunk-LMBNCW4L.js +142 -0
- package/dist/chunk-MSQUTURC.js +119 -0
- package/dist/chunk-MVD6RIS2.js +120 -0
- package/dist/chunk-OYW7MM4W.js +278 -0
- package/dist/chunk-RYVZHEHF.js +169 -0
- package/dist/chunk-SMSDMP5O.js +125 -0
- package/dist/chunk-ZDOKJ4KX.js +132 -0
- package/dist/daemon-resolver.d.ts +1 -1
- package/dist/daemon-resolver.js +1 -1
- package/dist/i18n.d.ts +7 -0
- package/dist/i18n.js +12 -0
- package/dist/index.js +73 -38
- package/dist/installer.d.ts +5 -2
- package/dist/installer.js +9 -6
- package/dist/register-service.js +2 -1
- package/dist/settings-merger.d.ts +4 -1
- package/dist/settings-merger.js +8 -3
- package/dist/uninstaller.d.ts +10 -0
- package/dist/uninstaller.js +23 -0
- package/dist/validators.js +2 -1
- package/package.json +2 -2
- package/vendor/commands/room/en/private.md +75 -0
- package/vendor/commands/room/en/room.md +475 -0
- package/vendor/commands/room/en/show.md +149 -0
- /package/vendor/commands/room/{private.md → ja/private.md} +0 -0
- /package/vendor/commands/room/{room.md → ja/room.md} +0 -0
- /package/vendor/commands/room/{show.md → ja/show.md} +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
t
|
|
3
|
+
} from "./chunk-OYW7MM4W.js";
|
|
4
|
+
|
|
5
|
+
// src/settings-merger.ts
|
|
6
|
+
import { readFileSync, writeFileSync, existsSync, copyFileSync, mkdirSync } from "fs";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
var SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
10
|
+
var CC_ROOM_HOOKS = {
|
|
11
|
+
UserPromptSubmit: [
|
|
12
|
+
{
|
|
13
|
+
hooks: [
|
|
14
|
+
{
|
|
15
|
+
type: "command",
|
|
16
|
+
command: "cc-room-daemon hook user-prompt-submit"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
PostToolUse: [
|
|
22
|
+
{
|
|
23
|
+
matcher: "Write|Edit",
|
|
24
|
+
hooks: [
|
|
25
|
+
{
|
|
26
|
+
type: "command",
|
|
27
|
+
command: "cc-room-daemon hook post-tool-use"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
Stop: [
|
|
33
|
+
{
|
|
34
|
+
hooks: [
|
|
35
|
+
{
|
|
36
|
+
type: "command",
|
|
37
|
+
command: "cc-room-daemon hook session-stop"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
var CC_ROOM_MCP = {
|
|
44
|
+
"cc-room": {
|
|
45
|
+
type: "stdio",
|
|
46
|
+
command: "cc-room-daemon",
|
|
47
|
+
args: ["mcp"]
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function mergeSettings() {
|
|
51
|
+
let settings = {};
|
|
52
|
+
mkdirSync(join(homedir(), ".claude"), { recursive: true });
|
|
53
|
+
if (existsSync(SETTINGS_PATH)) {
|
|
54
|
+
try {
|
|
55
|
+
settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
|
|
56
|
+
} catch {
|
|
57
|
+
console.log(t("settings.parse_fail_backup"));
|
|
58
|
+
copyFileSync(SETTINGS_PATH, SETTINGS_PATH + ".backup");
|
|
59
|
+
settings = {};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const existingHooks = settings.hooks ?? {};
|
|
63
|
+
const mergedHooks = { ...existingHooks };
|
|
64
|
+
for (const [event, newEntries] of Object.entries(CC_ROOM_HOOKS)) {
|
|
65
|
+
const existing = mergedHooks[event] ?? [];
|
|
66
|
+
const filtered = existing.filter((e) => {
|
|
67
|
+
const entry = e;
|
|
68
|
+
return !entry.hooks?.some((h) => h.command?.startsWith("cc-room-daemon hook"));
|
|
69
|
+
});
|
|
70
|
+
mergedHooks[event] = [...filtered, ...newEntries];
|
|
71
|
+
}
|
|
72
|
+
const existingMcp = settings.mcpServers ?? {};
|
|
73
|
+
const mergedMcp = { ...existingMcp, ...CC_ROOM_MCP };
|
|
74
|
+
settings.hooks = mergedHooks;
|
|
75
|
+
settings.mcpServers = mergedMcp;
|
|
76
|
+
writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + "\n", { mode: 420 });
|
|
77
|
+
console.log(t("settings.updated", { path: SETTINGS_PATH }));
|
|
78
|
+
}
|
|
79
|
+
function stripCcRoomFromSettings(settings) {
|
|
80
|
+
const next = { ...settings };
|
|
81
|
+
const existingHooks = settings.hooks ?? {};
|
|
82
|
+
const strippedHooks = {};
|
|
83
|
+
for (const [event, entries] of Object.entries(existingHooks)) {
|
|
84
|
+
strippedHooks[event] = (entries ?? []).filter((e) => {
|
|
85
|
+
const entry = e;
|
|
86
|
+
return !entry.hooks?.some((h) => h.command?.startsWith("cc-room-daemon hook"));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (Object.keys(existingHooks).length > 0 || Object.keys(strippedHooks).length > 0) {
|
|
90
|
+
next.hooks = strippedHooks;
|
|
91
|
+
}
|
|
92
|
+
const existingMcp = settings.mcpServers ?? {};
|
|
93
|
+
if (Object.keys(existingMcp).length > 0) {
|
|
94
|
+
const { ["cc-room"]: _removed, ...rest } = existingMcp;
|
|
95
|
+
next.mcpServers = rest;
|
|
96
|
+
}
|
|
97
|
+
return next;
|
|
98
|
+
}
|
|
99
|
+
function unmergeSettings() {
|
|
100
|
+
if (!existsSync(SETTINGS_PATH)) {
|
|
101
|
+
console.log(t("settings.skip_missing", { path: SETTINGS_PATH }));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
let settings;
|
|
105
|
+
try {
|
|
106
|
+
settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
|
|
107
|
+
} catch {
|
|
108
|
+
console.log(t("settings.parse_fail_skip"));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const next = stripCcRoomFromSettings(settings);
|
|
112
|
+
writeFileSync(SETTINGS_PATH, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
|
|
113
|
+
console.log(t("settings.stripped", { path: SETTINGS_PATH }));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
mergeSettings,
|
|
118
|
+
stripCcRoomFromSettings,
|
|
119
|
+
unmergeSettings
|
|
120
|
+
};
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// src/i18n.ts
|
|
2
|
+
function resolveLocale(argv = process.argv, env = process.env) {
|
|
3
|
+
const langFlagIdx = argv.findIndex((a) => a === "--lang" || a === "--locale");
|
|
4
|
+
if (langFlagIdx >= 0 && argv[langFlagIdx + 1]) {
|
|
5
|
+
return normalizeLocale(argv[langFlagIdx + 1]);
|
|
6
|
+
}
|
|
7
|
+
const inline = argv.find((a) => a.startsWith("--lang=") || a.startsWith("--locale="));
|
|
8
|
+
if (inline) {
|
|
9
|
+
return normalizeLocale(inline.split("=")[1] ?? "en");
|
|
10
|
+
}
|
|
11
|
+
if (env.CC_ROOM_LANG) {
|
|
12
|
+
return normalizeLocale(env.CC_ROOM_LANG);
|
|
13
|
+
}
|
|
14
|
+
return "en";
|
|
15
|
+
}
|
|
16
|
+
function normalizeLocale(raw) {
|
|
17
|
+
const v = raw.trim().toLowerCase();
|
|
18
|
+
if (v === "ja" || v === "jp" || v === "japanese" || v.startsWith("ja-")) return "ja";
|
|
19
|
+
return "en";
|
|
20
|
+
}
|
|
21
|
+
var en = {
|
|
22
|
+
"cli.running_preflight": " Running preflight checks...",
|
|
23
|
+
"cli.preflight_failed": " \x1B[31mPrerequisites not met. Fix the issues above and try again.\x1B[0m\n",
|
|
24
|
+
"cli.preflight_ok": " \x1B[32mAll checks passed. Starting install...\x1B[0m\n",
|
|
25
|
+
"cli.install_done": " \x1B[32m\u2705 Setup complete!\x1B[0m",
|
|
26
|
+
"cli.uninstall_done": " \x1B[32m\u2705 Uninstall complete.\x1B[0m",
|
|
27
|
+
"cli.restart_claude": " Restart Claude Code so hooks / MCP take effect.",
|
|
28
|
+
"cli.unknown_arg": " Unknown argument: {arg}",
|
|
29
|
+
"cli.error": " \x1B[31mError:\x1B[0m",
|
|
30
|
+
"cli.help": `
|
|
31
|
+
\u{1F3E0} setup-cc-room v{version}
|
|
32
|
+
|
|
33
|
+
Usage:
|
|
34
|
+
npx setup-cc-room Install cc-room (English by default)
|
|
35
|
+
npx setup-cc-room --lang ja Install with Japanese UI / commands
|
|
36
|
+
npx setup-cc-room uninstall Remove cc-room
|
|
37
|
+
npx setup-cc-room --help Show this help
|
|
38
|
+
|
|
39
|
+
Language: --lang en|ja or CC_ROOM_LANG=ja
|
|
40
|
+
`,
|
|
41
|
+
"cli.install_guide": `
|
|
42
|
+
How to use cc-room:
|
|
43
|
+
|
|
44
|
+
[Open a room]
|
|
45
|
+
1. Restart Claude Code (enable MCP and Hooks)
|
|
46
|
+
2. /room open <name> \u2190 creates a room (PIN issued)
|
|
47
|
+
3. Tell teammates the room name and PIN
|
|
48
|
+
4. They run /room join <name> <PIN>
|
|
49
|
+
|
|
50
|
+
[If invited]
|
|
51
|
+
1. Restart Claude Code
|
|
52
|
+
2. /room join <name> <PIN>
|
|
53
|
+
|
|
54
|
+
[Daily]
|
|
55
|
+
/room \u2026 view the whiteboard
|
|
56
|
+
/private \u2026 status / local vs public (on|off|share|drop)
|
|
57
|
+
|
|
58
|
+
\u26A0\uFE0F cc-room does not notify others automatically.
|
|
59
|
+
Share the room name and PIN yourself.
|
|
60
|
+
|
|
61
|
+
You need to be on the same Wi\u2011Fi (LAN).
|
|
62
|
+
(A VPN that creates a shared LAN also works.)
|
|
63
|
+
|
|
64
|
+
Uninstall: npx setup-cc-room uninstall
|
|
65
|
+
Japanese UI: npx setup-cc-room --lang ja
|
|
66
|
+
|
|
67
|
+
Docs: https://github.com/takanorisuzuki/cc-room
|
|
68
|
+
`,
|
|
69
|
+
"install.step1": " [1/5] Setting up {dir}/bin/...",
|
|
70
|
+
"install.copied": " Copied: {path}",
|
|
71
|
+
"install.global_ok": " Found global binary: {path}",
|
|
72
|
+
"install.step2": " [2/5] Writing {path}...",
|
|
73
|
+
"install.config_created": " Created: {path} (identity: {identity})",
|
|
74
|
+
"install.config_skip": " Skip: {path} already exists",
|
|
75
|
+
"install.step3": " [3/5] Installing slash commands ({locale})...",
|
|
76
|
+
"install.commands_ok": " Installed {count} files into {dir}",
|
|
77
|
+
"install.step4": " [4/5] Updating .claude/settings.json...",
|
|
78
|
+
"install.step5": " [5/5] Registering OS auto-start...",
|
|
79
|
+
"daemon.missing": "cc-room-daemon not found. In the repo run `pnpm --filter setup-cc-room run pack:vendor`, or use the npm setup-cc-room package.",
|
|
80
|
+
"settings.updated": " Updated {path}",
|
|
81
|
+
"settings.parse_fail_backup": " \x1B[33m\u26A0 Failed to parse settings.json. Creating a backup and overwriting.\x1B[0m",
|
|
82
|
+
"settings.skip_missing": " Skip: {path} does not exist",
|
|
83
|
+
"settings.parse_fail_skip": " \x1B[33m\u26A0 Failed to parse settings.json; skipped removing hooks/MCP.\x1B[0m",
|
|
84
|
+
"settings.stripped": " Removed cc-room from {path}",
|
|
85
|
+
"svc.launchd_ok": " Registered with launchd: {path}",
|
|
86
|
+
"svc.launchd_fail": " \x1B[33m\u26A0 launchd registration failed: {msg}\x1B[0m",
|
|
87
|
+
"svc.launchd_manual": " Manual: launchctl load {path}",
|
|
88
|
+
"svc.systemd_ok": " Registered with systemd: {path}",
|
|
89
|
+
"svc.systemd_fail": " \x1B[33m\u26A0 systemd registration failed: {msg}\x1B[0m",
|
|
90
|
+
"svc.systemd_manual": " Manual: systemctl --user enable --now cc-room-daemon",
|
|
91
|
+
"svc.unsupported": " \x1B[33m\u26A0 Auto-start is not supported on {os}. Start cc-room-daemon manually.\x1B[0m",
|
|
92
|
+
"svc.waiting": " Waiting for daemon to start...",
|
|
93
|
+
"svc.started": " Daemon started",
|
|
94
|
+
"svc.start_unconfirmed": " \x1B[33m\u26A0 Could not confirm daemon start. Run cc-room-daemon manually.\x1B[0m",
|
|
95
|
+
"un.step1": " [1/4] Stopping OS service...",
|
|
96
|
+
"un.launchd_none": " launchd: not registered",
|
|
97
|
+
"un.launchd_ok": " Unregistered launchd: {path}",
|
|
98
|
+
"un.plist_fail": " \x1B[33m\u26A0 Failed to remove plist: {msg}\x1B[0m",
|
|
99
|
+
"un.systemd_ok": " Unregistered systemd: {path}",
|
|
100
|
+
"un.unit_fail": " \x1B[33m\u26A0 Failed to remove unit: {msg}\x1B[0m",
|
|
101
|
+
"un.systemd_none": " systemd: not registered",
|
|
102
|
+
"un.os_manual": " {os}: unregister auto-start manually",
|
|
103
|
+
"un.step2": " [2/4] Removing slash commands...",
|
|
104
|
+
"un.commands_ok": " Removed {count} command files ({dir})",
|
|
105
|
+
"un.step3": " [3/4] Removing cc-room from .claude/settings.json...",
|
|
106
|
+
"un.step4": " [4/4] Removing data directory...",
|
|
107
|
+
"un.data_skip": " Skip: {dir} does not exist",
|
|
108
|
+
"un.data_ok": " Deleted: {dir}",
|
|
109
|
+
"val.node_bad": "Node.js {version} (20+ required)",
|
|
110
|
+
"val.node_hint": "Upgrade to Node.js 20+: https://nodejs.org/",
|
|
111
|
+
"val.claude_ok": "Claude Code is installed",
|
|
112
|
+
"val.claude_missing": "Claude Code not found",
|
|
113
|
+
"val.claude_hint": "Install Claude Code: https://claude.ai/code",
|
|
114
|
+
"val.claude_dir_ok": "~/.claude/ directory exists",
|
|
115
|
+
"val.claude_dir_missing": "~/.claude/ not found",
|
|
116
|
+
"val.claude_dir_hint": "Start Claude Code once to create a session",
|
|
117
|
+
"val.settings_writable": "settings.json is writable",
|
|
118
|
+
"val.settings_not_writable": "No write permission for settings.json",
|
|
119
|
+
"val.settings_chmod": "Run chmod 644 {path}",
|
|
120
|
+
"val.settings_creatable": "Can create settings.json",
|
|
121
|
+
"val.claude_dir_not_writable": "No write permission for ~/.claude/",
|
|
122
|
+
"val.claude_dir_chmod": "Run chmod 755 {path}",
|
|
123
|
+
"val.hooks_unset": "Hooks: unrestricted (no settings.json yet)",
|
|
124
|
+
"val.hooks_disabled": "Hooks are disabled",
|
|
125
|
+
"val.hooks_disabled_hint": "cc-room needs the PostToolUse hook. Remove the hooks disable setting from settings.json",
|
|
126
|
+
"val.hooks_ok": "Hooks: enabled",
|
|
127
|
+
"val.hooks_unrestricted": "Hooks: unrestricted",
|
|
128
|
+
"val.mcp_ok": "MCP Server: can register",
|
|
129
|
+
"val.mcp_disabled": "MCP Server registration is disabled",
|
|
130
|
+
"val.mcp_disabled_hint": "cc-room talks to Claude Code via MCP. Remove the MCP disable setting from settings.json",
|
|
131
|
+
"val.session_ok": "Session directory exists",
|
|
132
|
+
"val.session_pending": "Session directory not created yet (appears after first session)",
|
|
133
|
+
"val.git_ok": "Git user: {name}",
|
|
134
|
+
"val.git_no_name": "git user.name is not set",
|
|
135
|
+
"val.git_no_name_hint": 'Set with git config --global user.name "Your Name" (used as cc-room identity)',
|
|
136
|
+
"val.git_missing": "git not found",
|
|
137
|
+
"val.git_hint": "Install git"
|
|
138
|
+
};
|
|
139
|
+
var ja = {
|
|
140
|
+
"cli.running_preflight": " Preflight checks \u3092\u5B9F\u884C\u4E2D...",
|
|
141
|
+
"cli.preflight_failed": " \x1B[31m\u524D\u63D0\u6761\u4EF6\u3092\u6E80\u305F\u3057\u3066\u3044\u307E\u305B\u3093\u3002\u4E0A\u8A18\u306E\u554F\u984C\u3092\u89E3\u6C7A\u3057\u3066\u304B\u3089\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\x1B[0m\n",
|
|
142
|
+
"cli.preflight_ok": " \x1B[32m\u5168\u30C1\u30A7\u30C3\u30AF\u901A\u904E\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3092\u958B\u59CB\u3057\u307E\u3059\u3002\x1B[0m\n",
|
|
143
|
+
"cli.install_done": " \x1B[32m\u2705 \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\uFF01\x1B[0m",
|
|
144
|
+
"cli.uninstall_done": " \x1B[32m\u2705 \u30A2\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\u3002\x1B[0m",
|
|
145
|
+
"cli.restart_claude": " Claude Code \u3092\u518D\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\uFF08hooks / MCP \u306E\u53CD\u6620\uFF09\u3002",
|
|
146
|
+
"cli.unknown_arg": " \u4E0D\u660E\u306A\u5F15\u6570: {arg}",
|
|
147
|
+
"cli.error": " \x1B[31m\u30A8\u30E9\u30FC:\x1B[0m",
|
|
148
|
+
"cli.help": `
|
|
149
|
+
\u{1F3E0} setup-cc-room v{version}
|
|
150
|
+
|
|
151
|
+
\u4F7F\u3044\u65B9:
|
|
152
|
+
npx setup-cc-room \u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u82F1\u8A9E\uFF09
|
|
153
|
+
npx setup-cc-room --lang ja \u65E5\u672C\u8A9E UI / \u30B3\u30DE\u30F3\u30C9\u3067\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB
|
|
154
|
+
npx setup-cc-room uninstall \u30A2\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB
|
|
155
|
+
npx setup-cc-room --help \u30D8\u30EB\u30D7
|
|
156
|
+
|
|
157
|
+
\u8A00\u8A9E: --lang en|ja \u307E\u305F\u306F CC_ROOM_LANG=ja
|
|
158
|
+
`,
|
|
159
|
+
"cli.install_guide": `
|
|
160
|
+
cc-room \u306E\u4F7F\u3044\u65B9:
|
|
161
|
+
|
|
162
|
+
\u3010\u4F1A\u8B70\u5BA4\u3092\u958B\u304F\u5834\u5408\u3011
|
|
163
|
+
1. Claude Code \u3092\u518D\u8D77\u52D5\uFF08MCP \u3068 Hooks \u3092\u6709\u52B9\u5316\uFF09
|
|
164
|
+
2. /room open <name> \u2190 \u4F1A\u8B70\u5BA4\u3092\u958B\u304F\uFF08PIN \u767A\u884C\uFF09
|
|
165
|
+
3. \u8868\u793A\u3055\u308C\u308B\u90E8\u5C4B\u540D\u3068 PIN \u3092\u76F8\u624B\u306B\u53E3\u982D\u3084 DM \u3067\u4F1D\u3048\u308B
|
|
166
|
+
4. \u76F8\u624B\u304C /room join <name> <PIN> \u3092\u5B9F\u884C\u3059\u308C\u3070\u53C2\u52A0\u5B8C\u4E86
|
|
167
|
+
|
|
168
|
+
\u3010\u62DB\u5F85\u3055\u308C\u305F\u5834\u5408\u3011
|
|
169
|
+
1. Claude Code \u3092\u518D\u8D77\u52D5
|
|
170
|
+
2. /room join <name> <PIN> \u2190 \u76F8\u624B\u304B\u3089\u53D7\u3051\u53D6\u3063\u305F\u5024\u3092\u5165\u529B
|
|
171
|
+
|
|
172
|
+
\u3010\u65E5\u5E38\u64CD\u4F5C\u3011
|
|
173
|
+
/room \u2026 \u30DB\u30EF\u30A4\u30C8\u30DC\u30FC\u30C9\u3092\u898B\u308B
|
|
174
|
+
/private \u2026 \u72B6\u614B\u8868\u793A\u3001\u624B\u5143/\u516C\u958B\u306E\u5207\u66FF\uFF08on|off|share|drop\uFF09
|
|
175
|
+
|
|
176
|
+
\u26A0\uFE0F cc-room \u306F\u81EA\u52D5\u3067\u76F8\u624B\u306B\u901A\u77E5\u3057\u307E\u305B\u3093\u3002
|
|
177
|
+
\u90E8\u5C4B\u540D\u3068 PIN \u306F\u81EA\u5206\u3067\u76F8\u624B\u306B\u4F1D\u3048\u3066\u304F\u3060\u3055\u3044\u3002
|
|
178
|
+
|
|
179
|
+
\u63A5\u7D9A\u5F8C\u306F\u540C\u3058 WiFi\uFF08LAN\uFF09\u5185\u306B\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
|
|
180
|
+
\uFF08VPN \u3067\u540C\u4E00 LAN \u76F8\u5F53\u306B\u306A\u308C\u3070\u30EA\u30E2\u30FC\u30C8\u3067\u3082\u4F7F\u3048\u307E\u3059\uFF09
|
|
181
|
+
|
|
182
|
+
\u30A2\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB: npx setup-cc-room uninstall
|
|
183
|
+
|
|
184
|
+
\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8: https://github.com/takanorisuzuki/cc-room
|
|
185
|
+
`,
|
|
186
|
+
"install.step1": " [1/5] {dir}/bin/ \u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7...",
|
|
187
|
+
"install.copied": " \u30B3\u30D4\u30FC\u5B8C\u4E86: {path}",
|
|
188
|
+
"install.global_ok": " \u30B0\u30ED\u30FC\u30D0\u30EB\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u78BA\u8A8D\u6E08\u307F: {path}",
|
|
189
|
+
"install.step2": " [2/5] {path} \u306E\u751F\u6210...",
|
|
190
|
+
"install.config_created": " \u751F\u6210\u5B8C\u4E86: {path} (identity: {identity})",
|
|
191
|
+
"install.config_skip": " \u30B9\u30AD\u30C3\u30D7: {path} \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059",
|
|
192
|
+
"install.step3": " [3/5] \u30B3\u30DE\u30F3\u30C9\u30D5\u30A1\u30A4\u30EB\u306E\u914D\u7F6E ({locale})...",
|
|
193
|
+
"install.commands_ok": " {count} \u30D5\u30A1\u30A4\u30EB\u3092 {dir} \u306B\u914D\u7F6E\u3057\u307E\u3057\u305F",
|
|
194
|
+
"install.step4": " [4/5] .claude/settings.json \u306E\u66F4\u65B0...",
|
|
195
|
+
"install.step5": " [5/5] OS\u81EA\u52D5\u8D77\u52D5\u306E\u767B\u9332...",
|
|
196
|
+
"daemon.missing": "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",
|
|
197
|
+
"settings.updated": " {path} \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F",
|
|
198
|
+
"settings.parse_fail_backup": " \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",
|
|
199
|
+
"settings.parse_fail_skip": " \x1B[33m\u26A0 settings.json \u306E\u30D1\u30FC\u30B9\u306B\u5931\u6557\u3057\u305F\u305F\u3081\u3001hooks/MCP \u306E\u9664\u53BB\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3059\u3002\x1B[0m",
|
|
200
|
+
"settings.skip_missing": " \u30B9\u30AD\u30C3\u30D7: {path} \u306F\u5B58\u5728\u3057\u307E\u305B\u3093",
|
|
201
|
+
"settings.stripped": " {path} \u304B\u3089 cc-room \u3092\u9664\u53BB\u3057\u307E\u3057\u305F",
|
|
202
|
+
"svc.launchd_ok": " launchd \u306B\u767B\u9332\u3057\u307E\u3057\u305F: {path}",
|
|
203
|
+
"svc.launchd_fail": " \x1B[33m\u26A0 launchd \u767B\u9332\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {msg}\x1B[0m",
|
|
204
|
+
"svc.launchd_manual": " \u624B\u52D5\u3067\u767B\u9332: launchctl load {path}",
|
|
205
|
+
"svc.systemd_ok": " systemd \u306B\u767B\u9332\u3057\u307E\u3057\u305F: {path}",
|
|
206
|
+
"svc.systemd_fail": " \x1B[33m\u26A0 systemd \u767B\u9332\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {msg}\x1B[0m",
|
|
207
|
+
"svc.systemd_manual": " \u624B\u52D5\u3067\u767B\u9332: systemctl --user enable --now cc-room-daemon",
|
|
208
|
+
"svc.unsupported": " \x1B[33m\u26A0 {os} \u3067\u306E\u81EA\u52D5\u8D77\u52D5\u767B\u9332\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u624B\u52D5\u3067 cc-room-daemon \u3092\u8D77\u52D5\u3057\u3066\u304F\u3060\u3055\u3044\u3002\x1B[0m",
|
|
209
|
+
"svc.waiting": " daemon \u306E\u8D77\u52D5\u3092\u5F85\u6A5F\u4E2D...",
|
|
210
|
+
"svc.started": " daemon \u304C\u8D77\u52D5\u3057\u307E\u3057\u305F",
|
|
211
|
+
"svc.start_unconfirmed": " \x1B[33m\u26A0 daemon \u306E\u81EA\u52D5\u8D77\u52D5\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u624B\u52D5\u3067 cc-room-daemon \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\x1B[0m",
|
|
212
|
+
"un.step1": " [1/4] OS \u30B5\u30FC\u30D3\u30B9\u3092\u505C\u6B62...",
|
|
213
|
+
"un.launchd_none": " launchd: \u672A\u767B\u9332",
|
|
214
|
+
"un.launchd_ok": " launchd \u3092\u89E3\u9664: {path}",
|
|
215
|
+
"un.plist_fail": " \x1B[33m\u26A0 plist \u524A\u9664\u306B\u5931\u6557: {msg}\x1B[0m",
|
|
216
|
+
"un.systemd_ok": " systemd \u3092\u89E3\u9664: {path}",
|
|
217
|
+
"un.unit_fail": " \x1B[33m\u26A0 unit \u524A\u9664\u306B\u5931\u6557: {msg}\x1B[0m",
|
|
218
|
+
"un.systemd_none": " systemd: \u672A\u767B\u9332",
|
|
219
|
+
"un.os_manual": " {os}: \u81EA\u52D5\u8D77\u52D5\u306E\u89E3\u9664\u306F\u624B\u52D5\u3067\u884C\u3063\u3066\u304F\u3060\u3055\u3044",
|
|
220
|
+
"un.step2": " [2/4] Slash commands \u3092\u524A\u9664...",
|
|
221
|
+
"un.commands_ok": " \u30B3\u30DE\u30F3\u30C9\u30D5\u30A1\u30A4\u30EB\u3092 {count} \u4EF6\u524A\u9664 ({dir})",
|
|
222
|
+
"un.step3": " [3/4] .claude/settings.json \u304B\u3089 cc-room \u3092\u9664\u53BB...",
|
|
223
|
+
"un.step4": " [4/4] \u30C7\u30FC\u30BF\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u524A\u9664...",
|
|
224
|
+
"un.data_skip": " \u30B9\u30AD\u30C3\u30D7: {dir} \u306F\u5B58\u5728\u3057\u307E\u305B\u3093",
|
|
225
|
+
"un.data_ok": " \u524A\u9664: {dir}",
|
|
226
|
+
"val.node_bad": "Node.js {version} (20+ \u304C\u5FC5\u8981)",
|
|
227
|
+
"val.node_hint": "Node.js 20 \u4EE5\u4E0A\u306B\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044: https://nodejs.org/",
|
|
228
|
+
"val.claude_ok": "Claude Code \u304C\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6E08\u307F",
|
|
229
|
+
"val.claude_missing": "Claude Code \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
|
|
230
|
+
"val.claude_hint": "Claude Code \u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044: https://claude.ai/code",
|
|
231
|
+
"val.claude_dir_ok": "~/.claude/ \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728",
|
|
232
|
+
"val.claude_dir_missing": "~/.claude/ \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
|
|
233
|
+
"val.claude_dir_hint": "Claude Code \u3092\u4E00\u5EA6\u8D77\u52D5\u3057\u3066\u30BB\u30C3\u30B7\u30E7\u30F3\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
234
|
+
"val.settings_writable": "settings.json \u306B\u66F8\u304D\u8FBC\u307F\u53EF\u80FD",
|
|
235
|
+
"val.settings_not_writable": "settings.json \u306B\u66F8\u304D\u8FBC\u307F\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
236
|
+
"val.settings_chmod": "chmod 644 {path} \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
237
|
+
"val.settings_creatable": "settings.json \u3092\u4F5C\u6210\u53EF\u80FD",
|
|
238
|
+
"val.claude_dir_not_writable": "~/.claude/ \u306B\u66F8\u304D\u8FBC\u307F\u6A29\u9650\u304C\u3042\u308A\u307E\u305B\u3093",
|
|
239
|
+
"val.claude_dir_chmod": "chmod 755 {path} \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
240
|
+
"val.hooks_unset": "Hooks: \u5236\u9650\u306A\u3057\uFF08settings.json \u672A\u4F5C\u6210\uFF09",
|
|
241
|
+
"val.hooks_disabled": "Hooks \u304C\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059",
|
|
242
|
+
"val.hooks_disabled_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",
|
|
243
|
+
"val.hooks_ok": "Hooks: \u6709\u52B9",
|
|
244
|
+
"val.hooks_unrestricted": "Hooks: \u5236\u9650\u306A\u3057",
|
|
245
|
+
"val.mcp_ok": "MCP Server: \u767B\u9332\u53EF\u80FD",
|
|
246
|
+
"val.mcp_disabled": "MCP Server \u306E\u767B\u9332\u304C\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059",
|
|
247
|
+
"val.mcp_disabled_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",
|
|
248
|
+
"val.session_ok": "\u30BB\u30C3\u30B7\u30E7\u30F3\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728",
|
|
249
|
+
"val.session_pending": "\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",
|
|
250
|
+
"val.git_ok": "Git \u30E6\u30FC\u30B6\u30FC: {name}",
|
|
251
|
+
"val.git_no_name": "git user.name \u304C\u672A\u8A2D\u5B9A",
|
|
252
|
+
"val.git_no_name_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',
|
|
253
|
+
"val.git_missing": "git \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
|
|
254
|
+
"val.git_hint": "git \u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
255
|
+
};
|
|
256
|
+
var catalogs = { en, ja };
|
|
257
|
+
var activeLocale = "en";
|
|
258
|
+
function setLocale(locale) {
|
|
259
|
+
activeLocale = locale;
|
|
260
|
+
}
|
|
261
|
+
function getLocale() {
|
|
262
|
+
return activeLocale;
|
|
263
|
+
}
|
|
264
|
+
function t(key, vars = {}) {
|
|
265
|
+
const catalog = catalogs[activeLocale] ?? catalogs.en;
|
|
266
|
+
let template = catalog[key] ?? catalogs.en[key] ?? key;
|
|
267
|
+
for (const [k, v] of Object.entries(vars)) {
|
|
268
|
+
template = template.replaceAll(`{${k}}`, String(v));
|
|
269
|
+
}
|
|
270
|
+
return template;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export {
|
|
274
|
+
resolveLocale,
|
|
275
|
+
setLocale,
|
|
276
|
+
getLocale,
|
|
277
|
+
t
|
|
278
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
t
|
|
3
|
+
} from "./chunk-OYW7MM4W.js";
|
|
4
|
+
|
|
5
|
+
// src/validators.ts
|
|
6
|
+
import { execFileSync } from "child_process";
|
|
7
|
+
import { existsSync, readFileSync, accessSync, constants } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
function validateAll() {
|
|
11
|
+
const checks = [
|
|
12
|
+
checkNodeVersion(),
|
|
13
|
+
checkClaudeCodeInstalled(),
|
|
14
|
+
checkClaudeDir(),
|
|
15
|
+
checkSettingsWritable(),
|
|
16
|
+
checkHooksNotDisabled(),
|
|
17
|
+
checkMcpNotBlocked(),
|
|
18
|
+
checkSessionDir(),
|
|
19
|
+
checkGitUser()
|
|
20
|
+
];
|
|
21
|
+
const passed = checks.every((r) => r.ok);
|
|
22
|
+
return { passed, results: checks };
|
|
23
|
+
}
|
|
24
|
+
function printResults(results) {
|
|
25
|
+
console.log("\n Preflight checks:\n");
|
|
26
|
+
for (const r of results) {
|
|
27
|
+
const icon = r.ok ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
|
|
28
|
+
console.log(` ${icon} ${r.message}`);
|
|
29
|
+
if (!r.ok && r.hint) {
|
|
30
|
+
console.log(` \x1B[33m\u2192 ${r.hint}\x1B[0m`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
console.log("");
|
|
34
|
+
}
|
|
35
|
+
function checkNodeVersion() {
|
|
36
|
+
const major = parseInt(process.versions.node.split(".")[0], 10);
|
|
37
|
+
if (major >= 20) {
|
|
38
|
+
return { ok: true, message: `Node.js ${process.versions.node}` };
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
message: t("val.node_bad", { version: process.versions.node }),
|
|
43
|
+
hint: t("val.node_hint")
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function checkClaudeCodeInstalled() {
|
|
47
|
+
try {
|
|
48
|
+
execFileSync("claude", ["--version"], { encoding: "utf-8", stdio: "pipe" });
|
|
49
|
+
return { ok: true, message: t("val.claude_ok") };
|
|
50
|
+
} catch {
|
|
51
|
+
return {
|
|
52
|
+
ok: false,
|
|
53
|
+
message: t("val.claude_missing"),
|
|
54
|
+
hint: t("val.claude_hint")
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function checkClaudeDir() {
|
|
59
|
+
const claudeDir = join(homedir(), ".claude");
|
|
60
|
+
if (existsSync(claudeDir)) {
|
|
61
|
+
return { ok: true, message: t("val.claude_dir_ok") };
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
message: t("val.claude_dir_missing"),
|
|
66
|
+
hint: t("val.claude_dir_hint")
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function checkSettingsWritable() {
|
|
70
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
71
|
+
const settingsDir = join(homedir(), ".claude");
|
|
72
|
+
if (existsSync(settingsPath)) {
|
|
73
|
+
try {
|
|
74
|
+
accessSync(settingsPath, constants.W_OK);
|
|
75
|
+
return { ok: true, message: t("val.settings_writable") };
|
|
76
|
+
} catch {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
message: t("val.settings_not_writable"),
|
|
80
|
+
hint: t("val.settings_chmod", { path: settingsPath })
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
accessSync(settingsDir, constants.W_OK);
|
|
86
|
+
return { ok: true, message: t("val.settings_creatable") };
|
|
87
|
+
} catch {
|
|
88
|
+
return {
|
|
89
|
+
ok: false,
|
|
90
|
+
message: t("val.claude_dir_not_writable"),
|
|
91
|
+
hint: t("val.claude_dir_chmod", { path: settingsDir })
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function checkHooksNotDisabled() {
|
|
96
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
97
|
+
if (!existsSync(settingsPath)) {
|
|
98
|
+
return { ok: true, message: t("val.hooks_unset") };
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
102
|
+
if (settings.hooks === false || settings.disableHooks === true) {
|
|
103
|
+
return {
|
|
104
|
+
ok: false,
|
|
105
|
+
message: t("val.hooks_disabled"),
|
|
106
|
+
hint: t("val.hooks_disabled_hint")
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return { ok: true, message: t("val.hooks_ok") };
|
|
110
|
+
} catch {
|
|
111
|
+
return { ok: true, message: t("val.hooks_unrestricted") };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function checkMcpNotBlocked() {
|
|
115
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
116
|
+
if (!existsSync(settingsPath)) {
|
|
117
|
+
return { ok: true, message: t("val.mcp_ok") };
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
121
|
+
if (settings.mcpServers === false || settings.disableMcp === true) {
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
message: t("val.mcp_disabled"),
|
|
125
|
+
hint: t("val.mcp_disabled_hint")
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return { ok: true, message: t("val.mcp_ok") };
|
|
129
|
+
} catch {
|
|
130
|
+
return { ok: true, message: t("val.mcp_ok") };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function checkSessionDir() {
|
|
134
|
+
const projectsDir = join(homedir(), ".claude", "projects");
|
|
135
|
+
if (existsSync(projectsDir)) {
|
|
136
|
+
return { ok: true, message: t("val.session_ok") };
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
ok: true,
|
|
140
|
+
message: t("val.session_pending")
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function checkGitUser() {
|
|
144
|
+
try {
|
|
145
|
+
const name = execFileSync("git", ["config", "user.name"], {
|
|
146
|
+
encoding: "utf-8",
|
|
147
|
+
stdio: "pipe"
|
|
148
|
+
}).trim();
|
|
149
|
+
if (name) {
|
|
150
|
+
return { ok: true, message: t("val.git_ok", { name }) };
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
ok: false,
|
|
154
|
+
message: t("val.git_no_name"),
|
|
155
|
+
hint: t("val.git_no_name_hint")
|
|
156
|
+
};
|
|
157
|
+
} catch {
|
|
158
|
+
return {
|
|
159
|
+
ok: false,
|
|
160
|
+
message: t("val.git_missing"),
|
|
161
|
+
hint: t("val.git_hint")
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export {
|
|
167
|
+
validateAll,
|
|
168
|
+
printResults
|
|
169
|
+
};
|