@adithya-naik/cmd-tracker 1.0.2 → 1.0.3

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.
@@ -26,157 +26,157 @@ const CATEGORIES = {
26
26
  * Any command starting with "git" goes here
27
27
  * Examples: git status, git push, git commit -m "msg"
28
28
  */
29
- git: ["git"],
29
+ git: ['git'],
30
30
 
31
31
  /*
32
32
  * Any command starting with "npm" or "npx" goes here
33
33
  * Examples: npm install, npm run dev, npx create-react-app
34
34
  */
35
- npm: ["npm", "npx"],
35
+ npm: ['npm', 'npx'],
36
36
 
37
37
  /*
38
38
  * Any command starting with "docker" goes here
39
39
  * Examples: docker ps, docker build, docker-compose up
40
40
  */
41
- docker: ["docker", "docker-compose"],
41
+ docker: ['docker', 'docker-compose'],
42
42
 
43
43
  /*
44
44
  * Common linux commands go here
45
45
  * Examples: ls -la, cd projects, mkdir new-folder
46
46
  */
47
- linux: [
48
- "ls", "cd", "pwd", "mkdir", "rmdir",
49
- "rm", "cp", "mv", "cat", "touch",
50
- "chmod", "chown", "grep", "find",
51
- "echo", "sudo", "apt", "apt-get",
52
- "curl", "wget", "nano", "vim",
53
- "less", "head", "tail", "ps",
54
- "top", "kill", "df", "du",
55
- "tar", "zip", "unzip", "ssh",
56
- "scp", "rsync"
57
- ],
47
+ linux: [
48
+ 'ls', 'cd', 'pwd', 'mkdir', 'rmdir',
49
+ 'rm', 'cp', 'mv', 'cat', 'touch',
50
+ 'chmod', 'chown', 'grep', 'find',
51
+ 'echo', 'sudo', 'apt', 'apt-get',
52
+ 'curl', 'wget', 'nano', 'vim',
53
+ 'less', 'head', 'tail', 'ps',
54
+ 'top', 'kill', 'df', 'du',
55
+ 'tar', 'zip', 'unzip', 'ssh',
56
+ 'scp', 'rsync'
57
+ ],
58
58
 
59
59
  /*
60
60
  * Node.js related commands
61
61
  * Examples: node index.js, nodemon server.js
62
62
  */
63
- node: ["node", "nodemon"],
63
+ node: ['node', 'nodemon'],
64
64
 
65
65
  /*
66
66
  * Angular CLI commands
67
67
  * Examples: ng new my-app, ng serve, ng generate component
68
68
  */
69
- angular: ["ng"],
69
+ angular: ['ng'],
70
70
 
71
71
  /*
72
72
  * Python commands
73
73
  * Examples: python app.py, pip install flask
74
74
  */
75
- python: ["python", "python3", "pip", "pip3"],
75
+ python: ['python', 'python3', 'pip', 'pip3'],
76
76
 
77
- go: ["go"],
77
+ go: ['go'],
78
78
 
79
- /*
79
+ /*
80
80
  * Java ecosystem commands
81
81
  * Examples: java Main, javac Main.java,
82
82
  * mvn package, gradle build
83
83
  */
84
- java: ["java", "javac", "mvn", "gradle"],
84
+ java: ['java', 'javac', 'mvn', 'gradle'],
85
85
 
86
- /*
86
+ /*
87
87
  * Rust development commands
88
88
  * Examples: cargo build, cargo run,
89
89
  * cargo test, rustc main.rs
90
90
  */
91
- rust: ["cargo", "rustc"],
91
+ rust: ['cargo', 'rustc'],
92
92
 
93
- /*
93
+ /*
94
94
  * .NET commands
95
95
  * Examples: dotnet run, dotnet build,
96
96
  * dotnet new console
97
97
  */
98
- dotnet: ["dotnet"],
98
+ dotnet: ['dotnet'],
99
99
 
100
- /*
100
+ /*
101
101
  * Kubernetes tooling commands
102
102
  * Examples: kubectl get pods,
103
103
  * kubectl apply -f app.yaml,
104
104
  * helm install my-app chart/
105
105
  */
106
- kubernetes: ["kubectl", "helm"],
106
+ kubernetes: ['kubectl', 'helm'],
107
107
 
108
- /*
108
+ /*
109
109
  * Database CLI commands
110
110
  * Examples: mysql -u root -p,
111
111
  * psql mydb,
112
112
  * mongosh,
113
113
  * redis-cli
114
114
  */
115
- database: [
116
- "mysql",
117
- "psql",
118
- "sqlite3",
119
- "mongosh",
120
- "redis-cli"
121
- ],
115
+ database: [
116
+ 'mysql',
117
+ 'psql',
118
+ 'sqlite3',
119
+ 'mongosh',
120
+ 'redis-cli'
121
+ ],
122
122
 
123
- /*
123
+ /*
124
124
  * Cloud provider CLI commands
125
125
  * Examples: aws s3 ls,
126
126
  * gcloud compute instances list,
127
127
  * az login
128
128
  */
129
- cloud: [
130
- "aws",
131
- "gcloud",
132
- "az"
133
- ],
129
+ cloud: [
130
+ 'aws',
131
+ 'gcloud',
132
+ 'az'
133
+ ],
134
134
 
135
- /*
135
+ /*
136
136
  * Package manager commands
137
137
  * Examples: yarn install,
138
138
  * pnpm dev,
139
139
  * brew install git,
140
140
  * snap install code
141
141
  */
142
- packagemanagers: [
143
- "yarn",
144
- "pnpm",
145
- "brew",
146
- "snap"
147
- ],
142
+ packagemanagers: [
143
+ 'yarn',
144
+ 'pnpm',
145
+ 'brew',
146
+ 'snap'
147
+ ],
148
148
 
149
- /*
149
+ /*
150
150
  * Testing framework commands
151
151
  * Examples: jest,
152
152
  * vitest run,
153
153
  * playwright test,
154
154
  * cypress open
155
155
  */
156
- testing: [
157
- "jest",
158
- "vitest",
159
- "playwright",
160
- "cypress"
161
- ],
156
+ testing: [
157
+ 'jest',
158
+ 'vitest',
159
+ 'playwright',
160
+ 'cypress'
161
+ ],
162
162
 
163
- /*
163
+ /*
164
164
  * AI coding assistant CLI commands
165
165
  * Examples: claude, gemini, codex,
166
166
  * opencode, aider, q chat
167
167
  */
168
- ai: [
169
- "claude",
170
- "gemini",
171
- "codex",
172
- "c",
173
- "opencode",
174
- "aider",
175
- "q",
176
- "warp",
177
- "ollama",
178
- "huggingface-cli"
179
- ],
168
+ ai: [
169
+ 'claude',
170
+ 'gemini',
171
+ 'codex',
172
+ 'c',
173
+ 'opencode',
174
+ 'aider',
175
+ 'q',
176
+ 'warp',
177
+ 'ollama',
178
+ 'huggingface-cli'
179
+ ],
180
180
 
181
181
  };
