@rahul05ranjan/dhruv-cli 0.0.0-development
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/.eslintignore +1 -0
- package/.eslintrc.cjs +43 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +28 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- package/.github/auto_assign.yml +10 -0
- package/.github/copilot-instructions.md +3 -0
- package/.github/dependabot.yml +15 -0
- package/.github/labeler.yml +27 -0
- package/.github/workflows/auto-assign.yml +14 -0
- package/.github/workflows/ci.yml +53 -0
- package/.github/workflows/contribution.yml +51 -0
- package/.github/workflows/dependabot-auto-merge.yml +19 -0
- package/.github/workflows/labeler.yml +13 -0
- package/.github/workflows/stale.yml +17 -0
- package/.releaserc +12 -0
- package/CHANGELOG.md +56 -0
- package/CODE_OF_CONDUCT.md +19 -0
- package/CONTRIBUTING.md +60 -0
- package/README.md +61 -0
- package/SECURITY.md +8 -0
- package/dist/commands/explain.d.ts +1 -0
- package/dist/commands/explain.js +46 -0
- package/dist/commands/fix.d.ts +1 -0
- package/dist/commands/fix.js +40 -0
- package/dist/commands/generate.d.ts +1 -0
- package/dist/commands/generate.js +62 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +54 -0
- package/dist/commands/menu.d.ts +1 -0
- package/dist/commands/menu.js +33 -0
- package/dist/commands/optimize.d.ts +1 -0
- package/dist/commands/optimize.js +42 -0
- package/dist/commands/review.d.ts +1 -0
- package/dist/commands/review.js +54 -0
- package/dist/commands/security-check.d.ts +1 -0
- package/dist/commands/security-check.js +48 -0
- package/dist/commands/suggest.d.ts +1 -0
- package/dist/commands/suggest.js +41 -0
- package/dist/config/config.d.ts +8 -0
- package/dist/config/config.js +20 -0
- package/dist/core/ai.d.ts +5 -0
- package/dist/core/ai.js +43 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +143 -0
- package/dist/utils/projectType.d.ts +1 -0
- package/dist/utils/projectType.js +17 -0
- package/dist/utils/ux.d.ts +5 -0
- package/dist/utils/ux.js +44 -0
- package/docs/index.html +537 -0
- package/node-fetch.d.ts +4 -0
- package/package.json +55 -0
- package/plugins/hello.js +10 -0
- package/src/commands/explain.ts +45 -0
- package/src/commands/fix.ts +34 -0
- package/src/commands/generate.ts +55 -0
- package/src/commands/init.ts +54 -0
- package/src/commands/menu.ts +35 -0
- package/src/commands/optimize.ts +36 -0
- package/src/commands/review.ts +47 -0
- package/src/commands/security-check.ts +41 -0
- package/src/commands/suggest.ts +35 -0
- package/src/config/config.ts +32 -0
- package/src/core/ai.test.js +40 -0
- package/src/core/ai.ts +41 -0
- package/src/index.ts +154 -0
- package/src/utils/projectType.ts +14 -0
- package/src/utils/ux.ts +50 -0
- package/tsconfig.json +17 -0
package/docs/index.html
ADDED
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Dhruv CLI - AI-Powered Developer Assistant</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;700&family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
|
8
|
+
<link rel="icon" href="https://cdn.jsdelivr.net/gh/rahul05ranjan/dhruv-cli/docs/dhruv-favicon.png">
|
|
9
|
+
<style>
|
|
10
|
+
:root {
|
|
11
|
+
--primary: #eebf63;
|
|
12
|
+
--bg: #181c2f;
|
|
13
|
+
--bg2: #232946;
|
|
14
|
+
--text: #f4f4f4;
|
|
15
|
+
--text2: #a1a6b4;
|
|
16
|
+
--accent: #5f6fff;
|
|
17
|
+
--shadow: 0 4px 24px #0003;
|
|
18
|
+
--radius: 1rem;
|
|
19
|
+
--transition: 0.2s cubic-bezier(.4,2,.6,1);
|
|
20
|
+
}
|
|
21
|
+
[data-theme="light"] {
|
|
22
|
+
--bg: #f4f4f4;
|
|
23
|
+
--bg2: #fff;
|
|
24
|
+
--text: #232946;
|
|
25
|
+
--text2: #555;
|
|
26
|
+
--accent: #5f6fff;
|
|
27
|
+
--shadow: 0 4px 24px #0001;
|
|
28
|
+
}
|
|
29
|
+
html, body {
|
|
30
|
+
height: 100%;
|
|
31
|
+
margin: 0;
|
|
32
|
+
padding: 0;
|
|
33
|
+
font-family: 'Inter', Arial, sans-serif;
|
|
34
|
+
background: linear-gradient(135deg, var(--bg) 0%, var(--bg2) 100%);
|
|
35
|
+
color: var(--text);
|
|
36
|
+
transition: background 0.5s, color 0.5s;
|
|
37
|
+
}
|
|
38
|
+
body {
|
|
39
|
+
min-height: 100vh;
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
}
|
|
43
|
+
.sidebar {
|
|
44
|
+
position: fixed;
|
|
45
|
+
top: 0; left: 0;
|
|
46
|
+
width: 220px;
|
|
47
|
+
height: 100vh;
|
|
48
|
+
background: var(--bg2);
|
|
49
|
+
box-shadow: 2px 0 16px #0002;
|
|
50
|
+
padding: 2rem 1rem 1rem 1rem;
|
|
51
|
+
z-index: 10;
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
gap: 1.5rem;
|
|
55
|
+
transition: left var(--transition);
|
|
56
|
+
}
|
|
57
|
+
.sidebar h2 {
|
|
58
|
+
font-size: 1.3rem;
|
|
59
|
+
color: var(--primary);
|
|
60
|
+
margin: 0 0 1rem 0;
|
|
61
|
+
letter-spacing: 1px;
|
|
62
|
+
}
|
|
63
|
+
.sidebar nav {
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
gap: 0.7rem;
|
|
67
|
+
}
|
|
68
|
+
.sidebar a {
|
|
69
|
+
color: var(--text2);
|
|
70
|
+
text-decoration: none;
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
padding: 0.3em 0.7em;
|
|
73
|
+
border-radius: 6px;
|
|
74
|
+
transition: background var(--transition), color var(--transition);
|
|
75
|
+
}
|
|
76
|
+
.sidebar a.active, .sidebar a:hover {
|
|
77
|
+
background: var(--primary);
|
|
78
|
+
color: var(--bg2);
|
|
79
|
+
}
|
|
80
|
+
.theme-toggle {
|
|
81
|
+
margin-top: auto;
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: 0.5em;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
color: var(--primary);
|
|
87
|
+
font-size: 1.1em;
|
|
88
|
+
user-select: none;
|
|
89
|
+
}
|
|
90
|
+
.main {
|
|
91
|
+
margin-left: 240px;
|
|
92
|
+
padding: 2.5rem 2rem 2rem 2rem;
|
|
93
|
+
flex: 1;
|
|
94
|
+
transition: margin-left var(--transition);
|
|
95
|
+
}
|
|
96
|
+
@media (max-width: 900px) {
|
|
97
|
+
.sidebar { position: static; width: 100vw; height: auto; flex-direction: row; align-items: center; padding: 1rem; }
|
|
98
|
+
.sidebar nav { flex-direction: row; gap: 1rem; }
|
|
99
|
+
.main { margin-left: 0; padding: 1.5rem 0.5rem; }
|
|
100
|
+
}
|
|
101
|
+
.hero {
|
|
102
|
+
text-align: center;
|
|
103
|
+
margin-bottom: 2.5rem;
|
|
104
|
+
}
|
|
105
|
+
.hero-logo {
|
|
106
|
+
width: 70px; height: 70px; margin-bottom: 1rem;
|
|
107
|
+
filter: drop-shadow(0 2px 8px #0005);
|
|
108
|
+
border-radius: 50%;
|
|
109
|
+
background: var(--bg2);
|
|
110
|
+
display: inline-block;
|
|
111
|
+
padding: 0.5rem;
|
|
112
|
+
}
|
|
113
|
+
.hero-title {
|
|
114
|
+
font-size: 2.7rem;
|
|
115
|
+
font-weight: 700;
|
|
116
|
+
margin: 0 0 0.5rem 0;
|
|
117
|
+
letter-spacing: 1px;
|
|
118
|
+
}
|
|
119
|
+
.hero-animated {
|
|
120
|
+
font-size: 1.3rem;
|
|
121
|
+
color: var(--primary);
|
|
122
|
+
min-height: 2.2em;
|
|
123
|
+
font-family: 'Fira Mono', monospace;
|
|
124
|
+
margin-bottom: 1.2rem;
|
|
125
|
+
animation: fadeIn 1.2s;
|
|
126
|
+
}
|
|
127
|
+
@keyframes fadeIn {
|
|
128
|
+
from { opacity: 0; transform: translateY(20px); }
|
|
129
|
+
to { opacity: 1; transform: none; }
|
|
130
|
+
}
|
|
131
|
+
.hero-install {
|
|
132
|
+
display: inline-block;
|
|
133
|
+
background: var(--primary);
|
|
134
|
+
color: var(--bg2);
|
|
135
|
+
font-family: 'Fira Mono', monospace;
|
|
136
|
+
font-size: 1.1em;
|
|
137
|
+
padding: 0.5em 1.2em;
|
|
138
|
+
border-radius: 8px;
|
|
139
|
+
margin-bottom: 1.5rem;
|
|
140
|
+
box-shadow: 0 2px 8px #0002;
|
|
141
|
+
cursor: pointer;
|
|
142
|
+
transition: background var(--transition), color var(--transition);
|
|
143
|
+
border: none;
|
|
144
|
+
}
|
|
145
|
+
.hero-install:hover { background: var(--accent); color: #fff; }
|
|
146
|
+
.badges {
|
|
147
|
+
margin: 1.2rem 0 0.5rem 0;
|
|
148
|
+
display: flex;
|
|
149
|
+
justify-content: center;
|
|
150
|
+
gap: 0.7rem;
|
|
151
|
+
flex-wrap: wrap;
|
|
152
|
+
}
|
|
153
|
+
.badges img { height: 28px; }
|
|
154
|
+
.terminal-demo {
|
|
155
|
+
background: #181c2f;
|
|
156
|
+
border-radius: 1rem;
|
|
157
|
+
box-shadow: var(--shadow);
|
|
158
|
+
max-width: 600px;
|
|
159
|
+
margin: 2rem auto 2.5rem auto;
|
|
160
|
+
padding: 1.5rem 1.2rem 1.2rem 1.2rem;
|
|
161
|
+
font-family: 'Fira Mono', monospace;
|
|
162
|
+
color: #eebf63;
|
|
163
|
+
position: relative;
|
|
164
|
+
overflow: hidden;
|
|
165
|
+
}
|
|
166
|
+
.terminal-bar {
|
|
167
|
+
display: flex;
|
|
168
|
+
align-items: center;
|
|
169
|
+
gap: 0.5em;
|
|
170
|
+
margin-bottom: 1em;
|
|
171
|
+
}
|
|
172
|
+
.term-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }
|
|
173
|
+
.term-dot.red { background: #ff5f56; }
|
|
174
|
+
.term-dot.yellow { background: #ffbd2e; }
|
|
175
|
+
.term-dot.green { background: #27c93f; }
|
|
176
|
+
.terminal-content {
|
|
177
|
+
min-height: 2.5em;
|
|
178
|
+
font-size: 1.1em;
|
|
179
|
+
white-space: pre-line;
|
|
180
|
+
word-break: break-word;
|
|
181
|
+
transition: color 0.2s;
|
|
182
|
+
}
|
|
183
|
+
.copy-btn {
|
|
184
|
+
position: absolute;
|
|
185
|
+
top: 1.2rem; right: 1.2rem;
|
|
186
|
+
background: var(--primary);
|
|
187
|
+
color: var(--bg2);
|
|
188
|
+
border: none;
|
|
189
|
+
border-radius: 6px;
|
|
190
|
+
padding: 0.2em 0.7em;
|
|
191
|
+
font-size: 1em;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
transition: background var(--transition), color var(--transition);
|
|
194
|
+
opacity: 0.85;
|
|
195
|
+
}
|
|
196
|
+
.copy-btn:hover { background: var(--accent); color: #fff; }
|
|
197
|
+
.tabs {
|
|
198
|
+
display: flex;
|
|
199
|
+
gap: 1.2rem;
|
|
200
|
+
margin-bottom: 1.5rem;
|
|
201
|
+
border-bottom: 2px solid var(--bg2);
|
|
202
|
+
flex-wrap: wrap;
|
|
203
|
+
}
|
|
204
|
+
.tab {
|
|
205
|
+
padding: 0.5em 1.2em;
|
|
206
|
+
background: none;
|
|
207
|
+
border: none;
|
|
208
|
+
color: var(--text2);
|
|
209
|
+
font-size: 1.1em;
|
|
210
|
+
font-weight: 500;
|
|
211
|
+
border-radius: 8px 8px 0 0;
|
|
212
|
+
cursor: pointer;
|
|
213
|
+
transition: background var(--transition), color var(--transition);
|
|
214
|
+
outline: none;
|
|
215
|
+
}
|
|
216
|
+
.tab.active, .tab:hover {
|
|
217
|
+
background: var(--primary);
|
|
218
|
+
color: var(--bg2);
|
|
219
|
+
}
|
|
220
|
+
.tab-content { display: none; animation: fadeIn 0.7s; }
|
|
221
|
+
.tab-content.active { display: block; }
|
|
222
|
+
.collapsible {
|
|
223
|
+
background: var(--bg2);
|
|
224
|
+
color: var(--text);
|
|
225
|
+
cursor: pointer;
|
|
226
|
+
padding: 1em;
|
|
227
|
+
width: 100%;
|
|
228
|
+
border: none;
|
|
229
|
+
text-align: left;
|
|
230
|
+
outline: none;
|
|
231
|
+
font-size: 1.1em;
|
|
232
|
+
border-radius: 8px;
|
|
233
|
+
margin-bottom: 0.5em;
|
|
234
|
+
transition: background var(--transition);
|
|
235
|
+
}
|
|
236
|
+
.collapsible.active, .collapsible:hover {
|
|
237
|
+
background: var(--primary);
|
|
238
|
+
color: var(--bg2);
|
|
239
|
+
}
|
|
240
|
+
.collapsible-content {
|
|
241
|
+
padding: 0 1em 1em 1em;
|
|
242
|
+
display: none;
|
|
243
|
+
background: var(--bg2);
|
|
244
|
+
border-radius: 0 0 8px 8px;
|
|
245
|
+
margin-bottom: 1em;
|
|
246
|
+
animation: fadeIn 0.5s;
|
|
247
|
+
}
|
|
248
|
+
.collapsible-content.active { display: block; }
|
|
249
|
+
code, pre {
|
|
250
|
+
font-family: 'Fira Mono', monospace;
|
|
251
|
+
background: #181c2f;
|
|
252
|
+
color: #eebf63;
|
|
253
|
+
border-radius: 6px;
|
|
254
|
+
padding: 0.2em 0.5em;
|
|
255
|
+
font-size: 1em;
|
|
256
|
+
}
|
|
257
|
+
.plugin-example {
|
|
258
|
+
background: #181c2f;
|
|
259
|
+
border-left: 4px solid var(--primary);
|
|
260
|
+
padding: 1rem;
|
|
261
|
+
margin: 1rem 0;
|
|
262
|
+
border-radius: 0.5rem;
|
|
263
|
+
font-size: 1em;
|
|
264
|
+
color: var(--text);
|
|
265
|
+
}
|
|
266
|
+
.community {
|
|
267
|
+
margin: 2.5rem 0 1.5rem 0;
|
|
268
|
+
text-align: center;
|
|
269
|
+
}
|
|
270
|
+
.community a {
|
|
271
|
+
color: var(--primary);
|
|
272
|
+
text-decoration: none;
|
|
273
|
+
font-weight: 600;
|
|
274
|
+
margin: 0 0.7em;
|
|
275
|
+
transition: color var(--transition);
|
|
276
|
+
}
|
|
277
|
+
.community a:hover { color: var(--accent); }
|
|
278
|
+
footer {
|
|
279
|
+
text-align: center;
|
|
280
|
+
color: var(--text2);
|
|
281
|
+
padding: 2rem 0 1rem 0;
|
|
282
|
+
font-size: 1rem;
|
|
283
|
+
}
|
|
284
|
+
@media (max-width: 700px) {
|
|
285
|
+
.main { padding: 1rem 0.2rem; }
|
|
286
|
+
.sidebar { padding: 0.7rem; }
|
|
287
|
+
.hero-title { font-size: 2rem; }
|
|
288
|
+
.terminal-demo { padding: 1rem 0.5rem; }
|
|
289
|
+
}
|
|
290
|
+
</style>
|
|
291
|
+
</head>
|
|
292
|
+
<body>
|
|
293
|
+
<div class="sidebar">
|
|
294
|
+
<h2>Dhruv CLI</h2>
|
|
295
|
+
<nav>
|
|
296
|
+
<a href="#hero" class="active">Home</a>
|
|
297
|
+
<a href="#features">Features</a>
|
|
298
|
+
<a href="#install">Install</a>
|
|
299
|
+
<a href="#usage">Usage</a>
|
|
300
|
+
<a href="#plugins">Plugins</a>
|
|
301
|
+
<a href="#community">Community</a>
|
|
302
|
+
<a href="https://www.npmjs.com/package/@rahul05ranjan/dhruv-cli" target="_blank">NPM</a>
|
|
303
|
+
</nav>
|
|
304
|
+
<div class="theme-toggle" id="themeToggle" title="Toggle dark/light mode">
|
|
305
|
+
<span id="themeIcon">🌙</span> <span id="themeLabel">Dark</span>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
<main class="main">
|
|
309
|
+
<section class="hero" id="hero">
|
|
310
|
+
<img src="https://cdn.jsdelivr.net/gh/rahul05ranjan/dhruv-cli/docs/dhruv-favicon.png" alt="Dhruv CLI Logo" class="hero-logo" />
|
|
311
|
+
<div class="hero-title">Dhruv CLI</div>
|
|
312
|
+
<div class="hero-animated" id="animatedTagline"></div>
|
|
313
|
+
<button class="hero-install" onclick="copyInstall()" id="installBtn">npm install -g @rahul05ranjan/dhruv-cli<span style='font-size:0.9em;' id='copyIcon'>📋</span></button>
|
|
314
|
+
<div style="margin-top:0.7em;">
|
|
315
|
+
<a href="https://www.npmjs.com/package/@rahul05ranjan/dhruv-cli" target="_blank" style="color:#eebf63;font-weight:bold;">View on npm</a>
|
|
316
|
+
</div>
|
|
317
|
+
<div class="badges">
|
|
318
|
+
<img src="https://img.shields.io/github/stars/rahul05ranjan/dhruv-cli?style=social" alt="GitHub stars">
|
|
319
|
+
<img src="https://img.shields.io/npm/v/dhruv-cli?color=blue&label=npm" alt="npm version">
|
|
320
|
+
<img src="https://img.shields.io/github/workflow/status/rahul05ranjan/dhruv-cli/CI?label=build" alt="build status">
|
|
321
|
+
<img src="https://img.shields.io/github/license/rahul05ranjan/dhruv-cli?color=green" alt="license">
|
|
322
|
+
</div>
|
|
323
|
+
</section>
|
|
324
|
+
<section class="tab-content" id="installTab">
|
|
325
|
+
<h2>Install</h2>
|
|
326
|
+
<pre><code>npm install -g @rahul05ranjan/dhruv-cli</code></pre>
|
|
327
|
+
<p>Also available on <a href="https://www.npmjs.com/package/@rahul05ranjan/dhruv-cli" target="_blank">npm</a>.</p>
|
|
328
|
+
<p>Requires <a href="https://nodejs.org/" target="_blank">Node.js</a> 18+ and <a href="https://ollama.com/" target="_blank">Ollama</a> for local AI models.</p>
|
|
329
|
+
</section>
|
|
330
|
+
<section class="tab-content" id="usageTab">
|
|
331
|
+
<h2>Usage Examples</h2>
|
|
332
|
+
<pre><code>dhruv suggest "deploy react app to vercel"
|
|
333
|
+
dhruv explain "git rebase vs merge"
|
|
334
|
+
dhruv fix "cors error in express"
|
|
335
|
+
dhruv review src/
|
|
336
|
+
dhruv optimize package.json
|
|
337
|
+
dhruv security-check src/
|
|
338
|
+
dhruv generate tests src/utils/helpers.js
|
|
339
|
+
dhruv init
|
|
340
|
+
dhruv completion bash > dhruv-complete.sh</code></pre>
|
|
341
|
+
<h3>All Commands</h3>
|
|
342
|
+
<ul>
|
|
343
|
+
<li><b>suggest</b> <code><query></code> — Smart suggestions for any dev task</li>
|
|
344
|
+
<li><b>explain</b> <code><query></code> — Explain concepts, errors, or commands</li>
|
|
345
|
+
<li><b>fix</b> <code><query></code> — Get AI-powered fixes for errors</li>
|
|
346
|
+
<li><b>review</b> <code><fileOrDir></code> — Review code for improvements</li>
|
|
347
|
+
<li><b>optimize</b> <code><file></code> — Optimize files (e.g., <code>package.json</code>)</li>
|
|
348
|
+
<li><b>security-check</b> <code>[fileOrDir]</code> — Security analysis of code</li>
|
|
349
|
+
<li><b>generate</b> <code><type> <target></code> — Generate code/tests</li>
|
|
350
|
+
<li><b>init</b> — Interactive setup/configuration wizard</li>
|
|
351
|
+
<li><b>completion</b> <code>[shell]</code> — Output shell completion script</li>
|
|
352
|
+
<li><b>project-type</b> — Detect project type</li>
|
|
353
|
+
<li><b>hello-plugin</b> — Example plugin command</li>
|
|
354
|
+
</ul>
|
|
355
|
+
</section>
|
|
356
|
+
<section class="tab-content" id="pluginsTab">
|
|
357
|
+
<h2>Plugin Example</h2>
|
|
358
|
+
<div class="plugin-example">
|
|
359
|
+
<pre><code>export default (program) => {
|
|
360
|
+
program.command('hello-plugin').action(() => console.log('Hello from plugin!'));
|
|
361
|
+
};</code></pre>
|
|
362
|
+
</div>
|
|
363
|
+
<ul>
|
|
364
|
+
<li>Add new commands by dropping ESM modules in the <code>plugins/</code> directory.</li>
|
|
365
|
+
<li>Plugins are loaded automatically before CLI parsing.</li>
|
|
366
|
+
</ul>
|
|
367
|
+
</section>
|
|
368
|
+
<section class="tab-content" id="communityTab">
|
|
369
|
+
<div class="community" id="community">
|
|
370
|
+
<h2>Open Source & Community</h2>
|
|
371
|
+
<p>Dhruv CLI is fully open source and welcomes contributions!</p>
|
|
372
|
+
<a href="https://github.com/rahul05ranjan/dhruv-cli" target="_blank">GitHub Repo</a>
|
|
373
|
+
<a href="https://github.com/rahul05ranjan/dhruv-cli/issues" target="_blank">Issues</a>
|
|
374
|
+
<a href="https://github.com/rahul05ranjan/dhruv-cli/pulls" target="_blank">Pull Requests</a>
|
|
375
|
+
<a href="https://github.com/rahul05ranjan/dhruv-cli/blob/main/CONTRIBUTING.md" target="_blank">Contributing Guide</a>
|
|
376
|
+
<div style="margin-top:1.2em;">
|
|
377
|
+
<img src="https://img.shields.io/github/contributors/rahul05ranjan/dhruv-cli?color=blue" alt="contributors">
|
|
378
|
+
<img src="https://img.shields.io/github/issues/rahul05ranjan/dhruv-cli?color=orange" alt="issues">
|
|
379
|
+
<img src="https://img.shields.io/github/last-commit/rahul05ranjan/dhruv-cli?color=green" alt="last commit">
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
</section>
|
|
383
|
+
<div class="section">
|
|
384
|
+
<h2>Configuration & Context</h2>
|
|
385
|
+
<ul>
|
|
386
|
+
<li>Run <code>dhruv init</code> to set model, response format, and verbosity.</li>
|
|
387
|
+
<li>Project type is auto-detected for context-aware suggestions.</li>
|
|
388
|
+
<li>Works offline with local Ollama models.</li>
|
|
389
|
+
</ul>
|
|
390
|
+
</div>
|
|
391
|
+
</main>
|
|
392
|
+
<footer>
|
|
393
|
+
<div>MIT License © 2025 — Dhruv CLI</div>
|
|
394
|
+
<div>Made with ❤️ for developers</div>
|
|
395
|
+
</footer>
|
|
396
|
+
<script>
|
|
397
|
+
// Animated tagline
|
|
398
|
+
const taglines = [
|
|
399
|
+
'Your AI Pair Programmer in the Terminal',
|
|
400
|
+
'Smart suggestions, code review, and more',
|
|
401
|
+
'Powered by Ollama. Fully offline. Open source.',
|
|
402
|
+
'Beautiful CLI UX. Plugin system. Community-driven.'
|
|
403
|
+
];
|
|
404
|
+
let taglineIdx = 0;
|
|
405
|
+
function animateTagline() {
|
|
406
|
+
const el = document.getElementById('animatedTagline');
|
|
407
|
+
el.textContent = '';
|
|
408
|
+
let txt = taglines[taglineIdx];
|
|
409
|
+
let i = 0;
|
|
410
|
+
function type() {
|
|
411
|
+
if (i < txt.length) {
|
|
412
|
+
el.textContent += txt.charAt(i);
|
|
413
|
+
i++;
|
|
414
|
+
setTimeout(type, 28);
|
|
415
|
+
} else {
|
|
416
|
+
setTimeout(() => {
|
|
417
|
+
taglineIdx = (taglineIdx + 1) % taglines.length;
|
|
418
|
+
animateTagline();
|
|
419
|
+
}, 1800);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
type();
|
|
423
|
+
}
|
|
424
|
+
animateTagline();
|
|
425
|
+
|
|
426
|
+
// Terminal demo animation
|
|
427
|
+
const terminalLines = [
|
|
428
|
+
'dhruv suggest "deploy react app to vercel"',
|
|
429
|
+
'dhruv explain "git rebase vs merge"',
|
|
430
|
+
'dhruv fix "cors error in express"',
|
|
431
|
+
'dhruv review src/',
|
|
432
|
+
'dhruv optimize package.json',
|
|
433
|
+
'dhruv security-check src/',
|
|
434
|
+
'dhruv generate tests src/utils/helpers.js',
|
|
435
|
+
'dhruv init',
|
|
436
|
+
'dhruv completion bash > dhruv-complete.sh'
|
|
437
|
+
];
|
|
438
|
+
let termIdx = 0;
|
|
439
|
+
function animateTerminal() {
|
|
440
|
+
const el = document.getElementById('terminalContent');
|
|
441
|
+
el.textContent = '';
|
|
442
|
+
let txt = terminalLines[termIdx];
|
|
443
|
+
let i = 0;
|
|
444
|
+
function type() {
|
|
445
|
+
if (i < txt.length) {
|
|
446
|
+
el.textContent += txt.charAt(i);
|
|
447
|
+
i++;
|
|
448
|
+
setTimeout(type, 18);
|
|
449
|
+
} else {
|
|
450
|
+
setTimeout(() => {
|
|
451
|
+
termIdx = (termIdx + 1) % terminalLines.length;
|
|
452
|
+
animateTerminal();
|
|
453
|
+
}, 1200);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
type();
|
|
457
|
+
}
|
|
458
|
+
animateTerminal();
|
|
459
|
+
|
|
460
|
+
// Copy install command
|
|
461
|
+
function copyInstall() {
|
|
462
|
+
navigator.clipboard.writeText('npm install -g @rahul05ranjan/dhruv-cli');
|
|
463
|
+
const btn = document.getElementById('installBtn');
|
|
464
|
+
const icon = document.getElementById('copyIcon');
|
|
465
|
+
icon.textContent = '✅';
|
|
466
|
+
setTimeout(() => { icon.textContent = '📋'; }, 1200);
|
|
467
|
+
}
|
|
468
|
+
// Copy terminal command
|
|
469
|
+
function copyTerminal() {
|
|
470
|
+
const el = document.getElementById('terminalContent');
|
|
471
|
+
navigator.clipboard.writeText(el.textContent);
|
|
472
|
+
const btn = document.getElementById('copyTermBtn');
|
|
473
|
+
btn.textContent = 'Copied!';
|
|
474
|
+
setTimeout(() => { btn.textContent = 'Copy'; }, 1200);
|
|
475
|
+
}
|
|
476
|
+
// Tabs
|
|
477
|
+
const tabs = document.querySelectorAll('.tab');
|
|
478
|
+
const tabContents = document.querySelectorAll('.tab-content');
|
|
479
|
+
tabs.forEach(tab => {
|
|
480
|
+
tab.addEventListener('click', () => {
|
|
481
|
+
tabs.forEach(t => t.classList.remove('active'));
|
|
482
|
+
tab.classList.add('active');
|
|
483
|
+
tabContents.forEach(tc => tc.classList.remove('active'));
|
|
484
|
+
document.getElementById(tab.dataset.tab).classList.add('active');
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
// Collapsible
|
|
488
|
+
const collapsibles = document.querySelectorAll('.collapsible');
|
|
489
|
+
collapsibles.forEach(btn => {
|
|
490
|
+
btn.addEventListener('click', function() {
|
|
491
|
+
this.classList.toggle('active');
|
|
492
|
+
const content = this.nextElementSibling;
|
|
493
|
+
content.classList.toggle('active');
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
// Sidebar nav scrollspy
|
|
497
|
+
const navLinks = document.querySelectorAll('.sidebar nav a');
|
|
498
|
+
const sections = [
|
|
499
|
+
document.getElementById('hero'),
|
|
500
|
+
document.getElementById('features'),
|
|
501
|
+
document.getElementById('installTab'),
|
|
502
|
+
document.getElementById('usageTab'),
|
|
503
|
+
document.getElementById('pluginsTab'),
|
|
504
|
+
document.getElementById('community')
|
|
505
|
+
];
|
|
506
|
+
window.addEventListener('scroll', () => {
|
|
507
|
+
let idx = 0;
|
|
508
|
+
for (let i = 0; i < sections.length; i++) {
|
|
509
|
+
if (sections[i] && sections[i].getBoundingClientRect().top < 120) idx = i;
|
|
510
|
+
}
|
|
511
|
+
navLinks.forEach(l => l.classList.remove('active'));
|
|
512
|
+
if (navLinks[idx]) navLinks[idx].classList.add('active');
|
|
513
|
+
});
|
|
514
|
+
// Theme toggle
|
|
515
|
+
const themeToggle = document.getElementById('themeToggle');
|
|
516
|
+
const themeIcon = document.getElementById('themeIcon');
|
|
517
|
+
const themeLabel = document.getElementById('themeLabel');
|
|
518
|
+
function setTheme(theme) {
|
|
519
|
+
document.documentElement.setAttribute('data-theme', theme);
|
|
520
|
+
if (theme === 'light') {
|
|
521
|
+
themeIcon.textContent = '☀️';
|
|
522
|
+
themeLabel.textContent = 'Light';
|
|
523
|
+
} else {
|
|
524
|
+
themeIcon.textContent = '🌙';
|
|
525
|
+
themeLabel.textContent = 'Dark';
|
|
526
|
+
}
|
|
527
|
+
localStorage.setItem('dhruv-theme', theme);
|
|
528
|
+
}
|
|
529
|
+
themeToggle.addEventListener('click', () => {
|
|
530
|
+
const current = document.documentElement.getAttribute('data-theme') || 'dark';
|
|
531
|
+
setTheme(current === 'dark' ? 'light' : 'dark');
|
|
532
|
+
});
|
|
533
|
+
// Load theme
|
|
534
|
+
setTheme(localStorage.getItem('dhruv-theme') || 'dark');
|
|
535
|
+
</script>
|
|
536
|
+
</body>
|
|
537
|
+
</html>
|
package/node-fetch.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rahul05ranjan/dhruv-cli",
|
|
3
|
+
"version": "0.0.0-development",
|
|
4
|
+
"description": "AI-powered CLI assistant for developers using Ollama",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"cli",
|
|
8
|
+
"developer-tools",
|
|
9
|
+
"ollama",
|
|
10
|
+
"assistant"
|
|
11
|
+
],
|
|
12
|
+
"bin": {
|
|
13
|
+
"dhruv": "dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18.0.0"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"start": "node ./dist/index.js",
|
|
24
|
+
"dev": "ts-node src/index.ts"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"chalk": "^5.3.0",
|
|
28
|
+
"cli-highlight": "^2.1.11",
|
|
29
|
+
"cli-progress": "^3.12.0",
|
|
30
|
+
"commander": "^14.0.0",
|
|
31
|
+
"inquirer": "^12.6.3",
|
|
32
|
+
"node-fetch": "^2.7.0",
|
|
33
|
+
"ollama": "^0.5.16",
|
|
34
|
+
"ora": "^8.2.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@eslint/js": "^8.57.1",
|
|
38
|
+
"@types/inquirer": "^9.0.8",
|
|
39
|
+
"@types/node": "^24.0.7",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^8.35.0",
|
|
41
|
+
"@typescript-eslint/parser": "^8.35.0",
|
|
42
|
+
"eslint": "^8.57.1",
|
|
43
|
+
"semantic-release": "^23.1.1",
|
|
44
|
+
"ts-node": "^10.9.1",
|
|
45
|
+
"typescript": "^5.8.3",
|
|
46
|
+
"typescript-eslint": "^8.35.0"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/rahul05ranjan/dhruv-cli.git"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"registry": "https://registry.npmjs.org/"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/plugins/hello.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { askOllama } from '../core/ai.js';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { loadConfig } from '../config/config.js';
|
|
5
|
+
import { highlightCode, printError } from '../utils/ux.js';
|
|
6
|
+
|
|
7
|
+
export async function explain(query: string) {
|
|
8
|
+
const config = loadConfig();
|
|
9
|
+
const spinner = ora('Thinking...').start();
|
|
10
|
+
let streamed = '';
|
|
11
|
+
const dhruvIntro = chalk.yellowBright('Dhruv CLI: Your AI-powered CLI assistant for developers using Ollama.\n');
|
|
12
|
+
try {
|
|
13
|
+
spinner.stop();
|
|
14
|
+
process.stdout.write(dhruvIntro); // Print Dhruv intro before explanation
|
|
15
|
+
process.stdout.write(chalk.green('Explanation: '));
|
|
16
|
+
await askOllama({
|
|
17
|
+
prompt: `Explain: ${query}`,
|
|
18
|
+
model: config.model,
|
|
19
|
+
onToken: (token: string) => {
|
|
20
|
+
streamed += token;
|
|
21
|
+
process.stdout.write(chalk.cyan(token));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
process.stdout.write('\n');
|
|
25
|
+
if (typeof highlightCode === 'function' && streamed.match(/```[a-z]*[\s\S]*?```/)) {
|
|
26
|
+
const codeBlocks = streamed.match(/```([a-z]*)\n([\s\S]*?)```/g) || [];
|
|
27
|
+
for (const block of codeBlocks) {
|
|
28
|
+
const [, lang, code] = block.match(/```([a-z]*)\n([\s\S]*?)```/) || [];
|
|
29
|
+
if (code) {
|
|
30
|
+
try {
|
|
31
|
+
console.log(highlightCode(code, lang || 'js'));
|
|
32
|
+
} catch (err) {
|
|
33
|
+
// Only log highlight errors in development
|
|
34
|
+
if (process.env.NODE_ENV === 'development') {
|
|
35
|
+
console.error('Highlight error:', err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch (err) {
|
|
42
|
+
printError('Failed to get explanation.');
|
|
43
|
+
console.error(chalk.red((err as Error).message));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { askOllama } from '../core/ai.js';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { loadConfig } from '../config/config.js';
|
|
5
|
+
import { highlightCode, printError } from '../utils/ux.js';
|
|
6
|
+
|
|
7
|
+
export async function fix(query: string) {
|
|
8
|
+
const config = loadConfig();
|
|
9
|
+
const spinner = ora('Analyzing issue...').start();
|
|
10
|
+
let streamed = '';
|
|
11
|
+
try {
|
|
12
|
+
spinner.stop();
|
|
13
|
+
process.stdout.write(chalk.green('Fix suggestion: '));
|
|
14
|
+
await askOllama({
|
|
15
|
+
prompt: `Fix: ${query}`,
|
|
16
|
+
model: config.model,
|
|
17
|
+
onToken: (token: string) => {
|
|
18
|
+
streamed += token;
|
|
19
|
+
process.stdout.write(chalk.cyan(token));
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
process.stdout.write('\n');
|
|
23
|
+
if (typeof highlightCode === 'function' && streamed.match(/```[a-z]*[\s\S]*?```/)) {
|
|
24
|
+
const codeBlocks = streamed.match(/```([a-z]*)\n([\s\S]*?)```/g) || [];
|
|
25
|
+
for (const block of codeBlocks) {
|
|
26
|
+
const [, lang, code] = block.match(/```([a-z]*)\n([\s\S]*?)```/) || [];
|
|
27
|
+
if (code) try { console.log(highlightCode(code, lang || 'js')); } catch (err) { console.error('Highlight error:', err); }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
} catch (err) {
|
|
31
|
+
printError('Failed to get fix suggestion.');
|
|
32
|
+
console.error(chalk.red((err as Error).message));
|
|
33
|
+
}
|
|
34
|
+
}
|