@stan-chen/simple-cli 0.2.1

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 (87) hide show
  1. package/README.md +287 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.js +259 -0
  4. package/dist/commands/add.d.ts +9 -0
  5. package/dist/commands/add.js +50 -0
  6. package/dist/commands/git/commit.d.ts +12 -0
  7. package/dist/commands/git/commit.js +97 -0
  8. package/dist/commands/git/status.d.ts +6 -0
  9. package/dist/commands/git/status.js +42 -0
  10. package/dist/commands/index.d.ts +16 -0
  11. package/dist/commands/index.js +376 -0
  12. package/dist/commands/mcp/status.d.ts +6 -0
  13. package/dist/commands/mcp/status.js +31 -0
  14. package/dist/commands/swarm.d.ts +36 -0
  15. package/dist/commands/swarm.js +236 -0
  16. package/dist/commands.d.ts +32 -0
  17. package/dist/commands.js +427 -0
  18. package/dist/context.d.ts +116 -0
  19. package/dist/context.js +327 -0
  20. package/dist/index.d.ts +6 -0
  21. package/dist/index.js +109 -0
  22. package/dist/lib/agent.d.ts +98 -0
  23. package/dist/lib/agent.js +281 -0
  24. package/dist/lib/editor.d.ts +74 -0
  25. package/dist/lib/editor.js +441 -0
  26. package/dist/lib/git.d.ts +164 -0
  27. package/dist/lib/git.js +351 -0
  28. package/dist/lib/ui.d.ts +159 -0
  29. package/dist/lib/ui.js +252 -0
  30. package/dist/mcp/client.d.ts +22 -0
  31. package/dist/mcp/client.js +81 -0
  32. package/dist/mcp/manager.d.ts +186 -0
  33. package/dist/mcp/manager.js +442 -0
  34. package/dist/prompts/provider.d.ts +22 -0
  35. package/dist/prompts/provider.js +78 -0
  36. package/dist/providers/index.d.ts +15 -0
  37. package/dist/providers/index.js +82 -0
  38. package/dist/providers/multi.d.ts +11 -0
  39. package/dist/providers/multi.js +28 -0
  40. package/dist/registry.d.ts +24 -0
  41. package/dist/registry.js +379 -0
  42. package/dist/repoMap.d.ts +5 -0
  43. package/dist/repoMap.js +79 -0
  44. package/dist/router.d.ts +41 -0
  45. package/dist/router.js +108 -0
  46. package/dist/skills.d.ts +25 -0
  47. package/dist/skills.js +288 -0
  48. package/dist/swarm/coordinator.d.ts +86 -0
  49. package/dist/swarm/coordinator.js +257 -0
  50. package/dist/swarm/index.d.ts +28 -0
  51. package/dist/swarm/index.js +29 -0
  52. package/dist/swarm/task.d.ts +104 -0
  53. package/dist/swarm/task.js +221 -0
  54. package/dist/swarm/types.d.ts +132 -0
  55. package/dist/swarm/types.js +37 -0
  56. package/dist/swarm/worker.d.ts +107 -0
  57. package/dist/swarm/worker.js +299 -0
  58. package/dist/tools/analyzeFile.d.ts +16 -0
  59. package/dist/tools/analyzeFile.js +43 -0
  60. package/dist/tools/git.d.ts +40 -0
  61. package/dist/tools/git.js +236 -0
  62. package/dist/tools/glob.d.ts +34 -0
  63. package/dist/tools/glob.js +165 -0
  64. package/dist/tools/grep.d.ts +53 -0
  65. package/dist/tools/grep.js +296 -0
  66. package/dist/tools/linter.d.ts +35 -0
  67. package/dist/tools/linter.js +349 -0
  68. package/dist/tools/listDir.d.ts +29 -0
  69. package/dist/tools/listDir.js +50 -0
  70. package/dist/tools/memory.d.ts +34 -0
  71. package/dist/tools/memory.js +215 -0
  72. package/dist/tools/readFiles.d.ts +25 -0
  73. package/dist/tools/readFiles.js +31 -0
  74. package/dist/tools/reloadTools.d.ts +11 -0
  75. package/dist/tools/reloadTools.js +22 -0
  76. package/dist/tools/runCommand.d.ts +32 -0
  77. package/dist/tools/runCommand.js +79 -0
  78. package/dist/tools/scraper.d.ts +31 -0
  79. package/dist/tools/scraper.js +211 -0
  80. package/dist/tools/writeFiles.d.ts +63 -0
  81. package/dist/tools/writeFiles.js +87 -0
  82. package/dist/ui/server.d.ts +5 -0
  83. package/dist/ui/server.js +74 -0
  84. package/dist/watcher.d.ts +35 -0
  85. package/dist/watcher.js +164 -0
  86. package/docs/assets/logo.jpeg +0 -0
  87. package/package.json +78 -0
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Git Operations using simple-git
3
+ * Reliable git operations leveraging the native Git binary
4
+ */
5
+ import simpleGit from 'simple-git';
6
+ /**
7
+ * GitManager - Wrapper around simple-git for reliable git operations
8
+ */
9
+ export class GitManager {
10
+ git;
11
+ cwd;
12
+ constructor(config = {}) {
13
+ this.cwd = config.cwd || process.cwd();
14
+ this.git = simpleGit({
15
+ baseDir: this.cwd,
16
+ binary: 'git',
17
+ maxConcurrentProcesses: 6,
18
+ timeout: {
19
+ block: config.timeout || 30000,
20
+ },
21
+ });
22
+ }
23
+ /**
24
+ * Check if current directory is a git repository
25
+ */
26
+ async isRepo() {
27
+ try {
28
+ await this.git.revparse(['--git-dir']);
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ /**
36
+ * Initialize a new git repository
37
+ */
38
+ async init() {
39
+ await this.git.init();
40
+ }
41
+ /**
42
+ * Get repository status
43
+ */
44
+ async status() {
45
+ return this.git.status();
46
+ }
47
+ /**
48
+ * Get current branch name
49
+ */
50
+ async currentBranch() {
51
+ try {
52
+ const result = await this.git.revparse(['--abbrev-ref', 'HEAD']);
53
+ return result.trim() || null;
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ /**
60
+ * Get all branches
61
+ */
62
+ async branches() {
63
+ return this.git.branch();
64
+ }
65
+ /**
66
+ * Checkout a branch
67
+ */
68
+ async checkout(branch, create = false) {
69
+ if (create) {
70
+ await this.git.checkoutLocalBranch(branch);
71
+ }
72
+ else {
73
+ await this.git.checkout(branch);
74
+ }
75
+ }
76
+ /**
77
+ * Stage files
78
+ */
79
+ async add(files) {
80
+ const fileList = Array.isArray(files) ? files : [files];
81
+ await this.git.add(fileList);
82
+ }
83
+ /**
84
+ * Stage all changes
85
+ */
86
+ async addAll() {
87
+ await this.git.add('-A');
88
+ }
89
+ /**
90
+ * Commit changes
91
+ */
92
+ async commit(options) {
93
+ const { message, files, amend, noVerify, author } = options;
94
+ try {
95
+ const commitOptions = {};
96
+ if (amend) {
97
+ commitOptions['--amend'] = null;
98
+ }
99
+ if (noVerify) {
100
+ commitOptions['--no-verify'] = null;
101
+ }
102
+ if (author) {
103
+ commitOptions['--author'] = author;
104
+ }
105
+ if (files && files.length > 0) {
106
+ await this.git.add(files);
107
+ }
108
+ const result = await this.git.commit(message, files || [], commitOptions);
109
+ if (result.commit) {
110
+ return {
111
+ hash: result.commit,
112
+ message: message,
113
+ };
114
+ }
115
+ return null;
116
+ }
117
+ catch (error) {
118
+ console.error('Commit failed:', error);
119
+ return null;
120
+ }
121
+ }
122
+ /**
123
+ * Get diff
124
+ */
125
+ async diff(options = {}) {
126
+ const args = ['--no-color'];
127
+ if (options.staged) {
128
+ args.push('--cached');
129
+ }
130
+ if (options.from && options.to) {
131
+ args.push(options.from, options.to);
132
+ }
133
+ else if (options.from) {
134
+ args.push(options.from);
135
+ }
136
+ if (options.file) {
137
+ args.push('--', options.file);
138
+ }
139
+ return this.git.diff(args);
140
+ }
141
+ /**
142
+ * Get staged diff
143
+ */
144
+ async stagedDiff() {
145
+ return this.diff({ staged: true });
146
+ }
147
+ /**
148
+ * Get commit log
149
+ */
150
+ async log(maxCount = 20) {
151
+ return this.git.log({ maxCount });
152
+ }
153
+ /**
154
+ * Get the last commit
155
+ */
156
+ async lastCommit() {
157
+ try {
158
+ const log = await this.git.log({ maxCount: 1 });
159
+ if (log.latest) {
160
+ return {
161
+ hash: log.latest.hash,
162
+ message: log.latest.message,
163
+ author: log.latest.author_name,
164
+ date: log.latest.date,
165
+ };
166
+ }
167
+ return null;
168
+ }
169
+ catch {
170
+ return null;
171
+ }
172
+ }
173
+ /**
174
+ * Undo the last commit (soft reset)
175
+ */
176
+ async undoLastCommit() {
177
+ try {
178
+ await this.git.reset(['--soft', 'HEAD~1']);
179
+ return true;
180
+ }
181
+ catch {
182
+ return false;
183
+ }
184
+ }
185
+ /**
186
+ * Hard reset to a commit
187
+ */
188
+ async hardReset(commit = 'HEAD') {
189
+ await this.git.reset(['--hard', commit]);
190
+ }
191
+ /**
192
+ * Stash changes
193
+ */
194
+ async stash(message) {
195
+ if (message) {
196
+ await this.git.stash(['push', '-m', message]);
197
+ }
198
+ else {
199
+ await this.git.stash();
200
+ }
201
+ }
202
+ /**
203
+ * Pop stash
204
+ */
205
+ async stashPop() {
206
+ await this.git.stash(['pop']);
207
+ }
208
+ /**
209
+ * Get list of tracked files
210
+ */
211
+ async trackedFiles() {
212
+ const result = await this.git.raw(['ls-files']);
213
+ return result.split('\n').filter(Boolean);
214
+ }
215
+ /**
216
+ * Get list of changed files (staged + unstaged)
217
+ */
218
+ async changedFiles() {
219
+ const status = await this.status();
220
+ return [
221
+ ...status.modified,
222
+ ...status.created,
223
+ ...status.deleted,
224
+ ...status.renamed.map(r => r.to),
225
+ ...status.not_added,
226
+ ];
227
+ }
228
+ /**
229
+ * Check if a file is ignored
230
+ */
231
+ async isIgnored(file) {
232
+ try {
233
+ await this.git.raw(['check-ignore', '-q', file]);
234
+ return true;
235
+ }
236
+ catch {
237
+ return false;
238
+ }
239
+ }
240
+ /**
241
+ * Get blame for a file
242
+ */
243
+ async blame(file) {
244
+ return this.git.raw(['blame', '--no-color', '-l', file]);
245
+ }
246
+ /**
247
+ * Show a specific commit
248
+ */
249
+ async show(commit) {
250
+ return this.git.show(['--no-color', '--stat', commit]);
251
+ }
252
+ /**
253
+ * Get the root directory of the repository
254
+ */
255
+ async rootDir() {
256
+ try {
257
+ const result = await this.git.revparse(['--show-toplevel']);
258
+ return result.trim();
259
+ }
260
+ catch {
261
+ return null;
262
+ }
263
+ }
264
+ /**
265
+ * Pull changes from remote
266
+ */
267
+ async pull(remote = 'origin', branch) {
268
+ if (branch) {
269
+ await this.git.pull(remote, branch);
270
+ }
271
+ else {
272
+ await this.git.pull();
273
+ }
274
+ }
275
+ /**
276
+ * Push changes to remote
277
+ */
278
+ async push(remote = 'origin', branch, options) {
279
+ const args = [];
280
+ if (options?.setUpstream) {
281
+ args.push('-u');
282
+ }
283
+ args.push(remote);
284
+ if (branch) {
285
+ args.push(branch);
286
+ }
287
+ await this.git.push(args);
288
+ }
289
+ /**
290
+ * Create a new branch from current HEAD
291
+ */
292
+ async createBranch(name) {
293
+ await this.git.checkoutLocalBranch(name);
294
+ }
295
+ /**
296
+ * Delete a branch
297
+ */
298
+ async deleteBranch(name, force = false) {
299
+ await this.git.deleteLocalBranch(name, force);
300
+ }
301
+ /**
302
+ * Merge a branch into current branch
303
+ */
304
+ async merge(branch) {
305
+ await this.git.merge([branch]);
306
+ }
307
+ /**
308
+ * Get the raw simple-git instance for advanced operations
309
+ */
310
+ raw() {
311
+ return this.git;
312
+ }
313
+ }
314
+ // Singleton instance
315
+ let gitManager = null;
316
+ /**
317
+ * Get or create a GitManager instance
318
+ */
319
+ export function getGitManager(config) {
320
+ if (!gitManager || config) {
321
+ gitManager = new GitManager(config);
322
+ }
323
+ return gitManager;
324
+ }
325
+ /**
326
+ * Generate AI commit message from diff
327
+ */
328
+ export async function generateCommitMessage(diff, generateFn, context) {
329
+ const prompt = `Generate a concise git commit message for these changes.
330
+
331
+ Guidelines:
332
+ - Start with a type: feat, fix, refactor, docs, test, chore
333
+ - Keep the first line under 72 characters
334
+ - Focus on the "why" not the "what"
335
+ - Use imperative mood ("add" not "added")
336
+
337
+ ${context ? `Context: ${context}\n` : ''}
338
+ Diff:
339
+ \`\`\`
340
+ ${diff.slice(0, 4000)}${diff.length > 4000 ? '\n... (truncated)' : ''}
341
+ \`\`\`
342
+
343
+ Respond with ONLY the commit message, no explanation.`;
344
+ const message = await generateFn(prompt);
345
+ // Clean up the response
346
+ return message
347
+ .trim()
348
+ .replace(/^["']|["']$/g, '') // Remove quotes
349
+ .replace(/^commit:?\s*/i, '') // Remove "commit:" prefix
350
+ .split('\n')[0]; // Take only first line
351
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Terminal UI using Clack
3
+ * Modern, clean terminal prompts and spinners
4
+ */
5
+ import * as p from '@clack/prompts';
6
+ export { p as prompts };
7
+ /**
8
+ * UI Theme colors
9
+ */
10
+ export declare const theme: {
11
+ primary: import("picocolors/types").Formatter;
12
+ success: import("picocolors/types").Formatter;
13
+ warning: import("picocolors/types").Formatter;
14
+ error: import("picocolors/types").Formatter;
15
+ muted: import("picocolors/types").Formatter;
16
+ highlight: import("picocolors/types").Formatter;
17
+ code: import("picocolors/types").Formatter;
18
+ };
19
+ /**
20
+ * Display intro banner
21
+ */
22
+ export declare function intro(message: string): void;
23
+ /**
24
+ * Display outro message
25
+ */
26
+ export declare function outro(message: string): void;
27
+ /**
28
+ * Display a note
29
+ */
30
+ export declare function note(message: string, title?: string): void;
31
+ /**
32
+ * Display a log message
33
+ */
34
+ export declare function log(message: string): void;
35
+ /**
36
+ * Display an info message
37
+ */
38
+ export declare function info(message: string): void;
39
+ /**
40
+ * Display a success message
41
+ */
42
+ export declare function success(message: string): void;
43
+ /**
44
+ * Display a warning message
45
+ */
46
+ export declare function warning(message: string): void;
47
+ /**
48
+ * Display an error message
49
+ */
50
+ export declare function error(message: string): void;
51
+ /**
52
+ * Display a step message
53
+ */
54
+ export declare function step(message: string): void;
55
+ /**
56
+ * Show a spinner while executing an async operation
57
+ */
58
+ export declare function spin<T>(message: string, fn: () => Promise<T>): Promise<T>;
59
+ /**
60
+ * Prompt for text input
61
+ */
62
+ export declare function text(options: {
63
+ message: string;
64
+ placeholder?: string;
65
+ defaultValue?: string;
66
+ validate?: (value: string) => string | undefined;
67
+ }): Promise<string | symbol>;
68
+ /**
69
+ * Prompt for password input
70
+ */
71
+ export declare function password(options: {
72
+ message: string;
73
+ validate?: (value: string) => string | undefined;
74
+ }): Promise<string | symbol>;
75
+ /**
76
+ * Prompt for confirmation
77
+ */
78
+ export declare function confirm(options: {
79
+ message: string;
80
+ initialValue?: boolean;
81
+ }): Promise<boolean | symbol>;
82
+ /**
83
+ * Prompt for single selection
84
+ */
85
+ export declare function select<T extends string>(options: {
86
+ message: string;
87
+ options: Array<{
88
+ value: T;
89
+ label: string;
90
+ hint?: string;
91
+ }>;
92
+ initialValue?: T;
93
+ }): Promise<T | symbol>;
94
+ /**
95
+ * Prompt for multi-selection
96
+ */
97
+ export declare function multiselect<T extends string>(options: {
98
+ message: string;
99
+ options: Array<{
100
+ value: T;
101
+ label: string;
102
+ hint?: string;
103
+ }>;
104
+ initialValues?: T[];
105
+ required?: boolean;
106
+ }): Promise<T[] | symbol>;
107
+ /**
108
+ * Group related prompts together
109
+ */
110
+ export declare function group<T extends Record<string, unknown>>(prompts: Record<keyof T, () => Promise<unknown>>, options?: {
111
+ onCancel?: () => void;
112
+ }): Promise<T>;
113
+ /**
114
+ * Check if user cancelled
115
+ */
116
+ export declare function isCancel(value: unknown): value is symbol;
117
+ /**
118
+ * Cancel and exit
119
+ */
120
+ export declare function cancel(message?: string): void;
121
+ /**
122
+ * Display a diff with syntax highlighting
123
+ */
124
+ export declare function showDiff(diffText: string): void;
125
+ /**
126
+ * Display a code block
127
+ */
128
+ export declare function showCode(code: string, language?: string): void;
129
+ /**
130
+ * Display a thinking/reasoning block
131
+ */
132
+ export declare function showThought(thought: string): void;
133
+ /**
134
+ * Display a tool invocation
135
+ */
136
+ export declare function showToolCall(name: string, args: Record<string, unknown>): void;
137
+ /**
138
+ * Display a tool result
139
+ */
140
+ export declare function showToolResult(result: string, truncate?: number): void;
141
+ /**
142
+ * Display file status indicators
143
+ */
144
+ export declare function showFileStatus(files: Array<{
145
+ path: string;
146
+ status: 'added' | 'modified' | 'deleted' | 'readonly';
147
+ }>): void;
148
+ /**
149
+ * Display token count
150
+ */
151
+ export declare function showTokens(count: number, max?: number): void;
152
+ /**
153
+ * Create a task list for progress tracking
154
+ */
155
+ export declare function tasks(): {
156
+ add: (name: string, status?: 'pending' | 'running' | 'done' | 'error') => void;
157
+ update: (name: string, status: 'pending' | 'running' | 'done' | 'error') => void;
158
+ render: () => void;
159
+ };