star-prompt
CLI 프로젝트의 setup/postinstall 흐름에 GitHub 스타 요청을 추가한다. 'star prompt', '스타 요청', '리포 스타', 'star request', '깃헙 스타 넣어줘', 'star 눌러달라고', '응원 요청' 같은 요청에 사용한다.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
CLI 프로젝트의 setup/postinstall 흐름에 GitHub 스타 요청을 추가한다. 'star prompt', '스타 요청', '리포 스타', 'star request', '깃헙 스타 넣어줘', 'star 눌러달라고', '응원 요청' 같은 요청에 사용한다.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
어떤 스킬·경로를 선택할지 묻는 메타 라우팅 요청에 사용한다. 실행하지 않고 canonical routing SSOT에서 branch와 즉시 owner 하나만 반환한다.
Use when Claude, Codex, or a Triflux worker needs live Claude↔Codex orchestration: start/ask/stop, multi-turn, peer relay, daemon UDS attach, or UDS-first with tmux fallback.
코드나 아키텍처를 분석해야 할 때 사용한다. '코드 분석', 'code analysis', '아키텍처 분석', '이 코드 어떻게 돌아가?', '구조 파악', '심층 분석', '제대로 분석', '3관점 분석', '편향 없이 분석' 같은 요청에 반드시 사용.
통합 CLI 오케스트레이터이자 실행 스킬 front door. 단일/병렬 구현·수정 작업을 자동 분류해 Codex 우선으로 dispatch 하고, 명시 플래그로 mode/parallel/consensus 등 동작을 오버라이드한다. '코드 짜줘', '구현해줘', '만들어줘', '수정해줘', '고쳐줘', 'implement', 'build', 'fix' 같은 구현/수정 요청에 사용. 플래그 상세는 argument-hint, 라우팅 정책은 .claude/rules/tfx-routing.md 참조.
triflux 진단 및 수리 도구. AskUserQuestion 기반 인터랙티브 선택지로 CLI 미발견, HUD 미표시, 캐시 오류, 스킬 미설치 등을 진단하고 자동 수정합니다. Use when: not working, broken, error, 안 돼, 이상해, 에러, 캐시, reset, doctor
코드베이스에서 파일, 함수, 클래스, 문자열을 빠르게 찾을 때 사용한다. '코드 검색', 'find in code', '어디에 있어?', '이 함수 어디서 쓰여?', '파일 찾아줘', '코드베이스 탐색' 같은 요청에 반드시 사용. 파일 위치, 심볼 사용처, 패턴 검색이 필요한 모든 상황에 적극 활용.
| name | star-prompt |
| description | CLI 프로젝트의 setup/postinstall 흐름에 GitHub 스타 요청을 추가한다. 'star prompt', '스타 요청', '리포 스타', 'star request', '깃헙 스타 넣어줘', 'star 눌러달라고', '응원 요청' 같은 요청에 사용한다. |
CLI 도구의 setup/postinstall 완료 시점에 GitHub 리포 스타 요청을 추가한다.
기본 모드는 aggressive(모달 차단형)이며, --soft를 전달하면 기존 부드러운 confirm 모드로 폴백한다.
CI/비인터랙티브 환경에서는 자동으로 soft 모드로 강등한다.
detectInteractive() ─── false → soft 모드 강제
│
✓ true
│
gh --version ─── 실패 → URL만 표시
│
✓ 설치됨
│
gh auth status ─── 실패 → URL만 표시
│
✓ 인증됨
│
gh api user/starred/{owner}/{repo}
├─ 성공 → "이미 함께하고 계시군요. ⭐" + markPrompted()
├─ 404 → 미스타로 진행
└─ 그 외 에러 → 프롬프트 없이 URL만 표시 (마커 남기지 않음)
│
✗ 미스타
│
이미 프롬프트 본 유저(마커 존재)면 즉시 스킵
│
aggressive 기본: AskUserQuestion([예, 누를게요] / [아니오]) 블로킹 선택
soft(--soft): confirm("⭐ 하나가 큰 차이를 만듭니다.")
│
├─ 아니오 → aggressive: 안내 + URL / soft: URL만 + markPrompted()
└─ 예
│
Y
│
gh api -X PUT /user/starred/{owner}/{repo}
├─ 성공 → aggressive: "감사합니다! 여러분의 ⭐가 프로젝트를 성장시킵니다."
│ soft: "함께해 주셔서 감사합니다. ⭐"
└─ 실패 → URL 폴백
│
모든 프롬프트 완료 경로는 markPrompted() 호출
ok(message): 성공 메시지 출력(초록/강조 톤)info(message): 일반 안내 메시지 출력warn(message): 경고/실패 폴백 메시지 출력confirm(message, defaultValue): soft 모드용 Y/n 확인askUserQuestion({ question, options }): aggressive 모달 선택 UI
[예, 누를게요], [아니오]starRequest 교체 패턴아래 패턴으로 기존 starRequest 함수를 전면 교체한다.
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { execFileSync } from "node:child_process";
function detectInteractive() {
if (!process.stdout.isTTY) return false;
if (process.env.CI) return false;
if (process.env.TERM === "dumb") return false;
return true;
}
function runGh(args) {
return execFileSync("gh", args, {
timeout: 10000,
encoding: "utf8",
stdio: ["pipe", "pipe", "pipe"],
});
}
function getHttpStatus(error) {
const out = [error?.stdout, error?.stderr].filter(Boolean).join("\n");
const match = out.match(/HTTP\s+(\d{3})/i) || out.match(/\b(\d{3})\b/);
return match ? Number(match[1]) : null;
}
export async function starRequest({
owner,
repo,
soft = false,
askUserQuestion,
confirm,
ok,
info,
warn,
}) {
const repoUrl = `https://github.com/${owner}/${repo}`;
const interactive = detectInteractive();
const useSoft = soft || !interactive;
const MARKER_DIR = path.join(os.homedir(), ".config", "star-prompt");
const MARKER = path.join(MARKER_DIR, `${owner}-${repo}.prompted`);
const markPrompted = () => {
fs.mkdirSync(MARKER_DIR, { recursive: true });
fs.writeFileSync(MARKER, new Date().toISOString(), "utf8");
};
if (fs.existsSync(MARKER)) return;
try {
runGh(["--version"]);
} catch {
info(repoUrl);
return;
}
try {
runGh(["auth", "status"]);
} catch {
info(repoUrl);
return;
}
let alreadyStarred = false;
try {
runGh(["api", `user/starred/${owner}/${repo}`]);
alreadyStarred = true;
} catch (error) {
const status = getHttpStatus(error);
if (status === 404) {
alreadyStarred = false;
} else {
// API 에러(404 외): 프롬프트 없이 URL만 출력, 마커 미기록
warn(repoUrl);
return;
}
}
if (alreadyStarred) {
ok("이미 함께하고 계시군요. ⭐");
markPrompted();
return;
}
let accepted = false;
if (useSoft) {
accepted = await confirm("⭐ 하나가 큰 차이를 만듭니다.", true);
} else {
const answer = await askUserQuestion({
question: "⭐ 이 프로젝트가 마음에 드셨나요? 스타를 누르시겠습니까?",
options: ["예, 누를게요", "아니오"],
});
accepted = answer === "예, 누를게요";
}
if (!accepted) {
if (useSoft) {
info(repoUrl);
} else {
info(`괜찮습니다. 나중에 마음이 바뀌시면: ${repoUrl}`);
}
markPrompted();
return;
}
try {
runGh(["api", "-X", "PUT", `/user/starred/${owner}/${repo}`]);
if (useSoft) {
ok("함께해 주셔서 감사합니다. ⭐");
} else {
ok("감사합니다! 여러분의 ⭐가 프로젝트를 성장시킵니다.");
}
} catch {
warn(repoUrl);
} finally {
markPrompted();
}
}
--soft 전달 시에만 soft 모드로 전환한다.!process.stdout.isTTY || process.env.CI || process.env.TERM === "dumb"which 대신 gh --version으로 수행한다 (크로스플랫폼).gh auth status로 수행한다.gh api user/starred/{owner}/{repo}를 사용하고, 404만 미스타로 판단한다.404 외 상태면 프롬프트를 띄우지 않고 URL만 출력하며 마커를 남기지 않는다.~/.config/star-prompt/{owner}-{repo}.promptedmarkPrompted()를 호출한다.timeout: 10000, stdio: ["pipe","pipe","pipe"]를 사용한다.| 상황 | Aggressive (기본) | Soft (--soft) |
|---|---|---|
| 이미 스타 | 이미 함께하고 계시군요. ⭐ | (동일) |
| 요청 | AskUserQuestion: ⭐ 이 프로젝트가 마음에 드셨나요? 스타를 누르시겠습니까? | ⭐ 하나가 큰 차이를 만듭니다. |
| 수락 후 | 감사합니다! 여러분의 ⭐가 프로젝트를 성장시킵니다. | 함께해 주셔서 감사합니다. ⭐ |
| 거절 | 괜찮습니다. 나중에 마음이 바뀌시면: + URL | URL만 |
| gh 미설치 | URL만 표시 | (동일) |
| gh 미인증 | URL만 표시 | (동일) |
| CI/비인터랙티브 | soft 자동 폴백 | (동일) |
| API 에러 (404 외) | 프롬프트 없이 URL만 표시, 마커 안 남김 | (동일) |
| 이미 프롬프트 본 유저 | 스킵 | (동일) |