triflux 3.2.0-dev.6 → 3.2.0-dev.8
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/README.ko.md +7 -5
- package/README.md +7 -5
- package/bin/triflux.mjs +107 -37
- package/package.json +1 -1
- package/scripts/hub-ensure.mjs +2 -1
- package/scripts/setup.mjs +34 -25
package/README.ko.md
CHANGED
|
@@ -212,11 +212,13 @@ tfx doctor
|
|
|
212
212
|
|--------|------|
|
|
213
213
|
| `tfx setup` | 스크립트 + HUD + 스킬 동기화 |
|
|
214
214
|
| `tfx doctor` | CLI 진단 + 이슈 추적 |
|
|
215
|
-
| `tfx update` | 최신 버전으로 업데이트 |
|
|
216
|
-
| `tfx list` | 설치된 스킬 목록 |
|
|
217
|
-
| `tfx version` | 버전 표시 |
|
|
218
|
-
|
|
219
|
-
축약: `tfx` = `triflux`, `tfl` = `triflux`
|
|
215
|
+
| `tfx update` | 최신 안정 버전으로 업데이트 |
|
|
216
|
+
| `tfx list` | 설치된 스킬 목록 |
|
|
217
|
+
| `tfx version` | 버전 표시 |
|
|
218
|
+
|
|
219
|
+
축약: `tfx` = `triflux`, `tfl` = `triflux`
|
|
220
|
+
|
|
221
|
+
dev 채널 업데이트: `tfx update --dev` (`dev` 별칭 지원)
|
|
220
222
|
|
|
221
223
|
### HUD 상태 표시줄
|
|
222
224
|
|
package/README.md
CHANGED
|
@@ -212,11 +212,13 @@ tfx doctor
|
|
|
212
212
|
|---------|-------------|
|
|
213
213
|
| `tfx setup` | Sync scripts + HUD + skills |
|
|
214
214
|
| `tfx doctor` | CLI diagnostics + issue tracker |
|
|
215
|
-
| `tfx update` | Update to latest version |
|
|
216
|
-
| `tfx list` | List installed skills |
|
|
217
|
-
| `tfx version` | Show version info |
|
|
218
|
-
|
|
219
|
-
Shortcuts: `tfx` = `triflux`, `tfl` = `triflux`
|
|
215
|
+
| `tfx update` | Update to latest stable version |
|
|
216
|
+
| `tfx list` | List installed skills |
|
|
217
|
+
| `tfx version` | Show version info |
|
|
218
|
+
|
|
219
|
+
Shortcuts: `tfx` = `triflux`, `tfl` = `triflux`
|
|
220
|
+
|
|
221
|
+
Dev channel update: `tfx update --dev` (`dev` alias supported)
|
|
220
222
|
|
|
221
223
|
### HUD Status Bar
|
|
222
224
|
|
package/bin/triflux.mjs
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import { copyFileSync, existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync, readdirSync, unlinkSync } from "fs";
|
|
4
4
|
import { join, dirname } from "path";
|
|
5
5
|
import { homedir } from "os";
|
|
6
|
-
import { execSync, spawn } from "child_process";
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { execSync, spawn } from "child_process";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
|
|
9
|
+
const PKG_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
9
10
|
const CLAUDE_DIR = join(homedir(), ".claude");
|
|
10
11
|
const CODEX_DIR = join(homedir(), ".codex");
|
|
11
12
|
const CODEX_CONFIG_PATH = join(CODEX_DIR, "config.toml");
|
|
@@ -67,7 +68,7 @@ function which(cmd) {
|
|
|
67
68
|
} catch { return null; }
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
function whichInShell(cmd, shell) {
|
|
71
|
+
function whichInShell(cmd, shell) {
|
|
71
72
|
const cmds = {
|
|
72
73
|
bash: `bash -c "source ~/.bashrc 2>/dev/null && command -v ${cmd} 2>/dev/null"`,
|
|
73
74
|
cmd: `cmd /c where ${cmd} 2>nul`,
|
|
@@ -82,8 +83,12 @@ function whichInShell(cmd, shell) {
|
|
|
82
83
|
stdio: ["pipe", "pipe", "ignore"],
|
|
83
84
|
}).trim();
|
|
84
85
|
return result.split(/\r?\n/)[0] || null;
|
|
85
|
-
} catch { return null; }
|
|
86
|
-
}
|
|
86
|
+
} catch { return null; }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function isDevUpdateRequested(argv = process.argv) {
|
|
90
|
+
return argv.includes("--dev") || argv.includes("@dev") || argv.includes("dev");
|
|
91
|
+
}
|
|
87
92
|
|
|
88
93
|
function checkShellAvailable(shell) {
|
|
89
94
|
const cmds = { bash: "bash --version", cmd: "cmd /c echo ok", pwsh: "pwsh -NoProfile -c echo ok" };
|
|
@@ -676,10 +681,10 @@ function cmdDoctor(options = {}) {
|
|
|
676
681
|
}
|
|
677
682
|
}
|
|
678
683
|
|
|
679
|
-
function cmdUpdate() {
|
|
680
|
-
const isDev = process.argv
|
|
681
|
-
const tagLabel = isDev ? ` ${YELLOW}
|
|
682
|
-
console.log(`\n${BOLD}triflux update${RESET}${tagLabel}\n`);
|
|
684
|
+
function cmdUpdate() {
|
|
685
|
+
const isDev = isDevUpdateRequested(process.argv);
|
|
686
|
+
const tagLabel = isDev ? ` ${YELLOW}--dev${RESET}` : "";
|
|
687
|
+
console.log(`\n${BOLD}triflux update${RESET}${tagLabel}\n`);
|
|
683
688
|
|
|
684
689
|
// 1. 설치 방식 감지
|
|
685
690
|
const pluginsFile = join(CLAUDE_DIR, "plugins", "installed_plugins.json");
|
|
@@ -731,12 +736,13 @@ function cmdUpdate() {
|
|
|
731
736
|
|
|
732
737
|
info(`검색: ${installMode === "plugin" ? "플러그인" : installMode === "npm-global" ? "npm global" : installMode === "npm-local" ? "npm local" : installMode === "git-local" ? "git 로컬 저장소" : "알 수 없음"} 설치 감지`);
|
|
733
738
|
|
|
734
|
-
// 2. 설치 방식에 따라 업데이트
|
|
735
|
-
const oldVer = PKG.version;
|
|
736
|
-
let updated = false;
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
739
|
+
// 2. 설치 방식에 따라 업데이트
|
|
740
|
+
const oldVer = PKG.version;
|
|
741
|
+
let updated = false;
|
|
742
|
+
let stoppedHubInfo = null;
|
|
743
|
+
|
|
744
|
+
try {
|
|
745
|
+
switch (installMode) {
|
|
740
746
|
case "plugin": {
|
|
741
747
|
const gitDir = pluginPath || PKG_ROOT;
|
|
742
748
|
const result = execSync("git pull", {
|
|
@@ -747,15 +753,19 @@ function cmdUpdate() {
|
|
|
747
753
|
ok(`git pull — ${result}`);
|
|
748
754
|
updated = true;
|
|
749
755
|
break;
|
|
750
|
-
}
|
|
751
|
-
case "npm-global": {
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
756
|
+
}
|
|
757
|
+
case "npm-global": {
|
|
758
|
+
stoppedHubInfo = stopHubForUpdate();
|
|
759
|
+
if (stoppedHubInfo?.pid) {
|
|
760
|
+
info(`실행 중 hub 정지 (PID ${stoppedHubInfo.pid})`);
|
|
761
|
+
}
|
|
762
|
+
const npmCmd = isDev ? "npm install -g triflux@dev" : "npm update -g triflux";
|
|
763
|
+
const result = execSync(npmCmd, {
|
|
764
|
+
encoding: "utf8",
|
|
755
765
|
timeout: 60000,
|
|
756
766
|
stdio: ["pipe", "pipe", "ignore"],
|
|
757
767
|
}).trim().split(/\r?\n/)[0];
|
|
758
|
-
ok(`${isDev ? "npm install -g @dev" : "npm update -g"} — ${result || "완료"}`);
|
|
768
|
+
ok(`${isDev ? "npm install -g triflux@dev" : "npm update -g triflux"} — ${result || "완료"}`);
|
|
759
769
|
updated = true;
|
|
760
770
|
break;
|
|
761
771
|
}
|
|
@@ -767,7 +777,7 @@ function cmdUpdate() {
|
|
|
767
777
|
cwd: process.cwd(),
|
|
768
778
|
stdio: ["pipe", "pipe", "ignore"],
|
|
769
779
|
}).trim().split(/\r?\n/)[0];
|
|
770
|
-
ok(
|
|
780
|
+
ok(`${isDev ? "npm install triflux@dev" : "npm update triflux"} — ${result || "완료"}`);
|
|
771
781
|
updated = true;
|
|
772
782
|
break;
|
|
773
783
|
}
|
|
@@ -785,11 +795,14 @@ function cmdUpdate() {
|
|
|
785
795
|
fail("설치 방식을 감지할 수 없음");
|
|
786
796
|
info("수동 업데이트: cd <triflux-dir> && git pull");
|
|
787
797
|
return;
|
|
788
|
-
}
|
|
789
|
-
} catch (e) {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
798
|
+
}
|
|
799
|
+
} catch (e) {
|
|
800
|
+
if (stoppedHubInfo && startHubAfterUpdate(stoppedHubInfo)) {
|
|
801
|
+
info("업데이트 실패 후 hub 재기동 시도");
|
|
802
|
+
}
|
|
803
|
+
fail(`업데이트 실패: ${e.message}`);
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
793
806
|
|
|
794
807
|
// 3. setup 재실행 (tfx-route.sh, HUD, 스킬 동기화)
|
|
795
808
|
if (updated) {
|
|
@@ -807,11 +820,16 @@ function cmdUpdate() {
|
|
|
807
820
|
ok(`버전: v${oldVer} (이미 최신)`);
|
|
808
821
|
}
|
|
809
822
|
|
|
810
|
-
// setup 재실행
|
|
811
|
-
console.log("");
|
|
812
|
-
info("setup 재실행 중...");
|
|
813
|
-
cmdSetup();
|
|
814
|
-
|
|
823
|
+
// setup 재실행
|
|
824
|
+
console.log("");
|
|
825
|
+
info("setup 재실행 중...");
|
|
826
|
+
cmdSetup();
|
|
827
|
+
|
|
828
|
+
if (stoppedHubInfo) {
|
|
829
|
+
if (startHubAfterUpdate(stoppedHubInfo)) info("hub 재기동 완료");
|
|
830
|
+
else warn("hub 재기동 실패 — `tfx hub start`로 수동 시작 필요");
|
|
831
|
+
}
|
|
832
|
+
}
|
|
815
833
|
|
|
816
834
|
console.log(`${GREEN}${BOLD}업데이트 완료${RESET}\n`);
|
|
817
835
|
}
|
|
@@ -914,8 +932,8 @@ ${updateNotice}
|
|
|
914
932
|
${WHITE_BRIGHT}tfx doctor${RESET} ${GRAY}CLI 진단 + 이슈 확인${RESET}
|
|
915
933
|
${DIM} --fix${RESET} ${GRAY}진단 + 자동 수정${RESET}
|
|
916
934
|
${DIM} --reset${RESET} ${GRAY}캐시 전체 초기화${RESET}
|
|
917
|
-
${WHITE_BRIGHT}tfx update${RESET} ${GRAY}최신 버전으로 업데이트${RESET}
|
|
918
|
-
${DIM} --dev${RESET}
|
|
935
|
+
${WHITE_BRIGHT}tfx update${RESET} ${GRAY}최신 안정 버전으로 업데이트${RESET}
|
|
936
|
+
${DIM} --dev / dev${RESET} ${GRAY}dev 태그로 업데이트${RESET}
|
|
919
937
|
${WHITE_BRIGHT}tfx list${RESET} ${GRAY}설치된 스킬 목록${RESET}
|
|
920
938
|
${WHITE_BRIGHT}tfx hub${RESET} ${GRAY}MCP 메시지 버스 관리 (start/stop/status)${RESET}
|
|
921
939
|
${WHITE_BRIGHT}tfx team${RESET} ${GRAY}멀티-CLI 팀 모드 (tmux + Hub)${RESET}
|
|
@@ -989,8 +1007,60 @@ async function cmdCodexTeam() {
|
|
|
989
1007
|
|
|
990
1008
|
// ── hub 서브커맨드 ──
|
|
991
1009
|
|
|
992
|
-
const HUB_PID_DIR = join(homedir(), ".claude", "cache", "tfx-hub");
|
|
993
|
-
const HUB_PID_FILE = join(HUB_PID_DIR, "hub.pid");
|
|
1010
|
+
const HUB_PID_DIR = join(homedir(), ".claude", "cache", "tfx-hub");
|
|
1011
|
+
const HUB_PID_FILE = join(HUB_PID_DIR, "hub.pid");
|
|
1012
|
+
|
|
1013
|
+
function sleepMs(ms) {
|
|
1014
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
function stopHubForUpdate() {
|
|
1018
|
+
if (!existsSync(HUB_PID_FILE)) return null;
|
|
1019
|
+
let info = null;
|
|
1020
|
+
try {
|
|
1021
|
+
info = JSON.parse(readFileSync(HUB_PID_FILE, "utf8"));
|
|
1022
|
+
process.kill(info.pid, 0);
|
|
1023
|
+
} catch {
|
|
1024
|
+
try { unlinkSync(HUB_PID_FILE); } catch {}
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
try {
|
|
1029
|
+
if (process.platform === "win32") {
|
|
1030
|
+
execSync(`taskkill /PID ${info.pid} /T /F`, {
|
|
1031
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
1032
|
+
timeout: 10000,
|
|
1033
|
+
});
|
|
1034
|
+
} else {
|
|
1035
|
+
process.kill(info.pid, "SIGTERM");
|
|
1036
|
+
}
|
|
1037
|
+
} catch {
|
|
1038
|
+
try { process.kill(info.pid, "SIGKILL"); } catch {}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
sleepMs(300);
|
|
1042
|
+
try { unlinkSync(HUB_PID_FILE); } catch {}
|
|
1043
|
+
return info;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
function startHubAfterUpdate(info) {
|
|
1047
|
+
if (!info) return false;
|
|
1048
|
+
const serverPath = join(PKG_ROOT, "hub", "server.mjs");
|
|
1049
|
+
if (!existsSync(serverPath)) return false;
|
|
1050
|
+
const port = Number(info?.port) > 0 ? String(info.port) : String(process.env.TFX_HUB_PORT || "27888");
|
|
1051
|
+
|
|
1052
|
+
try {
|
|
1053
|
+
const child = spawn(process.execPath, [serverPath], {
|
|
1054
|
+
env: { ...process.env, TFX_HUB_PORT: port },
|
|
1055
|
+
stdio: "ignore",
|
|
1056
|
+
detached: true,
|
|
1057
|
+
});
|
|
1058
|
+
child.unref();
|
|
1059
|
+
return true;
|
|
1060
|
+
} catch {
|
|
1061
|
+
return false;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
994
1064
|
|
|
995
1065
|
// 설치된 CLI에 tfx-hub MCP 서버 자동 등록 (1회 설정, 이후 재실행 불필요)
|
|
996
1066
|
function autoRegisterMcp(mcpUrl) {
|
package/package.json
CHANGED
package/scripts/hub-ensure.mjs
CHANGED
|
@@ -7,9 +7,10 @@ import { existsSync, readFileSync } from "fs";
|
|
|
7
7
|
import { join, dirname } from "path";
|
|
8
8
|
import { homedir } from "os";
|
|
9
9
|
import { spawn } from "child_process";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
10
11
|
|
|
11
12
|
const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1"]);
|
|
12
|
-
const PLUGIN_ROOT = dirname(dirname(
|
|
13
|
+
const PLUGIN_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
13
14
|
const HUB_PID_FILE = join(homedir(), ".claude", "cache", "tfx-hub", "hub.pid");
|
|
14
15
|
|
|
15
16
|
function formatHostForUrl(host) {
|
package/scripts/setup.mjs
CHANGED
|
@@ -8,8 +8,9 @@ import { copyFileSync, mkdirSync, readFileSync, writeFileSync, readdirSync, exis
|
|
|
8
8
|
import { join, dirname } from "path";
|
|
9
9
|
import { homedir } from "os";
|
|
10
10
|
import { spawn } from "child_process";
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
|
|
13
|
+
const PLUGIN_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
13
14
|
const CLAUDE_DIR = join(homedir(), ".claude");
|
|
14
15
|
const CODEX_DIR = join(homedir(), ".codex");
|
|
15
16
|
const CODEX_CONFIG_PATH = join(CODEX_DIR, "config.toml");
|
|
@@ -51,15 +52,24 @@ const SYNC_MAP = [
|
|
|
51
52
|
},
|
|
52
53
|
];
|
|
53
54
|
|
|
54
|
-
function getVersion(filePath) {
|
|
55
|
-
try {
|
|
56
|
-
const content = readFileSync(filePath, "utf8");
|
|
57
|
-
const match = content.match(/VERSION\s*=\s*"([^"]+)"/);
|
|
58
|
-
return match ? match[1] : null;
|
|
59
|
-
} catch {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
55
|
+
function getVersion(filePath) {
|
|
56
|
+
try {
|
|
57
|
+
const content = readFileSync(filePath, "utf8");
|
|
58
|
+
const match = content.match(/VERSION\s*=\s*"([^"]+)"/);
|
|
59
|
+
return match ? match[1] : null;
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function shouldSyncTextFile(src, dst) {
|
|
66
|
+
if (!existsSync(dst)) return true;
|
|
67
|
+
try {
|
|
68
|
+
return readFileSync(src, "utf8") !== readFileSync(dst, "utf8");
|
|
69
|
+
} catch {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
63
73
|
|
|
64
74
|
function escapeRegExp(value) {
|
|
65
75
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -114,15 +124,13 @@ for (const { src, dst, label } of SYNC_MAP) {
|
|
|
114
124
|
copyFileSync(src, dst);
|
|
115
125
|
try { chmodSync(dst, 0o755); } catch {}
|
|
116
126
|
synced++;
|
|
117
|
-
} else {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
}
|
|
127
|
+
} else {
|
|
128
|
+
if (shouldSyncTextFile(src, dst)) {
|
|
129
|
+
copyFileSync(src, dst);
|
|
130
|
+
try { chmodSync(dst, 0o755); } catch {}
|
|
131
|
+
synced++;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
// ── 스킬 동기화 ──
|
|
@@ -349,11 +357,12 @@ ${B}╚════════════════════════
|
|
|
349
357
|
${G}✓${R} ${synced > 0 ? synced + " files synced" : "all files up to date"}
|
|
350
358
|
${G}✓${R} HUD statusLine → settings.json
|
|
351
359
|
|
|
352
|
-
${B}Commands:${R}
|
|
353
|
-
${C}triflux${R} setup 파일 동기화 + HUD 설정
|
|
354
|
-
${C}triflux${R} doctor CLI 진단 (Codex/Gemini 확인)
|
|
355
|
-
${C}triflux${R} list 설치된 스킬 목록
|
|
356
|
-
${C}triflux${R} update 최신 버전으로 업데이트
|
|
360
|
+
${B}Commands:${R}
|
|
361
|
+
${C}triflux${R} setup 파일 동기화 + HUD 설정
|
|
362
|
+
${C}triflux${R} doctor CLI 진단 (Codex/Gemini 확인)
|
|
363
|
+
${C}triflux${R} list 설치된 스킬 목록
|
|
364
|
+
${C}triflux${R} update 최신 안정 버전으로 업데이트
|
|
365
|
+
${C}triflux${R} update --dev dev 채널로 업데이트 (${D}dev 별칭 지원${R})
|
|
357
366
|
|
|
358
367
|
${B}Shortcuts:${R}
|
|
359
368
|
${C}tfx${R} triflux 축약
|