@team-semicolon/semo-cli 3.0.27 → 3.0.29
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/index.js +131 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -766,7 +766,7 @@ async function confirmOverwrite(itemName, itemPath) {
|
|
|
766
766
|
type: "confirm",
|
|
767
767
|
name: "shouldOverwrite",
|
|
768
768
|
message: chalk_1.default.yellow(`${itemName} 이미 존재합니다. SEMO 기준으로 덮어쓰시겠습니까?`),
|
|
769
|
-
default:
|
|
769
|
+
default: true,
|
|
770
770
|
},
|
|
771
771
|
]);
|
|
772
772
|
return shouldOverwrite;
|
|
@@ -806,8 +806,12 @@ function checkRequiredTools() {
|
|
|
806
806
|
{
|
|
807
807
|
name: "Supabase CLI",
|
|
808
808
|
installed: false,
|
|
809
|
-
installCmd: isWindows ? "
|
|
809
|
+
installCmd: isWindows ? "winget install Supabase.CLI" : "brew install supabase/tap/supabase",
|
|
810
810
|
description: "Supabase 데이터베이스 연동",
|
|
811
|
+
windowsAltCmds: isWindows ? [
|
|
812
|
+
"scoop bucket add supabase https://github.com/supabase/scoop-bucket.git && scoop install supabase",
|
|
813
|
+
"choco install supabase"
|
|
814
|
+
] : undefined,
|
|
811
815
|
},
|
|
812
816
|
];
|
|
813
817
|
// GitHub CLI 확인
|
|
@@ -849,6 +853,12 @@ async function showToolsStatus() {
|
|
|
849
853
|
console.log(chalk_1.default.cyan("📋 설치 명령어:"));
|
|
850
854
|
for (const tool of missingTools) {
|
|
851
855
|
console.log(chalk_1.default.white(` ${tool.installCmd}`));
|
|
856
|
+
if (tool.windowsAltCmds && tool.windowsAltCmds.length > 0) {
|
|
857
|
+
console.log(chalk_1.default.gray(" (대체 방법)"));
|
|
858
|
+
for (const altCmd of tool.windowsAltCmds) {
|
|
859
|
+
console.log(chalk_1.default.gray(` ${altCmd}`));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
852
862
|
}
|
|
853
863
|
console.log();
|
|
854
864
|
const { continueWithout } = await inquirer_1.default.prompt([
|
|
@@ -965,13 +975,15 @@ program
|
|
|
965
975
|
if (options.gitignore !== false) {
|
|
966
976
|
updateGitignore(cwd);
|
|
967
977
|
}
|
|
968
|
-
// 9.
|
|
978
|
+
// 9. Hooks 설치 (대화 로깅)
|
|
979
|
+
await setupHooks(cwd, false);
|
|
980
|
+
// 10. CLAUDE.md 생성
|
|
969
981
|
await setupClaudeMd(cwd, extensionsToInstall, options.force);
|
|
970
|
-
//
|
|
982
|
+
// 11. Extensions 심볼릭 링크 (agents/skills 병합)
|
|
971
983
|
if (extensionsToInstall.length > 0) {
|
|
972
984
|
await setupExtensionSymlinks(cwd, extensionsToInstall);
|
|
973
985
|
}
|
|
974
|
-
//
|
|
986
|
+
// 12. 설치 검증
|
|
975
987
|
const verificationResult = verifyInstallation(cwd, extensionsToInstall);
|
|
976
988
|
printVerificationResult(verificationResult);
|
|
977
989
|
// 완료 메시지
|
|
@@ -1896,6 +1908,117 @@ semo-system/
|
|
|
1896
1908
|
console.log(chalk_1.default.green("✓ .gitignore 생성됨 (SEMO 규칙 포함)"));
|
|
1897
1909
|
}
|
|
1898
1910
|
}
|
|
1911
|
+
// === Hooks 설치/업데이트 ===
|
|
1912
|
+
async function setupHooks(cwd, isUpdate = false) {
|
|
1913
|
+
const action = isUpdate ? "업데이트" : "설치";
|
|
1914
|
+
console.log(chalk_1.default.cyan(`\n🪝 Claude Code Hooks ${action}`));
|
|
1915
|
+
console.log(chalk_1.default.gray(" 전체 대화 로깅 시스템\n"));
|
|
1916
|
+
const hooksDir = path.join(cwd, "semo-system", "semo-hooks");
|
|
1917
|
+
// semo-hooks 디렉토리 확인
|
|
1918
|
+
if (!fs.existsSync(hooksDir)) {
|
|
1919
|
+
console.log(chalk_1.default.yellow(" ⚠ semo-hooks 디렉토리 없음 (건너뜀)"));
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
// 1. npm install
|
|
1923
|
+
console.log(chalk_1.default.gray(" → 의존성 설치 중..."));
|
|
1924
|
+
try {
|
|
1925
|
+
(0, child_process_1.execSync)("npm install", {
|
|
1926
|
+
cwd: hooksDir,
|
|
1927
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1928
|
+
});
|
|
1929
|
+
}
|
|
1930
|
+
catch {
|
|
1931
|
+
console.log(chalk_1.default.yellow(" ⚠ npm install 실패 (건너뜀)"));
|
|
1932
|
+
return;
|
|
1933
|
+
}
|
|
1934
|
+
// 2. 빌드
|
|
1935
|
+
console.log(chalk_1.default.gray(" → 빌드 중..."));
|
|
1936
|
+
try {
|
|
1937
|
+
(0, child_process_1.execSync)("npm run build", {
|
|
1938
|
+
cwd: hooksDir,
|
|
1939
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
catch {
|
|
1943
|
+
console.log(chalk_1.default.yellow(" ⚠ 빌드 실패 (건너뜀)"));
|
|
1944
|
+
return;
|
|
1945
|
+
}
|
|
1946
|
+
// 3. settings.local.json 설정
|
|
1947
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
1948
|
+
const settingsPath = path.join(homeDir, ".claude", "settings.local.json");
|
|
1949
|
+
const hooksCmd = `node ${path.join(hooksDir, "dist", "index.js")}`;
|
|
1950
|
+
// hooks 설정 객체
|
|
1951
|
+
const hooksConfig = {
|
|
1952
|
+
SessionStart: [
|
|
1953
|
+
{
|
|
1954
|
+
matcher: "",
|
|
1955
|
+
hooks: [
|
|
1956
|
+
{
|
|
1957
|
+
type: "command",
|
|
1958
|
+
command: `${hooksCmd} session-start`,
|
|
1959
|
+
timeout: 10,
|
|
1960
|
+
},
|
|
1961
|
+
],
|
|
1962
|
+
},
|
|
1963
|
+
],
|
|
1964
|
+
UserPromptSubmit: [
|
|
1965
|
+
{
|
|
1966
|
+
matcher: "",
|
|
1967
|
+
hooks: [
|
|
1968
|
+
{
|
|
1969
|
+
type: "command",
|
|
1970
|
+
command: `${hooksCmd} user-prompt`,
|
|
1971
|
+
timeout: 5,
|
|
1972
|
+
},
|
|
1973
|
+
],
|
|
1974
|
+
},
|
|
1975
|
+
],
|
|
1976
|
+
Stop: [
|
|
1977
|
+
{
|
|
1978
|
+
matcher: "",
|
|
1979
|
+
hooks: [
|
|
1980
|
+
{
|
|
1981
|
+
type: "command",
|
|
1982
|
+
command: `${hooksCmd} stop`,
|
|
1983
|
+
timeout: 10,
|
|
1984
|
+
},
|
|
1985
|
+
],
|
|
1986
|
+
},
|
|
1987
|
+
],
|
|
1988
|
+
SessionEnd: [
|
|
1989
|
+
{
|
|
1990
|
+
matcher: "",
|
|
1991
|
+
hooks: [
|
|
1992
|
+
{
|
|
1993
|
+
type: "command",
|
|
1994
|
+
command: `${hooksCmd} session-end`,
|
|
1995
|
+
timeout: 10,
|
|
1996
|
+
},
|
|
1997
|
+
],
|
|
1998
|
+
},
|
|
1999
|
+
],
|
|
2000
|
+
};
|
|
2001
|
+
// 기존 설정 로드 또는 새로 생성
|
|
2002
|
+
let existingSettings = {};
|
|
2003
|
+
const claudeConfigDir = path.join(homeDir, ".claude");
|
|
2004
|
+
if (!fs.existsSync(claudeConfigDir)) {
|
|
2005
|
+
fs.mkdirSync(claudeConfigDir, { recursive: true });
|
|
2006
|
+
}
|
|
2007
|
+
if (fs.existsSync(settingsPath)) {
|
|
2008
|
+
try {
|
|
2009
|
+
existingSettings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
2010
|
+
}
|
|
2011
|
+
catch {
|
|
2012
|
+
existingSettings = {};
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
// hooks 설정 병합
|
|
2016
|
+
existingSettings.hooks = hooksConfig;
|
|
2017
|
+
// 설정 저장
|
|
2018
|
+
fs.writeFileSync(settingsPath, JSON.stringify(existingSettings, null, 2));
|
|
2019
|
+
console.log(chalk_1.default.green(` ✓ Hooks ${action} 완료`));
|
|
2020
|
+
console.log(chalk_1.default.gray(` 설정: ${settingsPath}`));
|
|
2021
|
+
}
|
|
1899
2022
|
// === Context Mesh 초기화 ===
|
|
1900
2023
|
async function setupContextMesh(cwd) {
|
|
1901
2024
|
console.log(chalk_1.default.cyan("\n🧠 Context Mesh 초기화"));
|
|
@@ -2721,7 +2844,9 @@ program
|
|
|
2721
2844
|
}
|
|
2722
2845
|
}
|
|
2723
2846
|
}
|
|
2724
|
-
// ===
|
|
2847
|
+
// === 6. Hooks 업데이트 ===
|
|
2848
|
+
await setupHooks(cwd, true);
|
|
2849
|
+
// === 7. 설치 검증 ===
|
|
2725
2850
|
const verificationResult = verifyInstallation(cwd, installedExtensions);
|
|
2726
2851
|
printVerificationResult(verificationResult);
|
|
2727
2852
|
if (verificationResult.success) {
|