182
182
 
@@ -201,8 +201,8 @@ function categorize(command) {
201
201
  * Safety check — if command is empty or not a string, return "others"
202
202
  * This prevents crashes if something unexpected is passed in
203
203
  */
204
- if (!command || typeof command !== "string") {
205
- return "others";
204
+ if (!command || typeof command !== 'string') {
205
+ return 'others';
206
206
  }
207
207
 
208
208
  /*
@@ -216,7 +216,7 @@ function categorize(command) {
216
216
  * → split(" ") → ["git", "status"]
217
217
  * → [0] → "git"
218
218
  */
219
- const firstWord = command.trim().toLowerCase().split(" ")[0];
219
+ const firstWord = command.trim().toLowerCase().split(' ')[0];
220
220
 
221
221
  /*
222
222
  * Object.entries() converts our CATEGORIES object into an array like:
@@ -248,7 +248,7 @@ function categorize(command) {
248
248
  * If no category matched — return "others"
249
249
  * This is our catch-all category
250
250
  */
251
- return "others";
251
+ return 'others';
252
252
  }
253
253
 
254
254
  /*
package/src/utils/hook.js CHANGED
@@ -17,9 +17,9 @@
17
17
  * 4. User sources their config → automatic capture starts!
18
18
  */
19
19
 
20
- const fs = require("node:fs");
21
- const path = require("node:path");
22
- const os = require("node:os");
20
+ const fs = require('node:fs');
21
+ const path = require('node:path');
22
+ const os = require('node:os');
23
23
 
24
24
  /*
25
25
  * os module — built into Node.js
@@ -28,15 +28,14 @@ const os = require("node:os");
28
28
  * Mac/Linux → /home/adithya
29
29
  */
30
30
  const HOME_DIR = os.homedir();
31
-
32
31
  /*
33
32
  * Shell config file paths
34
33
  * These are standard locations for shell config files
35
34
  */
36
35
  const SHELL_CONFIGS = {
37
- bash: path.join(HOME_DIR, ".bashrc"),
38
- zsh: path.join(HOME_DIR, ".zshrc"),
39
- fish: path.join(HOME_DIR, ".config/fish/config.fish"),
36
+ bash: path.join(HOME_DIR, '.bashrc'),
37
+ zsh: path.join(HOME_DIR, '.zshrc'),
38
+ fish: path.join(HOME_DIR, '.config/fish/config.fish'),
40
39
 
41
40
  };
42
41
 
@@ -69,42 +68,42 @@ const SHELL_CONFIGS = {
69
68
  * This is cleaner and works on all bash/zsh versions
70
69
  */
71
70
  const HOOK_SCRIPT = [
72
- "",
73
- "# cmd-tracker shell hook — auto saves every command you type",
74
- "_cmd_tracker_hook() {",
75
- " local LAST_CMD",
76
- " LAST_CMD=$(history 1 | sed 's/^[[:space:]]*[0-9]*[[:space:]]*//')",
71
+ '',
72
+ '# cmd-tracker shell hook — auto saves every command you type',
73
+ '_cmd_tracker_hook() {',
74
+ ' local LAST_CMD',
75
+ ' LAST_CMD=$(history 1 | sed \'s/^[[:space:]]*[0-9]*[[:space:]]*//\')',
77
76
  ' if [ -n "$LAST_CMD" ]; then',
78
77
  ' tracker save "$LAST_CMD" > /dev/null 2>&1',
79
- " fi",
80
- "}",
81
- "",
82
- "# For zsh",
78
+ ' fi',
79
+ '}',
80
+ '',
81
+ '# For zsh',
83
82
  'if [ -n "$ZSH_VERSION" ]; then',
84
- " autoload -U add-zsh-hook",
85
- " add-zsh-hook precmd _cmd_tracker_hook",
86
- "fi",
87
- "",
88
- "# For bash",
83
+ ' autoload -U add-zsh-hook',
84
+ ' add-zsh-hook precmd _cmd_tracker_hook',
85
+ 'fi',
86
+ '',
87
+ '# For bash',
89
88
  'if [ -n "$BASH_VERSION" ]; then',
90
89
  ' PROMPT_COMMAND="_cmd_tracker_hook${PROMPT_COMMAND:+;$PROMPT_COMMAND}"',
91
- "fi",
92
- ""
93
- ].join("\n");
90
+ 'fi',
91
+ ''
92
+ ].join('\n');
94
93
 
95
94
 
96
95
  const FISH_HOOK_SCRIPT = [
97
- "",
98
- "# cmd-tracker shell hook — auto saves every command you type",
99
- "function __cmd_tracker_postexec --on-event fish_postexec",
100
- " set -l last_cmd (history --max=1)",
101
- "",
102
- ' if test -n "$last_cmd"',
103
- ' tracker save "$last_cmd" >/dev/null 2>&1',
104
- " end",
105
- "end",
106
- "",
107
- ].join("\n");
96
+ '',
97
+ '# cmd-tracker shell hook — auto saves every command you type',
98
+ 'function __cmd_tracker_postexec --on-event fish_postexec',
99
+ ' set -l last_cmd (history --max=1)',
100
+ '',
101
+ ' if test -n "$last_cmd"',
102
+ ' tracker save "$last_cmd" >/dev/null 2>&1',
103
+ ' end',
104
+ 'end',
105
+ '',
106
+ ].join('\n');
108
107
 
