@rahul05ranjan/dhruv-cli 1.3.0 → 1.5.0
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/.github/ENTERPRISE.md +275 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +45 -17
- package/.github/ISSUE_TEMPLATE/documentation_issue.md +61 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +61 -9
- package/.github/ISSUE_TEMPLATE/security_vulnerability.md +74 -0
- package/.github/dependabot.yml +42 -2
- package/.github/pull_request_template.md +13 -0
- package/.github/workflows/ci.yml +51 -38
- package/.github/workflows/contribution.yml +41 -34
- package/.github/workflows/dependabot-auto-merge.yml +62 -2
- package/.github/workflows/labeler.yml +1 -0
- package/.github/workflows/release.yml +229 -0
- package/.github/workflows/security.yml +201 -0
- package/.releaserc.json +50 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +13 -0
- package/README.md +145 -40
- package/__tests__/cli-contract.test.ts +104 -0
- package/__tests__/core.test.ts +439 -0
- package/__tests__/diagnostics.test.ts +155 -0
- package/__tests__/file-workflows.test.ts +195 -0
- package/__tests__/interactive.test.ts +119 -0
- package/__tests__/setup.ts +62 -0
- package/__tests__/workflows.test.ts +118 -0
- package/dist/commands/explain.js +13 -44
- package/dist/commands/fix.js +13 -38
- package/dist/commands/generate.d.ts +6 -1
- package/dist/commands/generate.js +60 -55
- package/dist/commands/health.d.ts +4 -0
- package/dist/commands/health.js +419 -0
- package/dist/commands/init.js +56 -42
- package/dist/commands/menu.js +137 -24
- package/dist/commands/metrics.d.ts +5 -0
- package/dist/commands/metrics.js +80 -0
- package/dist/commands/optimize.js +42 -34
- package/dist/commands/review.d.ts +4 -1
- package/dist/commands/review.js +87 -43
- package/dist/commands/security-check.d.ts +4 -1
- package/dist/commands/security-check.js +109 -38
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +83 -0
- package/dist/commands/suggest.js +13 -39
- package/dist/config/config.d.ts +5 -1
- package/dist/config/config.js +53 -8
- package/dist/core/ai.d.ts +88 -2
- package/dist/core/ai.js +231 -30
- package/dist/core/command-catalog.d.ts +10 -0
- package/dist/core/command-catalog.js +27 -0
- package/dist/core/command-runner.d.ts +17 -0
- package/dist/core/command-runner.js +157 -0
- package/dist/core/logger.d.ts +40 -0
- package/dist/core/logger.js +139 -0
- package/dist/core/metrics.d.ts +62 -0
- package/dist/core/metrics.js +284 -0
- package/dist/core/prompts.d.ts +1 -0
- package/dist/core/prompts.js +121 -0
- package/dist/core/security.d.ts +34 -0
- package/dist/core/security.js +197 -0
- package/dist/index.js +84 -22
- package/dist/utils/projectType.d.ts +1 -1
- package/dist/utils/projectType.js +26 -7
- package/dist/utils/ux.d.ts +3 -0
- package/dist/utils/ux.js +15 -0
- package/docs/agents/domain.md +51 -0
- package/docs/agents/issue-tracker.md +45 -0
- package/docs/agents/triage-labels.md +15 -0
- package/docs/api/.nojekyll +1 -0
- package/docs/api/assets/hierarchy.js +1 -0
- package/docs/api/assets/highlight.css +71 -0
- package/docs/api/assets/icons.js +18 -0
- package/docs/api/assets/icons.svg +1 -0
- package/docs/api/assets/main.js +60 -0
- package/docs/api/assets/navigation.js +1 -0
- package/docs/api/assets/search.js +1 -0
- package/docs/api/assets/style.css +1633 -0
- package/docs/api/hierarchy.html +1 -0
- package/docs/api/index.html +161 -0
- package/docs/api/media/CONTRIBUTING.md +60 -0
- package/docs/api/media/SECURITY.md +8 -0
- package/docs/api/media/dhruv-cli-preview.svg +42 -0
- package/docs/api/media/publishing-fix.md +34 -0
- package/docs/api/modules.html +1 -0
- package/docs/dhruv-cli-preview.svg +42 -0
- package/docs/index.html +631 -533
- package/docs/publishing-fix.md +34 -0
- package/eslint.config.js +170 -0
- package/jest.config.json +37 -0
- package/lighthouserc.json +22 -0
- package/package.json +62 -8
- package/src/commands/explain.ts +13 -42
- package/src/commands/fix.ts +13 -31
- package/src/commands/generate.ts +68 -48
- package/src/commands/health.ts +485 -0
- package/src/commands/init.ts +57 -42
- package/src/commands/menu.ts +132 -24
- package/src/commands/metrics.ts +100 -0
- package/src/commands/optimize.ts +40 -28
- package/src/commands/review.ts +96 -37
- package/src/commands/security-check.ts +127 -33
- package/src/commands/status.ts +83 -0
- package/src/commands/suggest.ts +13 -32
- package/src/config/config.ts +60 -8
- package/src/core/ai.ts +265 -26
- package/src/core/command-catalog.ts +37 -0
- package/src/core/command-runner.ts +185 -0
- package/src/core/logger.ts +195 -0
- package/src/core/metrics.ts +335 -0
- package/src/core/prompts.ts +128 -0
- package/src/core/security.ts +243 -0
- package/src/index.ts +90 -22
- package/src/utils/projectType.ts +22 -7
- package/src/utils/ux.ts +18 -0
- package/test-suite.sh +147 -0
- package/tsconfig.json +4 -3
- package/typedoc.json +44 -0
- package/types/global.d.ts +13 -0
- package/validate-workflows.sh +270 -0
- package/.eslintignore +0 -1
- package/.eslintrc.cjs +0 -43
- package/.github/workflows/auto-assign.yml +0 -14
- package/src/core/ai.test.js +0 -40
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
name: Security Monitoring
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '0 6 * * 1' # Every Monday at 6 AM UTC
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
push:
|
|
8
|
+
branches: [ main ]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [ main ]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
actions: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
secret-scan:
|
|
18
|
+
name: Secret Scanning
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
timeout-minutes: 10
|
|
21
|
+
steps:
|
|
22
|
+
- name: Harden Runner
|
|
23
|
+
uses: step-security/harden-runner@v2
|
|
24
|
+
with:
|
|
25
|
+
egress-policy: audit
|
|
26
|
+
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
|
|
31
|
+
- name: Run TruffleHog
|
|
32
|
+
uses: trufflesecurity/trufflehog@main
|
|
33
|
+
with:
|
|
34
|
+
path: ./
|
|
35
|
+
# Use the action's event-aware range (push, PR, or full history).
|
|
36
|
+
extra_args: --debug --only-verified
|
|
37
|
+
|
|
38
|
+
license-check:
|
|
39
|
+
name: License Compliance
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
if: github.event_name != 'pull_request'
|
|
42
|
+
timeout-minutes: 10
|
|
43
|
+
steps:
|
|
44
|
+
- name: Harden Runner
|
|
45
|
+
uses: step-security/harden-runner@v2
|
|
46
|
+
with:
|
|
47
|
+
egress-policy: audit
|
|
48
|
+
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
|
|
51
|
+
- name: Set up Node.js
|
|
52
|
+
uses: actions/setup-node@v4
|
|
53
|
+
with:
|
|
54
|
+
node-version: '20.8.1'
|
|
55
|
+
cache: 'npm'
|
|
56
|
+
|
|
57
|
+
- name: Install dependencies
|
|
58
|
+
run: npm ci --prefer-offline --no-audit
|
|
59
|
+
|
|
60
|
+
- name: Check licenses
|
|
61
|
+
run: |
|
|
62
|
+
npx license-checker --summary --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;0BSD;Unlicense' || echo "License check completed with warnings"
|
|
63
|
+
continue-on-error: true
|
|
64
|
+
|
|
65
|
+
supply-chain:
|
|
66
|
+
name: Supply Chain Security
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
if: github.event_name != 'pull_request'
|
|
69
|
+
timeout-minutes: 15
|
|
70
|
+
steps:
|
|
71
|
+
- name: Harden Runner
|
|
72
|
+
uses: step-security/harden-runner@v2
|
|
73
|
+
with:
|
|
74
|
+
egress-policy: audit
|
|
75
|
+
|
|
76
|
+
- uses: actions/checkout@v4
|
|
77
|
+
|
|
78
|
+
- name: Set up Node.js
|
|
79
|
+
uses: actions/setup-node@v4
|
|
80
|
+
with:
|
|
81
|
+
node-version: '20.8.1'
|
|
82
|
+
cache: 'npm'
|
|
83
|
+
|
|
84
|
+
- name: Install dependencies
|
|
85
|
+
run: npm ci --prefer-offline --no-audit
|
|
86
|
+
|
|
87
|
+
- name: Run OSV Scanner
|
|
88
|
+
uses: google/osv-scanner-action/osv-scanner-action@v2.6.0
|
|
89
|
+
continue-on-error: true
|
|
90
|
+
with:
|
|
91
|
+
scan-args: |-
|
|
92
|
+
--recursive
|
|
93
|
+
./
|
|
94
|
+
|
|
95
|
+
- name: Run Snyk Security Scan
|
|
96
|
+
uses: snyk/actions/node@master
|
|
97
|
+
env:
|
|
98
|
+
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
|
99
|
+
with:
|
|
100
|
+
args: --severity-threshold=high
|
|
101
|
+
continue-on-error: true
|
|
102
|
+
|
|
103
|
+
sbom-generation:
|
|
104
|
+
name: Generate SBOM
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
if: github.event_name != 'pull_request'
|
|
107
|
+
timeout-minutes: 10
|
|
108
|
+
steps:
|
|
109
|
+
- name: Harden Runner
|
|
110
|
+
uses: step-security/harden-runner@v2
|
|
111
|
+
with:
|
|
112
|
+
egress-policy: audit
|
|
113
|
+
|
|
114
|
+
- uses: actions/checkout@v4
|
|
115
|
+
|
|
116
|
+
- name: Set up Node.js
|
|
117
|
+
uses: actions/setup-node@v4
|
|
118
|
+
with:
|
|
119
|
+
node-version: '20.8.1'
|
|
120
|
+
cache: 'npm'
|
|
121
|
+
|
|
122
|
+
- name: Install dependencies
|
|
123
|
+
run: npm ci --prefer-offline --no-audit
|
|
124
|
+
|
|
125
|
+
- name: Generate SBOM
|
|
126
|
+
run: |
|
|
127
|
+
npx --yes @cyclonedx/cyclonedx-npm --output-file sbom.json
|
|
128
|
+
npx --yes @cyclonedx/cyclonedx-npm --output-file sbom.xml --output-format XML
|
|
129
|
+
|
|
130
|
+
- name: Upload SBOM
|
|
131
|
+
uses: actions/upload-artifact@v4
|
|
132
|
+
with:
|
|
133
|
+
name: sbom-files
|
|
134
|
+
path: |
|
|
135
|
+
sbom.json
|
|
136
|
+
sbom.xml
|
|
137
|
+
retention-days: 90
|
|
138
|
+
|
|
139
|
+
security-scorecard:
|
|
140
|
+
name: OSSF Scorecard
|
|
141
|
+
runs-on: ubuntu-latest
|
|
142
|
+
permissions:
|
|
143
|
+
security-events: write
|
|
144
|
+
actions: read
|
|
145
|
+
contents: read
|
|
146
|
+
id-token: write
|
|
147
|
+
# Scorecard only supports analysis from the repository's default branch.
|
|
148
|
+
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
149
|
+
steps:
|
|
150
|
+
- name: Harden Runner
|
|
151
|
+
uses: step-security/harden-runner@v2
|
|
152
|
+
with:
|
|
153
|
+
egress-policy: audit
|
|
154
|
+
|
|
155
|
+
- uses: actions/checkout@v4
|
|
156
|
+
with:
|
|
157
|
+
persist-credentials: false
|
|
158
|
+
|
|
159
|
+
- name: Run analysis
|
|
160
|
+
uses: ossf/scorecard-action@v2.4.4
|
|
161
|
+
with:
|
|
162
|
+
results_file: results.sarif
|
|
163
|
+
results_format: sarif
|
|
164
|
+
publish_results: true
|
|
165
|
+
|
|
166
|
+
- name: Upload SARIF results
|
|
167
|
+
if: always() && hashFiles('results.sarif') != ''
|
|
168
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
169
|
+
with:
|
|
170
|
+
sarif_file: results.sarif
|
|
171
|
+
|
|
172
|
+
container-scan:
|
|
173
|
+
name: Container and Dependency Scan
|
|
174
|
+
runs-on: ubuntu-latest
|
|
175
|
+
timeout-minutes: 15
|
|
176
|
+
if: github.event_name != 'pull_request'
|
|
177
|
+
permissions:
|
|
178
|
+
contents: read
|
|
179
|
+
security-events: write
|
|
180
|
+
steps:
|
|
181
|
+
- name: Harden Runner
|
|
182
|
+
uses: step-security/harden-runner@v2
|
|
183
|
+
with:
|
|
184
|
+
egress-policy: audit
|
|
185
|
+
|
|
186
|
+
- uses: actions/checkout@v4
|
|
187
|
+
|
|
188
|
+
# Scorecard publishing only permits approved actions in its own job.
|
|
189
|
+
- name: Container and dependency scan
|
|
190
|
+
uses: anchore/scan-action@v7.4.2
|
|
191
|
+
id: scan
|
|
192
|
+
with:
|
|
193
|
+
path: "."
|
|
194
|
+
fail-build: false
|
|
195
|
+
output-format: sarif
|
|
196
|
+
|
|
197
|
+
- name: Upload Anchore scan SARIF file
|
|
198
|
+
if: always() && steps.scan.outputs.sarif != ''
|
|
199
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
200
|
+
with:
|
|
201
|
+
sarif_file: ${{ steps.scan.outputs.sarif }}
|
package/.releaserc.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"branches": [
|
|
3
|
+
"main",
|
|
4
|
+
{
|
|
5
|
+
"name": "improvement",
|
|
6
|
+
"prerelease": "beta"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "development",
|
|
10
|
+
"prerelease": "alpha"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"plugins": [
|
|
14
|
+
"@semantic-release/commit-analyzer",
|
|
15
|
+
"@semantic-release/release-notes-generator",
|
|
16
|
+
[
|
|
17
|
+
"@semantic-release/changelog",
|
|
18
|
+
{
|
|
19
|
+
"changelogFile": "CHANGELOG.md"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"@semantic-release/npm",
|
|
23
|
+
[
|
|
24
|
+
"@semantic-release/github",
|
|
25
|
+
{
|
|
26
|
+
"assets": [
|
|
27
|
+
{
|
|
28
|
+
"path": "dist/**",
|
|
29
|
+
"label": "Distribution files"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"path": "docs/**",
|
|
33
|
+
"label": "Documentation"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
"@semantic-release/git",
|
|
40
|
+
{
|
|
41
|
+
"assets": [
|
|
42
|
+
"CHANGELOG.md",
|
|
43
|
+
"package.json",
|
|
44
|
+
"package-lock.json"
|
|
45
|
+
],
|
|
46
|
+
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
]
|
|
50
|
+
}
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Agent skills
|
|
2
|
+
|
|
3
|
+
### Issue tracker
|
|
4
|
+
|
|
5
|
+
Issues live in GitHub Issues (rahul05ranjan/dhruv-cli), via the `gh` CLI. See `docs/agents/issue-tracker.md`.
|
|
6
|
+
|
|
7
|
+
### Triage labels
|
|
8
|
+
|
|
9
|
+
Default five-role vocabulary: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. See `docs/agents/triage-labels.md`.
|
|
10
|
+
|
|
11
|
+
### Domain docs
|
|
12
|
+
|
|
13
|
+
Single-context: one `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
# [1.4.0](https://github.com/rahul05ranjan/dhruv-cli/compare/v1.4.6...v1.4.0) (2026-09-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* change moduleResolution from Node to Bundler in tsconfig ([b8339bb](https://github.com/rahul05ranjan/dhruv-cli/commit/b8339bb89781490d5678f43052b606138f375d21))
|
|
7
|
+
* drop unused menu loop flag ([51eeec6](https://github.com/rahul05ranjan/dhruv-cli/commit/51eeec6a607299120ce3e1f15af9f9dc62396ce7))
|
|
8
|
+
* stabilize health and CLI contract tests on CI ([3b3e650](https://github.com/rahul05ranjan/dhruv-cli/commit/3b3e6503591c8c33d36f1887e94358dafe6163ce))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* improve cli experience across commands ([ce41913](https://github.com/rahul05ranjan/dhruv-cli/commit/ce4191350ca3d1c5f49b371508e66de9421f6d20))
|
|
1
14
|
# Changelog
|
|
2
15
|
|
|
3
16
|
## [1.1.1](https://github.com/rahul05ranjan/dhruv-cli/compare/v1.1.0...v1.1.1) (2025-06-29)
|
package/README.md
CHANGED
|
@@ -1,61 +1,166 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/rahul05ranjan/dhruv-cli">
|
|
3
|
+
<strong>⚡ Dhruv CLI</strong>
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
A local-first AI command center for your terminal.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
Ask better questions. Understand unfamiliar code. Ship with confidence.
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://rahul05ranjan.github.io/dhruv-cli/">Website</a>
|
|
17
|
+
·
|
|
18
|
+
<a href="https://www.npmjs.com/package/@rahul05ranjan/dhruv-cli">npm</a>
|
|
19
|
+
·
|
|
20
|
+
<a href="https://github.com/rahul05ranjan/dhruv-cli/issues">Issues</a>
|
|
21
|
+
·
|
|
22
|
+
<a href="CONTRIBUTING.md">Contributing</a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<a href="https://github.com/rahul05ranjan/dhruv-cli/actions/workflows/deploy.yml"><img src="https://github.com/rahul05ranjan/dhruv-cli/actions/workflows/deploy.yml/badge.svg" alt="Deployment status"></a>
|
|
27
|
+
<a href="https://www.npmjs.com/package/@rahul05ranjan/dhruv-cli"><img src="https://img.shields.io/npm/v/%40rahul05ranjan%2Fdhruv-cli?style=flat-square&label=npm" alt="npm version"></a>
|
|
28
|
+
<a href="https://www.npmjs.com/package/@rahul05ranjan/dhruv-cli"><img src="https://img.shields.io/npm/dm/%40rahul05ranjan%2Fdhruv-cli?style=flat-square&label=downloads" alt="npm downloads"></a>
|
|
29
|
+
<img src="https://img.shields.io/github/license/rahul05ranjan/dhruv-cli?style=flat-square" alt="MIT license">
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
<img src="docs/dhruv-cli-preview.svg" alt="Dhruv CLI terminal preview" width="760">
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
## Why Dhruv?
|
|
37
|
+
|
|
38
|
+
Dhruv brings a focused AI toolkit into the terminal, powered by local Ollama models. It keeps your workflow close to the codebase, works without a hosted AI account, and turns everyday developer questions into fast, actionable output.
|
|
39
|
+
|
|
40
|
+
<table>
|
|
41
|
+
<tr>
|
|
42
|
+
<td width="33%"><strong>✦ Think with you</strong><br>Explain concepts, suggest approaches, and turn errors into clear next steps.</td>
|
|
43
|
+
<td width="33%"><strong>◈ Inspect deeply</strong><br>Review code, optimize files, and scan projects for common security risks.</td>
|
|
44
|
+
<td width="33%"><strong>⌁ Fit your flow</strong><br>Use an interactive menu, shell completion, JSON output, or your own plugins.</td>
|
|
45
|
+
</tr>
|
|
46
|
+
</table>
|
|
47
|
+
|
|
48
|
+
## Start in 60 seconds
|
|
49
|
+
|
|
50
|
+
### 1. Install Dhruv
|
|
51
|
+
|
|
25
52
|
```bash
|
|
26
53
|
npm install -g @rahul05ranjan/dhruv-cli
|
|
27
54
|
```
|
|
28
55
|
|
|
29
|
-
|
|
56
|
+
### 2. Start a local model
|
|
57
|
+
|
|
58
|
+
Install [Ollama](https://ollama.com/), then run:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
ollama serve
|
|
62
|
+
ollama pull gemma3:270m
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 3. Configure once, then go
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
dhruv init
|
|
69
|
+
dhruv suggest "how should I structure this Node.js service?"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Dhruv requires Node.js 18 or newer. The default model is `gemma3:270m`; choose any model available in your Ollama installation during setup.
|
|
73
|
+
|
|
74
|
+
## A command surface built for shipping
|
|
75
|
+
|
|
76
|
+
| Command | What it does |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `dhruv suggest <query>` | Generate practical suggestions for a development task |
|
|
79
|
+
| `dhruv explain <query>` | Explain a concept, command, or unfamiliar error |
|
|
80
|
+
| `dhruv fix <query>` | Analyze a coding issue and propose a fix |
|
|
81
|
+
| `dhruv review <file-or-dir>` | Review up to ten code files for quality and maintainability; add `--diff` for uncommitted changes |
|
|
82
|
+
| `dhruv optimize <file>` | Find actionable improvements for source or configuration files |
|
|
83
|
+
| `dhruv security-check [file-or-dir]` | Run a redacted local security analysis; add `--strict` for CI failure on high-confidence findings |
|
|
84
|
+
| `dhruv generate <type> <target>` | Preview generated tests by default; use `--apply`, `--output`, or `--overwrite` to write safely |
|
|
85
|
+
| `dhruv status` | Check Ollama connectivity and configured models |
|
|
86
|
+
| `dhruv health` | Show a concise health summary; use `--details` for diagnostics |
|
|
87
|
+
| `dhruv metrics` | Inspect local usage and performance metrics; use `--raw` or `--reset` explicitly |
|
|
88
|
+
| `dhruv project-type` | Detect the current project type |
|
|
89
|
+
| `dhruv menu` | Open the interactive command palette |
|
|
90
|
+
| `dhruv completion [shell]` | Generate Bash, Zsh, or Fish completion |
|
|
91
|
+
|
|
92
|
+
### Common workflows
|
|
30
93
|
|
|
31
|
-
## 📝 Usage Examples
|
|
32
94
|
```bash
|
|
33
|
-
|
|
95
|
+
# Understand and plan
|
|
34
96
|
dhruv explain "git rebase vs merge"
|
|
35
|
-
dhruv
|
|
97
|
+
dhruv suggest "deploy a React app to Vercel"
|
|
98
|
+
|
|
99
|
+
# Improve an existing project
|
|
36
100
|
dhruv review src/
|
|
101
|
+
dhruv review --diff .
|
|
37
102
|
dhruv optimize package.json
|
|
38
103
|
dhruv security-check src/
|
|
39
|
-
dhruv
|
|
40
|
-
|
|
41
|
-
|
|
104
|
+
dhruv security-check src/ --strict
|
|
105
|
+
|
|
106
|
+
# Generate and automate
|
|
107
|
+
dhruv generate tests src/utils/helpers.js # preview only
|
|
108
|
+
dhruv generate tests src/utils/helpers.js --apply
|
|
109
|
+
dhruv completion zsh > ~/.zsh/completions/_dhruv
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Configuration that stays out of your way
|
|
113
|
+
|
|
114
|
+
Run `dhruv init` to set the Ollama model, response format, verbosity, terminal theme, and whether settings are project-local or user-global. Local configuration is stored in `.dhruv-config.json`; global settings live under your user config directory.
|
|
115
|
+
|
|
116
|
+
For one-off runs, use global flags:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
dhruv suggest "summarize this migration" --model llama3.2 --json
|
|
120
|
+
dhruv review src/ --verbose
|
|
121
|
+
dhruv explain "what changed?" --timeout 60000
|
|
42
122
|
```
|
|
43
123
|
|
|
44
|
-
##
|
|
45
|
-
|
|
124
|
+
## Extend it with plugins
|
|
125
|
+
|
|
126
|
+
Drop an ESM module into your project's `plugins/` directory. Dhruv loads `.js` plugins before parsing the command line, so you can add commands without changing the core CLI.
|
|
127
|
+
|
|
46
128
|
```js
|
|
47
129
|
// plugins/hello.js
|
|
48
130
|
export default (program) => {
|
|
49
|
-
program
|
|
131
|
+
program
|
|
132
|
+
.command('hello-plugin')
|
|
133
|
+
.description('Say hello from a project plugin')
|
|
134
|
+
.action(() => console.log('Hello from Dhruv!'));
|
|
50
135
|
};
|
|
51
136
|
```
|
|
52
137
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
138
|
+
Then run:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
dhruv hello-plugin
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Documentation & project guides
|
|
56
145
|
|
|
57
|
-
|
|
58
|
-
|
|
146
|
+
| Resource | Link |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| Product site | [rahul05ranjan.github.io/dhruv-cli](https://rahul05ranjan.github.io/dhruv-cli/) |
|
|
149
|
+
| API reference | [Generated TypeDoc](https://rahul05ranjan.github.io/dhruv-cli/api/) |
|
|
150
|
+
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) |
|
|
151
|
+
| Security policy | [SECURITY.md](SECURITY.md) |
|
|
152
|
+
| Publishing notes | [docs/publishing-fix.md](docs/publishing-fix.md) |
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm install
|
|
158
|
+
npm run type-check
|
|
159
|
+
npm test
|
|
160
|
+
npm run lint
|
|
161
|
+
npm run build
|
|
162
|
+
```
|
|
59
163
|
|
|
60
164
|
## License
|
|
61
|
-
|
|
165
|
+
|
|
166
|
+
MIT © [Rahul Ranjan](https://github.com/rahul05ranjan)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, expect, it } from '@jest/globals';
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
const repoRoot = resolve(__dirname, '..');
|
|
8
|
+
// Package/relative specifiers so Windows does not pass `D:\...` into the ESM loader.
|
|
9
|
+
const sourceEntry = './src/index.ts';
|
|
10
|
+
const loaderEntry = 'ts-node/esm';
|
|
11
|
+
|
|
12
|
+
describe('CLI output contract', () => {
|
|
13
|
+
it('keeps shell completion stdout free of startup telemetry', async () => {
|
|
14
|
+
const result = await execFileAsync(
|
|
15
|
+
process.execPath,
|
|
16
|
+
['--loader', loaderEntry, sourceEntry, 'completion', 'bash'],
|
|
17
|
+
{
|
|
18
|
+
cwd: repoRoot,
|
|
19
|
+
env: { ...process.env, DHRUV_METRICS_ENABLED: 'false' },
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
expect(result.stdout).toMatch(/^#!\/bin\/bash/);
|
|
24
|
+
expect(result.stdout).not.toContain('Dhruv CLI starting');
|
|
25
|
+
expect(result.stdout).not.toContain('\u001b[');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('includes diagnostic commands and shared options in completion scripts', async () => {
|
|
29
|
+
const result = await execFileAsync(
|
|
30
|
+
process.execPath,
|
|
31
|
+
['--loader', loaderEntry, sourceEntry, 'completion', 'bash'],
|
|
32
|
+
{
|
|
33
|
+
cwd: repoRoot,
|
|
34
|
+
env: { ...process.env, DHRUV_METRICS_ENABLED: 'false' },
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
expect(result.stdout).toContain('status');
|
|
39
|
+
expect(result.stdout).toContain('--json');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('rejects unsupported completion shells', async () => {
|
|
43
|
+
await expect(execFileAsync(
|
|
44
|
+
process.execPath,
|
|
45
|
+
['--loader', loaderEntry, sourceEntry, 'completion', 'powershell'],
|
|
46
|
+
{ cwd: repoRoot, env: { ...process.env, DHRUV_METRICS_ENABLED: 'false' } },
|
|
47
|
+
)).rejects.toMatchObject({ code: 2 });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('documents strict security checks in command help', async () => {
|
|
51
|
+
const result = await execFileAsync(
|
|
52
|
+
process.execPath,
|
|
53
|
+
['--loader', loaderEntry, sourceEntry, 'security-check', '--help'],
|
|
54
|
+
{
|
|
55
|
+
cwd: repoRoot,
|
|
56
|
+
env: { ...process.env, DHRUV_METRICS_ENABLED: 'false' },
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
expect(result.stdout).toContain('--strict');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('documents safe generation controls in command help', async () => {
|
|
64
|
+
const result = await execFileAsync(
|
|
65
|
+
process.execPath,
|
|
66
|
+
['--loader', loaderEntry, sourceEntry, 'generate', '--help'],
|
|
67
|
+
{
|
|
68
|
+
cwd: repoRoot,
|
|
69
|
+
env: { ...process.env, DHRUV_METRICS_ENABLED: 'false' },
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(result.stdout).toContain('--apply');
|
|
74
|
+
expect(result.stdout).toContain('--output');
|
|
75
|
+
expect(result.stdout).toContain('--overwrite');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('documents explicit metrics export and reset controls', async () => {
|
|
79
|
+
const result = await execFileAsync(
|
|
80
|
+
process.execPath,
|
|
81
|
+
['--loader', loaderEntry, sourceEntry, 'metrics', '--help'],
|
|
82
|
+
{
|
|
83
|
+
cwd: repoRoot,
|
|
84
|
+
env: { ...process.env, DHRUV_METRICS_ENABLED: 'false' },
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(result.stdout).toContain('--raw');
|
|
89
|
+
expect(result.stdout).toContain('--reset');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('documents detailed health diagnostics as an explicit option', async () => {
|
|
93
|
+
const result = await execFileAsync(
|
|
94
|
+
process.execPath,
|
|
95
|
+
['--loader', loaderEntry, sourceEntry, 'health', '--help'],
|
|
96
|
+
{
|
|
97
|
+
cwd: repoRoot,
|
|
98
|
+
env: { ...process.env, DHRUV_METRICS_ENABLED: 'false' },
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
expect(result.stdout).toContain('--details');
|
|
103
|
+
});
|
|
104
|
+
});
|