@sumant.pathak/devjar 1.0.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/LICENSE +21 -0
- package/README.md +125 -0
- package/bin/devjar.js +55 -0
- package/package.json +35 -0
- package/src/config.js +103 -0
- package/src/init.js +388 -0
- package/src/prompt.js +135 -0
- package/src/providers/anthropic.js +27 -0
- package/src/providers/gemini.js +37 -0
- package/src/providers/index.js +54 -0
- package/src/providers/ollama.js +40 -0
- package/src/providers/openai.js +37 -0
- package/src/stats.js +173 -0
- package/src/update.js +235 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sumnt Pathak
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# devjar
|
|
2
|
+
|
|
3
|
+
Scan your project into a Claude-ready knowledge map. Rewrite vague prompts into structured ones. Use 60–70% fewer tokens on any AI coding tool.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Every Claude Code session starts blind. You re-explain the same context, re-read the same files, burn tokens on clarification. devjar fixes both.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g devjar
|
|
15
|
+
cd your-project
|
|
16
|
+
devjar init
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Your project is now mapped. Claude reads `CLAUDE.md` at session start and never re-reads your files again.
|
|
20
|
+
|
|
21
|
+
For prompt normalization, pick a provider once:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ollama pull llama3.2 # free, runs locally
|
|
25
|
+
devjar config --provider ollama --model llama3.2
|
|
26
|
+
devjar prompt "fix login bug"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
| Command | What it does |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `devjar init` | Scan project → generate `CLAUDE.md` (stack, file map, rules) |
|
|
36
|
+
| `devjar prompt "text"` | Rewrite vague input into STAR-C format, copy to clipboard |
|
|
37
|
+
| `devjar update` | Regenerate `CLAUDE.md` after major changes |
|
|
38
|
+
| `devjar update --watch` | Live watcher — updates file map on every save |
|
|
39
|
+
| `devjar stats` | Token savings estimate, streak, per-project breakdown |
|
|
40
|
+
| `devjar config` | Set AI provider, or run setup wizard |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Provider setup
|
|
45
|
+
|
|
46
|
+
**Ollama — free, local, no account needed (recommended)**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Install from https://ollama.com, then:
|
|
50
|
+
ollama pull llama3.2
|
|
51
|
+
devjar config --provider ollama --model llama3.2
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Cloud providers**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
devjar config --provider gemini --key AIza... # free tier at aistudio.google.com
|
|
58
|
+
devjar config --provider anthropic --key sk-ant-...
|
|
59
|
+
devjar config --provider openai --key sk-...
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
First time you run `devjar prompt` with no config, the setup wizard runs automatically.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## What it looks like
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
$ devjar init
|
|
70
|
+
⬡ devjar init → /your-project
|
|
71
|
+
────────────────────────────────────────────────────
|
|
72
|
+
Phase 1 Scanning project structure...
|
|
73
|
+
✓ 115 files | Stack: React + Vite
|
|
74
|
+
Phase 2 Pattern extraction via Haiku...
|
|
75
|
+
✓ 5 rules extracted from 4 key files
|
|
76
|
+
Phase 3 Writing CLAUDE.md...
|
|
77
|
+
────────────────────────────────────────────────────
|
|
78
|
+
✓ CLAUDE.md generated — 115 files scanned, 5 rules extracted
|
|
79
|
+
→ /your-project/CLAUDE.md
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
$ devjar prompt "login not working after deploy"
|
|
84
|
+
⬡ devjar prompt
|
|
85
|
+
────────────────────────────────────────────────────
|
|
86
|
+
Provider: ollama/llama3.2
|
|
87
|
+
Input: login not working after deploy
|
|
88
|
+
✓ CLAUDE.md loaded (7236 chars)
|
|
89
|
+
|
|
90
|
+
─── STAR-C Prompt ───────────────────────────────────
|
|
91
|
+
S — care-home — React + Vite, auth via httpOnly cookie
|
|
92
|
+
T — Debug login failure introduced after deployment
|
|
93
|
+
A — Check src/routes/auth.js COOKIE_OPTIONS (SameSite attr)
|
|
94
|
+
Verify KV session creation on login success
|
|
95
|
+
R — Login succeeds, sc_token cookie set, /api/auth/me returns user
|
|
96
|
+
C — Don't change PBKDF2 iterations (CF Workers hard cap: 100k)
|
|
97
|
+
Don't rotate JWT_SECRET without flushing KV sessions
|
|
98
|
+
────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
Copy to clipboard? (Y/n) y
|
|
101
|
+
✓ Copied
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## How it works
|
|
107
|
+
|
|
108
|
+
`devjar init` walks your project, reads `package.json` + config files, then sends 3–5 key files to your AI provider and extracts naming conventions, patterns, and 5 unbreakable rules. Writes everything to `CLAUDE.md`.
|
|
109
|
+
|
|
110
|
+
`devjar prompt` sends your vague input + your `CLAUDE.md` to your provider. Gets back a structured prompt with the exact files to check, expected result, and constraints inferred from your codebase. One provider call ≈ $0.00 with Ollama.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Requirements
|
|
115
|
+
|
|
116
|
+
- Node.js 18+
|
|
117
|
+
- `devjar init` — fully offline, no provider needed
|
|
118
|
+
- `devjar prompt` — Ollama (free) or any cloud API key
|
|
119
|
+
- `devjar stats` / `devjar update` — fully offline
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
MIT
|
package/bin/devjar.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { init } from '../src/init.js';
|
|
4
|
+
import { prompt } from '../src/prompt.js';
|
|
5
|
+
import { update } from '../src/update.js';
|
|
6
|
+
import { stats } from '../src/stats.js';
|
|
7
|
+
import { configCommand } from '../src/config.js';
|
|
8
|
+
|
|
9
|
+
const program = new Command();
|
|
10
|
+
|
|
11
|
+
program
|
|
12
|
+
.name('devjar')
|
|
13
|
+
.description('Jarvis CLI — scan projects, normalize prompts, watch files, track tokens')
|
|
14
|
+
.version('0.1.0');
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.command('init [dir]')
|
|
18
|
+
.description('Scan project and build Jarvis knowledge map')
|
|
19
|
+
.option('-o, --output <file>', 'output map file', 'jarvis-map.txt')
|
|
20
|
+
.option('--depth <n>', 'max directory depth to scan', '4')
|
|
21
|
+
.action(init);
|
|
22
|
+
|
|
23
|
+
program
|
|
24
|
+
.command('prompt <text...>')
|
|
25
|
+
.description('Normalize a prompt into STAR-C format')
|
|
26
|
+
.option('--copy', 'copy result to clipboard')
|
|
27
|
+
.option('--inject', 'inject into Claude Code session context')
|
|
28
|
+
.action(prompt);
|
|
29
|
+
|
|
30
|
+
program
|
|
31
|
+
.command('update [dir]')
|
|
32
|
+
.description('Regenerate CLAUDE.md, or watch for live updates with --watch')
|
|
33
|
+
.option('--watch', 'watch for file changes and update live')
|
|
34
|
+
.option('--depth <n>', 'max directory depth to scan', '2')
|
|
35
|
+
.option('--debounce <ms>', 'debounce delay in ms for watch mode', '500')
|
|
36
|
+
.action(update);
|
|
37
|
+
|
|
38
|
+
program
|
|
39
|
+
.command('stats')
|
|
40
|
+
.description('Show prompt history and estimated token savings')
|
|
41
|
+
.option('--reset', 'clear all history')
|
|
42
|
+
.option('--json', 'output raw JSON')
|
|
43
|
+
.action(stats);
|
|
44
|
+
|
|
45
|
+
program
|
|
46
|
+
.command('config')
|
|
47
|
+
.description('Set AI provider (ollama/anthropic/gemini/openai) or run setup wizard')
|
|
48
|
+
.option('--provider <name>', 'provider name: ollama, anthropic, gemini, openai')
|
|
49
|
+
.option('--model <name>', 'model name (e.g. llama3.2, gpt-4o-mini)')
|
|
50
|
+
.option('--key <apikey>', 'API key for cloud providers')
|
|
51
|
+
.option('--url <url>', 'custom Ollama base URL (default: http://localhost:11434)')
|
|
52
|
+
.option('--show', 'show current config')
|
|
53
|
+
.action(configCommand);
|
|
54
|
+
|
|
55
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sumant.pathak/devjar",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scan your project into a Claude-ready knowledge map. Use 60-70% fewer tokens on any AI coding tool.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"devjar": "bin/devjar.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/devjar.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@anthropic-ai/sdk": "^0.39.0",
|
|
14
|
+
"chalk": "^5.6.2",
|
|
15
|
+
"chokidar": "^5.0.0",
|
|
16
|
+
"clipboardy": "^5.3.1",
|
|
17
|
+
"commander": "^12.1.0"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"claude",
|
|
24
|
+
"ai",
|
|
25
|
+
"prompt",
|
|
26
|
+
"developer-tools",
|
|
27
|
+
"ollama",
|
|
28
|
+
"token",
|
|
29
|
+
"cli",
|
|
30
|
+
"jarvis",
|
|
31
|
+
"star-c",
|
|
32
|
+
"token-tracker"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT"
|
|
35
|
+
}
|
package/src/config.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// devjar config — provider setup, wizard, config display
|
|
2
|
+
|
|
3
|
+
import readline from 'readline';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { loadConfig, saveConfig } from './providers/index.js';
|
|
6
|
+
|
|
7
|
+
const PROVIDERS = {
|
|
8
|
+
1: { name: 'ollama', label: 'Ollama (free, local, recommended)', defaultModel: 'llama3.2', needsKey: false },
|
|
9
|
+
2: { name: 'anthropic', label: 'Anthropic (API key required)', defaultModel: 'claude-haiku-4-5-20251001', needsKey: true },
|
|
10
|
+
3: { name: 'gemini', label: 'Gemini (free tier available)', defaultModel: 'gemini-2.0-flash', needsKey: true },
|
|
11
|
+
4: { name: 'openai', label: 'OpenAI (API key required)', defaultModel: 'gpt-4o-mini', needsKey: true },
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function ask(rl, question) {
|
|
15
|
+
return new Promise(resolve => rl.question(question, ans => resolve(ans.trim())));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function runWizard() {
|
|
19
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
20
|
+
|
|
21
|
+
console.log(chalk.bold.blue('⬡ devjar') + chalk.gray(' — first run setup'));
|
|
22
|
+
console.log(chalk.gray('─'.repeat(52)));
|
|
23
|
+
console.log(chalk.white('Which AI provider do you want to use?\n'));
|
|
24
|
+
|
|
25
|
+
for (const [num, p] of Object.entries(PROVIDERS)) {
|
|
26
|
+
const tag = num === '1' ? chalk.green(' ← default') : '';
|
|
27
|
+
console.log(` ${chalk.cyan(num + '.')} ${p.label}${tag}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log();
|
|
31
|
+
const choice = await ask(rl, chalk.bold('Enter number') + chalk.gray(' [1]: ')) || '1';
|
|
32
|
+
const provider = PROVIDERS[choice] || PROVIDERS[1];
|
|
33
|
+
|
|
34
|
+
let apiKey = '';
|
|
35
|
+
if (provider.needsKey) {
|
|
36
|
+
console.log(chalk.gray(`\n ${provider.name} requires an API key.`));
|
|
37
|
+
apiKey = await ask(rl, chalk.bold(' Paste API key: '));
|
|
38
|
+
if (!apiKey) {
|
|
39
|
+
console.log(chalk.yellow(' No key entered — switching to Ollama.'));
|
|
40
|
+
rl.close();
|
|
41
|
+
return runWizard(); // restart with ollama default path
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
rl.close();
|
|
46
|
+
|
|
47
|
+
const cfg = { provider: provider.name, model: provider.defaultModel, ...(apiKey && { apiKey }) };
|
|
48
|
+
saveConfig(cfg);
|
|
49
|
+
|
|
50
|
+
console.log();
|
|
51
|
+
console.log(chalk.green('✓ Configured: ') + chalk.white(`${provider.name} / ${provider.defaultModel}`));
|
|
52
|
+
if (provider.name === 'ollama') {
|
|
53
|
+
console.log(chalk.gray(' Make sure Ollama is running: ') + chalk.cyan('ollama serve'));
|
|
54
|
+
console.log(chalk.gray(' Pull model if needed: ') + chalk.cyan(`ollama pull ${provider.defaultModel}`));
|
|
55
|
+
}
|
|
56
|
+
console.log();
|
|
57
|
+
|
|
58
|
+
return cfg;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function configCommand(options) {
|
|
62
|
+
// devjar config --show
|
|
63
|
+
if (options.show) {
|
|
64
|
+
const cfg = loadConfig();
|
|
65
|
+
if (!cfg) {
|
|
66
|
+
console.log(chalk.yellow('No config found.') + chalk.gray(' Run `devjar config` to set up.'));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
console.log(chalk.bold.blue('⬡ devjar') + chalk.gray(' config'));
|
|
70
|
+
console.log(chalk.gray('─'.repeat(52)));
|
|
71
|
+
console.log(chalk.gray(' Provider: ') + chalk.cyan(cfg.provider));
|
|
72
|
+
console.log(chalk.gray(' Model: ') + chalk.white(cfg.model));
|
|
73
|
+
if (cfg.apiKey) console.log(chalk.gray(' API Key: ') + chalk.white(cfg.apiKey.slice(0, 8) + '••••••••'));
|
|
74
|
+
if (cfg.ollamaUrl) console.log(chalk.gray(' Ollama: ') + chalk.white(cfg.ollamaUrl));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// devjar config --provider X --model Y --key Z
|
|
79
|
+
if (options.provider) {
|
|
80
|
+
const known = Object.values(PROVIDERS).map(p => p.name);
|
|
81
|
+
if (!known.includes(options.provider)) {
|
|
82
|
+
console.log(chalk.red(`Unknown provider "${options.provider}".`) + chalk.gray(` Choose: ${known.join(', ')}`));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const existing = loadConfig() || {};
|
|
87
|
+
const defaultModel = Object.values(PROVIDERS).find(p => p.name === options.provider)?.defaultModel;
|
|
88
|
+
const cfg = {
|
|
89
|
+
...existing,
|
|
90
|
+
provider: options.provider,
|
|
91
|
+
model: options.model || existing.model || defaultModel,
|
|
92
|
+
...(options.key && { apiKey: options.key }),
|
|
93
|
+
...(options.url && { ollamaUrl: options.url }),
|
|
94
|
+
};
|
|
95
|
+
saveConfig(cfg);
|
|
96
|
+
|
|
97
|
+
console.log(chalk.green('✓ Saved: ') + chalk.white(`${cfg.provider} / ${cfg.model}`));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// No flags — run wizard
|
|
102
|
+
await runWizard();
|
|
103
|
+
}
|