109
108
 
110
109
  /*
@@ -113,7 +112,7 @@ const FISH_HOOK_SCRIPT = [
113
112
  * → Check if hook already exists (avoid duplicates)
114
113
  * → Find and remove hook when user runs tracker unhook
115
114
  */
116
- const HOOK_MARKER = "# cmd-tracker shell hook — auto saves every command you type";
115
+ const HOOK_MARKER = '# cmd-tracker shell hook — auto saves every command you type';
117
116
 
118
117
  /*
119
118
  * detectShell() — detects which shell user is running
@@ -128,28 +127,30 @@ const HOOK_MARKER = "# cmd-tracker shell hook — auto saves every command you t
128
127
  * @returns {string} — "bash", "zsh", "fish", or "unknown"
129
128
  */
130
129
  function detectShell() {
131
- const shell = process.env.SHELL || "";
130
+ const shell = process.env.SHELL || '';
132
131
 
133
- if (process.env.FISH_VERSION) return "fish";
132
+ if (process.env.FISH_VERSION) return 'fish';
134
133
 
135
- if (shell.includes("fish")) return "fish";
134
+ if (shell.includes('fish')) return 'fish';
136
135
 
137
- try {
138
- const ppid = process.ppid;
139
- const { execFileSync } = require("node:child_process");
140
- const comm = execFileSync("/bin/ps", ["-o", "comm=", "-p", String(ppid)], { encoding: "utf-8" }).trim();
141
- if (comm.includes("fish")) return "fish";
142
- if (comm.includes("zsh")) return "zsh";
143
- if (comm.includes("bash")) return "bash";
144
- } catch (_) {}
136
+ try {
137
+ const ppid = process.ppid;
138
+ const { execFileSync } = require('node:child_process');
139
+ const comm = execFileSync('/bin/ps', ['-o', 'comm=', '-p', String(ppid)], { encoding: 'utf-8' }).trim();
140
+ if (comm.includes('fish')) return 'fish';
141
+ if (comm.includes('zsh')) return 'zsh';
142
+ if (comm.includes('bash')) return 'bash';
143
+ } catch {
144
+ // ignore ps command errors
145
+ }
145
146
 
146
- if (shell.includes("zsh")) return "zsh";
147
- if (shell.includes("bash")) return "bash";
147
+ if (shell.includes('zsh')) return 'zsh';
148
+ if (shell.includes('bash')) return 'bash';
148
149
 
149
- const comspec = process.env.ComSpec || "";
150
- if (comspec.includes("cmd.exe")) return "unknown";
150
+ const comspec = process.env.ComSpec || '';
151
+ if (comspec.includes('cmd.exe')) return 'unknown';
151
152
 
152
- return "unknown";
153
+ return 'unknown';
153
154
  }
