@yesdgq/claude-buddy 1.1.1012 → 1.1.1014

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.md CHANGED
@@ -29,9 +29,10 @@ Claude Buddy is a simple and easy-to-use CLI tool that provides a visual way to
29
29
  ## Screenshot
30
30
 
31
31
 
32
- <center>
33
- <img src="https://i.postimg.cc/kXV5DcLt/Screen-Shot-2026-01-22-094423-493.png" alt="Claude Buddy Interface">
34
- </center>
32
+ <div style="display: flex; justify-content: center; gap: 16px; flex-wrap: wrap;">
33
+ <img src="https://i.postimg.cc/76ss68sL/Screen-Shot-2026-03-18-095002-643.png" alt="Claude Buddy Interface" style="max-width: 48%; height: auto;">
34
+ <img src="https://i.postimg.cc/HkdhB2yd/Screen-Shot-2026-03-18-095041-515.png" alt="Claude Buddy Interface" style="max-width: 48%; height: auto;">
35
+ </div>
35
36
 
36
37
 
37
38
  ## Prerequisites
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html lang="zh-CN">
2
+ <html lang="zh-CN" data-theme="dark">
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -20,16 +20,29 @@
20
20
  <div class="container">
21
21
  <div class="header-row">
22
22
  <div class="title-group">
23
- <h1 class="page-title">Claude Buddy</h1>
24
- <div class="lang-selector">
23
+ <h1 class="page-title">
24
+ Claude Buddy
25
+ </h1>
26
+ <div class="controls-row">
27
+ <!-- 主题切换 -->
25
28
  <button
26
- v-for="lang in languages"
27
- :key="lang.code"
28
- :class="['lang-btn', { 'lang-btn-active': currentLang === lang.code }]"
29
- @click="setLanguage(lang.code)"
29
+ @click="toggleTheme"
30
+ class="theme-toggle"
31
+ :title="isDark ? t.switchToLight : t.switchToDark"
30
32
  >
31
- {{ lang.label }}
33
+ <i :class="isDark ? 'fa fa-moon-o' : 'fa fa-sun-o'"></i>
32
34
  </button>
35
+ <!-- 语言选择 -->
36
+ <div class="lang-selector">
37
+ <button
38
+ v-for="lang in languages"
39
+ :key="lang.code"
40
+ :class="['lang-btn', { 'lang-btn-active': currentLang === lang.code }]"
41
+ @click="setLanguage(lang.code)"
42
+ >
43
+ {{ lang.label }}
44
+ </button>
45
+ </div>
33
46
  </div>
34
47
  </div>
35
48
  <div class="cli-selector">
@@ -56,72 +69,42 @@
56
69
 
57
70
  <transition name="fade">
58
71
  <div v-if="showHelp" class="help-content">
59
- <div>
60
- <p style="line-height: 1.5; margin-bottom: 0.5rem;">{{ t.helpDescription }}</p>
61
- </div>
62
- <div class="info-section">
63
- <ul style="padding-left: 0; list-style: none; margin-bottom: 1rem; margin-top: 1.5rem;">
64
- <li style="margin-bottom: 0.5rem;">
65
- <strong>{{ t.feature1Title }}</strong>:{{ t.feature1Desc }}
66
- </li>
67
- <li style="margin-bottom: 0.5rem;">
68
- <strong>{{ t.feature2Title }}</strong>:{{ t.feature2Desc }}
69
- </li>
70
- <li style="margin-bottom: 0.5rem;">
71
- <strong>{{ t.feature3Title }}</strong>:{{ t.feature3Desc }}
72
- </li>
73
- <li style="margin-bottom: 0.5rem;">
74
- <strong>{{ t.feature4Title }}</strong>:{{ t.feature4Desc }}
75
- </li>
76
- <li style="margin-bottom: 0.5rem;">
77
- <strong>{{ t.feature5Title }}</strong>:{{ t.feature5Desc }}
78
- </li>
79
- </ul>
72
+ <p class="help-description">{{ t.helpDescription }}</p>
73
+ <div class="info-section">
74
+ <ul class="feature-list">
75
+ <li><strong>{{ t.feature1Title }}</strong>:{{ t.feature1Desc }}</li>
76
+ <li><strong>{{ t.feature2Title }}</strong>:{{ t.feature2Desc }}</li>
77
+ <li><strong>{{ t.feature3Title }}</strong>:{{ t.feature3Desc }}</li>
78
+ <li><strong>{{ t.feature4Title }}</strong>:{{ t.feature4Desc }}</li>
79
+ <li><strong>{{ t.feature5Title }}</strong>:{{ t.feature5Desc }}</li>
80
+ </ul>
80
81
 
