@cliphijack/santaclaude 0.9.3 → 0.9.4

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/santaclaude.js +24 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cliphijack/santaclaude",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "publishConfig": { "access": "public" },
5
5
  "description": "SantaClaude 커넥터 — 클라우드 예약을 내 로컬 Claude(tmux)에 발사",
6
6
  "bin": { "santaclaude": "./santaclaude.js" },
package/santaclaude.js CHANGED
@@ -114,6 +114,30 @@ async function run(conf) {
114
114
  // 루돌프 = 작업장(session) 안의 윈도우(탭). 별도 세션 아님.
115
115
  async function runControl(cmd) {
116
116
  try {
117
+ if (cmd.action === 'skill') {
118
+ // 마켓 스킬 이식 — 그 루돌프 프로젝트 폴더 .claude/skills/<name>/ 에 설치 + claude에 적용 주입
119
+ const w = (cmd.name && windowExists(session, cmd.name)) ? (session + ':' + cmd.name) : pane;
120
+ let r; try { r = await fetch(api + '/api/skill/get?token=' + encodeURIComponent(token) + '&id=' + encodeURIComponent(cmd.skillId || '')); } catch (e) { console.warn(' 스킬 받기 실패'); return; }
121
+ if (!r.ok) { console.warn(' 스킬 없음'); return; }
122
+ const sk = await r.json();
123
+ // 그 창의 작업 폴더 (없으면 홈)
124
+ let cwd = os.homedir();
125
+ try { const pc = execFileSync('tmux', ['display-message', '-t', w, '-p', '#{pane_current_path}'], { encoding: 'utf8' }).trim(); if (pc) cwd = pc; } catch (e) {}
126
+ const sdir = path.join(cwd, '.claude', 'skills', sk.name);
127
+ let cnt = 0;
128
+ for (const f of (sk.files || [])) {
129
+ const safe = String(f.path || '').replace(/\\/g, '/').replace(/(^|\/)\.\.(\/|$)/g, '/').replace(/^\/+/, '');
130
+ if (!safe) continue;
131
+ const fp = path.join(sdir, safe);
132
+ if (!fp.startsWith(sdir)) continue; // 경로 탈출 방지
133
+ try { fs.mkdirSync(path.dirname(fp), { recursive: true }); fs.writeFileSync(fp, String(f.content || '')); cnt++; } catch (e) {}
134
+ }
135
+ console.log(` 🧩 스킬 "${sk.name}" ${cnt}개 파일 이식 → ${sdir}`);
136
+ const msg = sk.prompt && sk.prompt.trim() ? sk.prompt.trim() : ('스킬 "' + sk.name + '"이 .claude/skills/' + sk.name + '/ 에 이식됐어. SKILL.md 읽고 적용해줘.');
137
+ execFileSync('tmux', ['send-keys', '-t', w, '-l', msg]);
138
+ setTimeout(() => { try { execFileSync('tmux', ['send-keys', '-t', w, 'Enter']); } catch (e) {} }, 300);
139
+ return;
140
+ }
117
141
  if (cmd.action === 'image') {
118
142
  // 웹이 올린 이미지를 받아 로컬에 저장하고 claude에 경로 주입
119
143
  const dir = path.join(os.homedir(), '.santaclaude', 'img');