154
155
 
155
156
  /*
@@ -176,10 +177,10 @@ function installHook() {
176
177
  * If shell is unknown — we can't install hook
177
178
  * This happens on Windows CMD/PowerShell
178
179
  */
179
- if (shell === "unknown") {
180
+ if (shell === 'unknown') {
180
181
  return {
181
182
  success: false,
182
- message: "❌ Automatic hook not supported on Windows CMD/PowerShell\n💡 Use Git Bash or WSL for automatic capture"
183
+ message: '❌ Automatic hook not supported on Windows CMD/PowerShell\n💡 Use Git Bash or WSL for automatic capture'
183
184
  };
184
185
  }
185
186
 
@@ -190,7 +191,7 @@ function installHook() {
190
191
  * Look for our unique marker in the config file
191
192
  */
192
193
  if (fs.existsSync(configFile)) {
193
- const content = fs.readFileSync(configFile, "utf-8");
194
+ const content = fs.readFileSync(configFile, 'utf-8');
194
195
 
195
196
  if (content.includes(HOOK_MARKER)) {
196
197
  return {
@@ -204,17 +205,17 @@ function installHook() {
204
205
  * Append hook script to shell config file
205
206
  * appendFileSync → adds to end without deleting existing content
206
207
  */
207
- if (shell === "fish") {
208
- fs.mkdirSync(path.dirname(configFile), { recursive: true });
209
- }
208
+ if (shell === 'fish') {
209
+ fs.mkdirSync(path.dirname(configFile), { recursive: true });
210
+ }
210
211
 
211
- /*
212
+ /*
212
213
  * Choose correct hook
213
214
  */
214
- const hookScript =
215
- shell === "fish" ? FISH_HOOK_SCRIPT : HOOK_SCRIPT;
215
+ const hookScript =
216
+ shell === 'fish' ? FISH_HOOK_SCRIPT : HOOK_SCRIPT;
216
217
 
217
- fs.appendFileSync(configFile, hookScript);
218
+ fs.appendFileSync(configFile, hookScript);
218
219
 
219
220
  return {
220
221
  success: true,
@@ -225,10 +226,10 @@ function installHook() {
225
226
 
226
227
  } catch (error) {
227
228
 
228
- if (error.code === "EACCES") {
229
+ if (error.code === 'EACCES') {
229
230
  return {
230
231
  success: false,
231
- message: "❌ Permission denied! Try with sudo/admin permissions"
232
+ message: '❌ Permission denied! Try with sudo/admin permissions'
232
233
  };
233
234
  }
234
235
 
@@ -253,11 +254,11 @@ function removeHook() {
253
254
  if (!fs.existsSync(configFile)) {
254
255
  return {
255
256
  success: false,
256
- message: "❌ Shell config file not found"
257
+ message: '❌ Shell config file not found'
257
258
  };
258
259
  }
259
260
 
260
- const content = fs.readFileSync(configFile, "utf-8");
261
+ const content = fs.readFileSync(configFile, 'utf-8');
261
262
 
262
263
  /*
263
264
  * Check if hook exists
@@ -265,7 +266,7 @@ function removeHook() {
265
266
  if (!content.includes(HOOK_MARKER)) {
266
267
  return {
267
268
  success: false,
268
- message: "⚠️ Hook not found in shell config"
269
+ message: '⚠️ Hook not found in shell config'
269
270
  };
270
271
  }
271
272
 
@@ -274,7 +275,7 @@ function removeHook() {
274
275
  * Split by marker → take everything before it
275
276
  * Then trim trailing whitespace
276
277
  */
277
- const newContent = content.split(HOOK_MARKER)[0].trimEnd() + "\n";
278
+ const newContent = content.split(HOOK_MARKER)[0].trimEnd() + '\n';
278
279
  fs.writeFileSync(configFile, newContent);
279
280
 
280
281
  return {
@@ -303,7 +304,7 @@ function isHookInstalled() {
303
304
 
304
305
  if (!fs.existsSync(configFile)) return false;
305
306
 
306
- const content = fs.readFileSync(configFile, "utf-8");
307
+ const content = fs.readFileSync(configFile, 'utf-8');
307
308
  return content.includes(HOOK_MARKER);
308
309
 
309
310
  } catch (error) {
@@ -11,14 +11,14 @@
11
11
  * Mac/Linux: /home/user/project/.tracker/commands.json
12
12
  * path module handles this difference automatically
13
13
  */
14
- const fs = require("fs");
15
- const path = require("path");
14
+ const fs = require('fs');
15
+ const path = require('path');
16
16
 
17
17
  /*
18
18
  * Import our categorize function from categorizer.js
19
19
  * We need it here to know WHICH category to save the command in
20
20
  */
21
- const { categorize } = require("./categorizer");
21
+ const { categorize } = require('./categorizer');
22
22
 
23
23
  /*
24
24
  * process.cwd() → Current Working Directory
@@ -31,13 +31,13 @@ const { categorize } = require("./categorizer");
31
31
  * This is VERY important — we want to save commands in THEIR repo
32
32
  * not in our package folder
33
33
  */
34
- const TRACKER_DIR = path.join(process.cwd(), ".tracker");
34
+ const TRACKER_DIR = path.join(process.cwd(), '.tracker');
35
35
 
36
36
  /*
37
37
  * This is where all commands will be saved
38
38
  * .tracker/commands.json inside the user's repo
39
39
  */
40
- const COMMANDS_FILE = path.join(TRACKER_DIR, "commands.json");
40
+ const COMMANDS_FILE = path.join(TRACKER_DIR, 'commands.json');
41
41
 
42
42
  /*
43
43
  * This is our default empty structure
@@ -63,7 +63,7 @@ function getDefaultStructure() {
63
63
  kubernetes: [],
64
64
  database: [],
65
65
  cloud: [],
66
- packagemanagers: [],
66
+ packagemanagers: [],
67
67
  testing: [],
68
68
  ai: [],
69
69
  others: [],
@@ -92,7 +92,7 @@ function initStorage() {
92
92
  * Like "mkdir -p" in linux
93
93
  */
94
94
  fs.mkdirSync(TRACKER_DIR, { recursive: true });
95
- console.log("✅ Created .tracker folder");
95
+ console.log('✅ Created .tracker folder');
96
96
  }
97
97
 
98
98
  /*
@@ -109,7 +109,7 @@ function initStorage() {
109
109
  COMMANDS_FILE,
110
110
  JSON.stringify(getDefaultStructure(), null, 2)
111
111
  );
112
- console.log("✅ Created .tracker/commands.json");
112
+ console.log('✅ Created .tracker/commands.json');
113
113
  }
114
114
  }
115
115
 
@@ -132,7 +132,7 @@ function readCommands() {
132
132
  * fs.readFileSync() → reads the file content as text
133
133
  * JSON.parse() → converts JSON text back to JavaScript object
134
134
  */
135
- const fileContent = fs.readFileSync(COMMANDS_FILE, "utf-8");
135
+ const fileContent = fs.readFileSync(COMMANDS_FILE, 'utf-8');
136
136
  const parsed = JSON.parse(fileContent);
137
137
  return { ...getDefaultStructure(), ...parsed };
138
138
  }
@@ -149,7 +149,7 @@ function saveCommand(command) {
149
149
  * Safety check — don't save empty commands
150
150
  */
151
151
  if (!command || !command.trim()) {
152
- return { saved: false, reason: "empty command" };
152
+ return { saved: false, reason: 'empty command' };
153
153
  }
154
154
 
155
155
  /*
@@ -183,7 +183,7 @@ function saveCommand(command) {
183
183
  );
184
184
 
185
185
  if (isDuplicate) {
186
- return { saved: false, reason: "duplicate", category };
186
+ return { saved: false, reason: 'duplicate', category };
187
187
  }
188
188
 
189
189
  /*
@@ -218,7 +218,7 @@ function saveCommand(command) {
218
218
  function toggleFavorite(command) {
219
219
 
220
220
  if (!command || !command.trim()) {
221
- return { success: false, reason: "empty command" };
221
+ return { success: false, reason: 'empty command' };
222
222
  }
223
223
 
224
224
  const cleanCommand = command.trim();
@@ -245,14 +245,14 @@ function toggleFavorite(command) {
245
245
 
246
246
  return {
247
247
  success: true,
248
- action: currentFav ? "removed" : "added",
248
+ action: currentFav ? 'removed' : 'added',
249
249
  command: cleanCommand,
250
250
  category
251
251
  };
252
252
  }
253
253
  }
254
254
 
255
- return { success: false, reason: "command not found" };
255
+ return { success: false, reason: 'command not found' };
256
256
  }
257
257
 
258
258
  /*