81
- <h3 style="margin-top: 1.5rem;">
82
- <i class="fa fa-book text-blue-500"></i>
83
- {{ t.commandUsageTitle }}
84
- </h3>
85
- <ul style="padding-left: 1rem;">
86
- <li>
87
- <i class="fa fa-chevron-right"></i>
88
- <code>ccby config</code> {{ t.command1 }}
89
- </li>
90
- <li>
91
- <i class="fa fa-chevron-right"></i>
92
- <code>ccby</code> 或 <code>claude</code> {{ t.command2 }}
93
- </li>
94
- <li>
95
- <i class="fa fa-chevron-right"></i>
96
- <code>ccby -r</code> {{ t.command3 }}
97
- </li>
98
- <li>
99
- <i class="fa fa-chevron-right"></i>
100
- <code>ccby -c</code> {{ t.command4 }}
101
- </li>
102
- <li>
103
- <i class="fa fa-chevron-right"></i>
104
- <code>ccby --version</code> {{ t.command5 }}
105
- </li>
106
- <li>
107
- <i class="fa fa-chevron-right"></i>
108
- <code>claude --version</code> {{ t.command6 }}
109
- </li>
110
- </ul>
82
+ <h3 class="command-title">
83
+ <i class="fa fa-book"></i>
84
+ {{ t.commandUsageTitle }}
85
+ </h3>
86
+ <ul class="command-list">
87
+ <li><i class="fa fa-chevron-right"></i><code>ccby config</code> {{ t.command1 }}</li>
88
+ <li><i class="fa fa-chevron-right"></i><code>ccby</code> {{ t.command2 }}</li>
89
+ <li><i class="fa fa-chevron-right"></i><code>ccby -r</code> {{ t.command3 }}</li>
90
+ <li><i class="fa fa-chevron-right"></i><code>ccby -c</code> {{ t.command4 }}</li>
91
+ <li><i class="fa fa-chevron-right"></i><code>ccby --version</code> {{ t.command5 }}</li>
92
+ <li><i class="fa fa-chevron-right"></i><code>claude --version</code> {{ t.command6 }}</li>
93
+ </ul>
94
+ </div>
111
95
 
112
- <div style="margin-top: 1.5rem; padding: 0.75rem; background-color: #e5e7eb; border-radius: 5px; color: #ef4444;">
96
+ <div class="notice-box">
113
97
  <i class="fa fa-exclamation-triangle"></i>
114
98
  {{ t.restartNotice }}
115
99
  </div>
116
100
  </div>
117
- </div>
118
101
  </transition>
119
102
  </div>
120
103
 
121
104
  <!-- 加载状态 -->
122
105
  <div v-if="loading" class="loading-container">
123
106
  <i class="fa fa-spinner fa-spin"></i>
124
- <p>{{ t.loading }}</p>
107
+ <p>{{ funLoadingMessage }}</p>
125
108
  </div>
126
109
 
127
110
 
@@ -187,7 +170,7 @@
187
170
  <input
188
171
  v-model="auth.BASE_URL"
189
172
  type="text"
190
- placeholder="https://example.com/"
173
+ :placeholder="t.baseUrlPlaceholder"
191
174
  >
192
175
  </div>
193
176
 
@@ -201,7 +184,7 @@
201
184
  <input
202
185
  v-model="auth.TOKEN"
203
186
  :type="showTokens[index] ? 'text' : 'password'"
204
- placeholder="your-token-here"
187
+ :placeholder="t.tokenPlaceholder"
205
188
  >
206
189
  <button
207
190
  @click="toggleTokenVisibility(index)"
@@ -357,6 +340,6 @@
357
340
  </div>
358
341
  </div>
359
342
 
360
- <script src="config.js"></script>
343
+ <script src="config.js" defer></script>
361
344
  </body>
362
345
  </html>
package/assets/config.js CHANGED
@@ -15,6 +15,7 @@ createApp({
15
15
  showHelp: false,
16
16
  currentCli: 'Claude',
17
17
  currentLang: 'en',
18
+ isDark: true,
18
19
  languages: [
19
20
  { code: 'en', label: 'English' },
20
21
  { code: 'zh', label: '中文' }
@@ -38,17 +39,17 @@ createApp({
38
39
  translations: {
39
40
  en: {
40
41
  helpTitle: 'User Guide',
41
- helpDescription: 'Claude Buddy is an easy-to-use CLI tool that helps you quickly configure API keys, model mappings, and other settings for CLI tools like Claude Code, Codex, and Gemini through a visual interface. It greatly simplifies your usage of these CLI tools.',
42
+ helpDescription: 'Claude Buddy helps you quickly configure API keys, models, and environment variables for Claude Code and other CLI tools through a visual interface.',
42
43
  feature1Title: 'API Key Management',
43
- feature1Desc: 'Easily store, switch, and manage multiple API keys',
44
+ feature1Desc: 'Store and switch between multiple API keys easily',
44
45
  feature2Title: 'Model Mapping',
45
- feature2Desc: 'Conveniently customize and manage model configurations',
46
- feature3Title: 'One-time Installation, Permanent Use',
47
- feature3Desc: 'Local deployment with long-term usage after installation',
48
- feature4Title: 'Quick Configuration',
49
- feature4Desc: 'Visual interface, complete settings in seconds',
50
- feature5Title: 'Developer Friendly',
51
- feature5Desc: 'Designed for developers focused on coding',
46
+ feature2Desc: 'Customize model names and configurations',
47
+ feature3Title: 'Install Once, Use Forever',
48
+ feature3Desc: 'Local setup with permanent use after installation',
49
+ feature4Title: 'Quick Setup',
50
+ feature4Desc: 'Visual interface, configure in seconds',
51
+ feature5Title: 'Developer First',
52
+ feature5Desc: 'Built for developers who love efficiency',
52
53
  commandUsageTitle: 'Command Usage',
53
54
  command1: 'Open the configuration page to set your API URL and access token',
54
55
  command2: 'Launch Claude Code',
@@ -80,8 +81,8 @@ createApp({
80
81
  saveConfig: 'Save Configuration',
81
82
  saving: 'Saving...',
82
83
  reload: 'Reload',
83
- confirmDeleteWithName: 'Are you sure you want to delete configuration {name}?',
84
- confirmDeleteWithIndex: 'Are you sure you want to delete configuration #{index}?',
84
+ confirmDeleteWithName: 'Delete configuration "{name}"? This action cannot be undone.',
85
+ confirmDeleteWithIndex: 'Delete configuration #{index}? This action cannot be undone.',
85
86
  emptyConfigCannotDeleteToast: 'Empty configuration cannot be deleted',
86
87
  configLoadSuccess: 'Configuration loaded successfully',
87
88
  configLoadFailed: 'Failed to load configuration',
@@ -94,21 +95,25 @@ createApp({
94
95
  notAvailableYet: 'Not available yet, stay tuned',
95
96
  saveFailed: 'Save failed',
96
97
  cancel: 'Cancel',
97
- confirm: 'Confirm'
98
+ confirm: 'Confirm',
99
+ switchToLight: 'Switch to light mode',
100
+ switchToDark: 'Switch to dark mode',
101
+ baseUrlPlaceholder: 'https://api.example.com',
102
+ tokenPlaceholder: 'Enter your API token'
98
103
  },
99
104
  zh: {
100
105
  helpTitle: '使用说明',
101
- helpDescription: 'Claude Buddy 是一款简单易用的 CLI 工具,通过可视化方式快速配置 Claude Code、Codex Gemini 等CLI的API密钥、模型映射等信息,可极大的方便和简化您对Claude Code等CLI的使用。',
106
+ helpDescription: 'Claude Buddy 是一款简单易用的 CLI 工具,通过可视化界面帮助您快速配置 Claude Code CLI 工具的 API 密钥、模型和环境变量。',
102
107
  feature1Title: 'API 密钥管理',
103
- feature1Desc: '轻松存储、切换和管理多组API 密钥',
108
+ feature1Desc: '轻松存储和切换多组 API 密钥',
104
109
  feature2Title: '模型映射',
105
- feature2Desc: '便捷地自定义和管理模型配置',
110
+ feature2Desc: '自定义模型名称和配置',
106
111
  feature3Title: '一次安装永久使用',
107
- feature3Desc: '本地部署,安装后可长久使用',
112
+ feature3Desc: '本地部署,安装后长期使用',
108
113
  feature4Title: '快速配置',
109
- feature4Desc: '可视化界面,几秒钟即可完成设置',
114
+ feature4Desc: '可视化界面,几秒完成设置',
110
115
  feature5Title: '开发者友好',
111
- feature5Desc: '专为专注于编码的开发者打造',
116
+ feature5Desc: '专为追求效率的开发者打造',
112
117
  commandUsageTitle: '命令使用',
113
118
  command1: '打开配置页面,配置您的 API 地址和访问令牌(TOKEN)',
114
119
  command2: '启动claude code',
@@ -140,8 +145,8 @@ createApp({
140
145
  saveConfig: '保存配置',
141
146
  saving: '保存中...',
142
147
  reload: '重新加载',
143
- confirmDeleteWithName: '确定要删除配置 {name} 吗?',
144
- confirmDeleteWithIndex: '确定要删除配置 #{index} 吗?',
148
+ confirmDeleteWithName: '确定要删除配置 "{name}" 吗?此操作无法撤销。',
149
+ confirmDeleteWithIndex: '确定要删除配置 #{index} 吗?此操作无法撤销。',
145
150
  emptyConfigCannotDeleteToast: '空配置项不能删除',
146
151
  configLoadSuccess: '配置加载成功',
147
152
  configLoadFailed: '加载配置失败',
@@ -154,7 +159,11 @@ createApp({
154
159
  notAvailableYet: '暂未开放,敬请期待',
155
160
  saveFailed: '保存失败',
156
161
  cancel: '取消',
157
- confirm: '确认'
162
+ confirm: '确认',
163
+ switchToLight: '切换到浅色模式',
164
+ switchToDark: '切换到深色模式',
165
+ baseUrlPlaceholder: 'https://api.example.com',
166
+ tokenPlaceholder: '输入您的 API 令牌'
158
167
  }
159
168
  }
160
169
  };
@@ -162,6 +171,30 @@ createApp({
162
171
  computed: {
163
172
  t() {
164
173
  return this.translations[this.currentLang];
174
+ },
175
+ funLoadingMessage() {
176
+ const messages = {
177
+ en: [
178
+ 'Waking up the servers...',
179
+ 'Consulting the digital oracles...',
180
+ 'Polishing pixels...',
181
+ 'Herding electrons...',
182
+ 'Brewing digital coffee...',
183
+ 'Loading with intention...',
184
+ 'Almost there...'
185
+ ],
186
+ zh: [
187
+ '叫醒服务器中...',
188
+ '咨询数字预言家...',
189
+ '打磨像素中...',
190
+ '驱赶电子中...',
191
+ '冲泡数字咖啡中...',
192
+ '有目的地加载中...',
193
+ '马上就好...'
194
+ ]
195
+ };
196
+ const list = messages[this.currentLang] || messages.en;
197
+ return list[Math.floor(Math.random() * list.length)];
165
198
  }
166
199
  },
167
200
  methods: {
@@ -188,6 +221,18 @@ createApp({
188
221
  localStorage.setItem('ccby-lang', langCode);
189
222
  },
190
223
 
224
+ // 切换主题
225
+ toggleTheme() {
226
+ this.isDark = !this.isDark;
227
+ localStorage.setItem('ccby-theme', this.isDark ? 'dark' : 'light');
228
+ this.applyTheme();
229
+ },
230
+
231
+ // 应用主题
232
+ applyTheme() {
233
+ document.documentElement.setAttribute('data-theme', this.isDark ? 'dark' : 'light');
234
+ },
235
+
191
236
  // 重置服务器倒计时
192
237
  async resetTimer() {
193
238
  try {
@@ -244,6 +289,32 @@ createApp({
244
289
  }, 3000);
245
290
  },
246
291
 
292
+ // 彩带庆祝动画
293
+ showConfetti() {
294
+ const container = document.createElement('div');
295
+ container.className = 'confetti-container';
296
+ document.body.appendChild(container);
297
+
298
+ const colors = ['#3b82f6', '#22c55e', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899'];
299
+ const confettiCount = 50;
300
+
301
+ for (let i = 0; i < confettiCount; i++) {
302
+ const confetti = document.createElement('div');
303
+ confetti.className = 'confetti';
304
+ confetti.style.left = Math.random() * 100 + 'vw';
305
+ confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
306
+ confetti.style.width = (Math.random() * 8 + 6) + 'px';
307
+ confetti.style.height = (Math.random() * 8 + 6) + 'px';
308
+ confetti.style.borderRadius = Math.random() > 0.5 ? '50%' : '2px';
309
+ confetti.style.animation = `confetti-fall ${Math.random() * 2 + 1.5}s ease-out forwards`;
310
+ confetti.style.animationDelay = Math.random() * 0.5 + 's';
311
+ container.appendChild(confetti);
312
+ }
313
+
314
+ // 清理
315
+ setTimeout(() => container.remove(), 4000);
316
+ },
317
+
247
318
  async loadConfig(cliType) {
248
319
  // 如果没有传递 cliType,使用当前选择的 CLI 类型
249
320
  if (!cliType) {
@@ -334,6 +405,8 @@ createApp({
334
405
  cliType: this.currentCli.toLowerCase()
335
406
  });
336
407
  this.showToast(this.t.configSaveSuccess);
408
+ // 彩带庆祝
409
+ this.showConfetti();
337
410
  // 重置服务器倒计时
338
411
  this.resetTimer();
339
412
  } catch (err) {
@@ -458,6 +531,8 @@ createApp({
458
531
  cliType: this.currentCli.toLowerCase()
459
532
  });
460
533
  this.showToast(this.t.configActivated);
534
+ // 彩带庆祝
535
+ this.showConfetti();
461
536
  // 重置服务器倒计时
462
537
  this.resetTimer();
463
538
  } catch (err) {
@@ -638,6 +713,12 @@ createApp({
638
713
  if (savedLang && (savedLang === 'en' || savedLang === 'zh')) {
639
714
  this.currentLang = savedLang;
640
715
  }
716
+ // 从 localStorage 读取主题设置
717
+ const savedTheme = localStorage.getItem('ccby-theme');
718
+ if (savedTheme) {
719
+ this.isDark = savedTheme === 'dark';
720
+ }
721
+ this.applyTheme();
641
722
  this.loadConfig();
642
723
  },
643
724
  updated() {