@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.
- package/.github/workflows/ci.yml +19 -1
- package/.husky/pre-commit +1 -0
- package/bin/tracker.js +45 -45
- package/eslint.config.js +30 -0
- package/package.json +19 -4
- package/src/commands/clear.js +13 -13
- package/src/commands/export.js +16 -16
- package/src/commands/favorite.js +16 -16
- package/src/commands/hook.js +26 -26
- package/src/commands/init.js +43 -43
- package/src/commands/list.js +32 -32
- package/src/commands/save.js +2 -2
- package/src/commands/search.js +18 -18
- package/src/commands/stats.js +55 -55
- package/src/index.js +2 -2
- package/src/utils/categorizer.js +71 -71
- package/src/utils/hook.js +70 -69
- package/src/utils/storage.js +14 -14
- package/src/utils/validator.js +27 -27
package/.github/workflows/ci.yml
CHANGED
|
@@ -11,6 +11,24 @@ permissions:
|
|
|
11
11
|
contents: read
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
name: Lint Code
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout code
|
|
19
|
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
|
20
|
+
with:
|
|
21
|
+
persist-credentials: false
|
|
22
|
+
- name: Setup Node.js
|
|
23
|
+
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
|
|
24
|
+
with:
|
|
25
|
+
node-version: "20"
|
|
26
|
+
cache: "npm"
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: npm ci
|
|
29
|
+
- name: Run ESLint
|
|
30
|
+
run: npm run lint
|
|
31
|
+
|
|
14
32
|
validate:
|
|
15
33
|
name: Validate Code
|
|
16
34
|
runs-on: ubuntu-latest
|
|
@@ -74,4 +92,4 @@ jobs:
|
|
|
74
92
|
- name: Test CLI loads
|
|
75
93
|
run: |
|
|
76
94
|
node bin/tracker.js --version
|
|
77
|
-
echo "✅ CLI loads successfully!"
|
|
95
|
+
echo "✅ CLI loads successfully!"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx lint-staged
|
package/bin/tracker.js
CHANGED
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
|
|
20
20
|
// Import commander - this package helps us build CLI commands easily
|
|
21
21
|
// Like "list", "stats", "search" etc.
|
|
22
|
-
const { program } = require(
|
|
22
|
+
const { program } = require('commander');
|
|
23
23
|
|
|
24
24
|
// Import package.json to read our version number
|
|
25
25
|
// __dirname = current folder path (bin/)
|
|
26
26
|
// ../ = go one level up (to root of project)
|
|
27
|
-
const packageJson = require(
|
|
27
|
+
const packageJson = require('../package.json');
|
|
28
28
|
|
|
29
29
|
/*
|
|
30
30
|
* Import our init command function
|
|
@@ -34,34 +34,34 @@ const packageJson = require("../package.json");
|
|
|
34
34
|
* bin/ → go up one level → ../
|
|
35
35
|
* then into src/commands/init.js
|
|
36
36
|
*/
|
|
37
|
-
const { initCommand } = require(
|
|
37
|
+
const { initCommand } = require('../src/commands/init');
|
|
38
38
|
|
|
39
39
|
/*
|
|
40
40
|
* Import our save command function
|
|
41
41
|
* This runs automatically via shell hook every time
|
|
42
42
|
* user types a command in terminal
|
|
43
43
|
*/
|
|
44
|
-
const { saveCommandAction } = require(
|
|
44
|
+
const { saveCommandAction } = require('../src/commands/save');
|
|
45
45
|
// Import list command function
|
|
46
|
-
const { listCommand } = require(
|
|
46
|
+
const { listCommand } = require('../src/commands/list');
|
|
47
47
|
// Import search command function
|
|
48
|
-
const { searchCommand } = require(
|
|
49
|
-
const { statsCommand } = require(
|
|
50
|
-
const { clearCommand } = require(
|
|
51
|
-
const { exportCommand } = require(
|
|
52
|
-
const { hookCommand, unhookCommand } = require(
|
|
53
|
-
const { favoriteCommand, favoritesCommand } = require(
|
|
48
|
+
const { searchCommand } = require('../src/commands/search');
|
|
49
|
+
const { statsCommand } = require('../src/commands/stats');
|
|
50
|
+
const { clearCommand } = require('../src/commands/clear');
|
|
51
|
+
const { exportCommand } = require('../src/commands/export');
|
|
52
|
+
const { hookCommand, unhookCommand } = require('../src/commands/hook');
|
|
53
|
+
const { favoriteCommand, favoritesCommand } = require('../src/commands/favorite');
|
|
54
54
|
/*
|
|
55
55
|
* .name() → sets the name of our CLI tool
|
|
56
56
|
* This shows up when user types: tracker --help
|
|
57
57
|
*/
|
|
58
|
-
program.name(
|
|
58
|
+
program.name('tracker');
|
|
59
59
|
|
|
60
60
|
/*
|
|
61
61
|
* .description() → explains what our tool does
|
|
62
62
|
* This also shows up in: tracker --help
|
|
63
63
|
*/
|
|
64
|
-
program.description(
|
|
64
|
+
program.description('📟 A developer tool that auto-captures, categorizes and saves terminal commands per project for easy revision');
|
|
65
65
|
|
|
66
66
|
/*
|
|
67
67
|
* .version() → sets the version of our CLI tool
|
|
@@ -79,21 +79,21 @@ program.version(packageJson.version);
|
|
|
79
79
|
* So user runs: tracker hello
|
|
80
80
|
*/
|
|
81
81
|
program
|
|
82
|
-
.command(
|
|
82
|
+
.command('hello')
|
|
83
83
|
|
|
84
84
|
/*
|
|
85
85
|
* .description() → explains what this command does
|
|
86
86
|
* Shows up when user types: tracker --help
|
|
87
87
|
*/
|
|
88
|
-
.description(
|
|
88
|
+
.description('A test command to check if CLI is working')
|
|
89
89
|
|
|
90
90
|
/*
|
|
91
91
|
* .action() → this function runs when user types: tracker hello
|
|
92
92
|
* Whatever code you write inside here — runs when command is called
|
|
93
93
|
*/
|
|
94
94
|
.action(() => {
|
|
95
|
-
console.log(
|
|
96
|
-
console.log(
|
|
95
|
+
console.log('👋 Hey! tracker CLI is working perfectly!');
|
|
96
|
+
console.log('🚀 Let\'s start tracking your commands!');
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
|
|
@@ -109,8 +109,8 @@ program
|
|
|
109
109
|
* This keeps bin/tracker.js clean and simple
|
|
110
110
|
*/
|
|
111
111
|
program
|
|
112
|
-
.command(
|
|
113
|
-
.description(
|
|
112
|
+
.command('init')
|
|
113
|
+
.description('Initialize cmd-tracker in your current project')
|
|
114
114
|
.action(() => {
|
|
115
115
|
initCommand();
|
|
116
116
|
});
|
|
@@ -132,9 +132,9 @@ program
|
|
|
132
132
|
* "[command]" → square brackets mean OPTIONAL
|
|
133
133
|
*/
|
|
134
134
|
program
|
|
135
|
-
.command(
|
|
136
|
-
.description(
|
|
137
|
-
.argument(
|
|
135
|
+
.command('save')
|
|
136
|
+
.description('Save a command to tracker (called automatically by shell hook)')
|
|
137
|
+
.argument('<command>', 'the terminal command to save')
|
|
138
138
|
.action((command) => {
|
|
139
139
|
saveCommandAction(command);
|
|
140
140
|
});
|
|
@@ -148,9 +148,9 @@ program
|
|
|
148
148
|
* [category] → square brackets = OPTIONAL argument
|
|
149
149
|
*/
|
|
150
150
|
program
|
|
151
|
-
.command(
|
|
152
|
-
.description(
|
|
153
|
-
.argument(
|
|
151
|
+
.command('list')
|
|
152
|
+
.description('List all saved commands or filter by category')
|
|
153
|
+
.argument('[category]', 'optional category filter (git/npm/docker/linux/node/angular/python/others)')
|
|
154
154
|
.action((category) => {
|
|
155
155
|
listCommand(category);
|
|
156
156
|
});
|
|
@@ -164,9 +164,9 @@ program
|
|
|
164
164
|
* <query> → required argument
|
|
165
165
|
*/
|
|
166
166
|
program
|
|
167
|
-
.command(
|
|
168
|
-
.description(
|
|
169
|
-
.argument(
|
|
167
|
+
.command('search')
|
|
168
|
+
.description('Search through all saved commands')
|
|
169
|
+
.argument('<query>', 'search term to look for in saved commands')
|
|
170
170
|
.action((query) => {
|
|
171
171
|
searchCommand(query);
|
|
172
172
|
});
|
|
@@ -176,8 +176,8 @@ program
|
|
|
176
176
|
* tracker stats → shows category breakdown with percentages
|
|
177
177
|
*/
|
|
178
178
|
program
|
|
179
|
-
.command(
|
|
180
|
-
.description(
|
|
179
|
+
.command('stats')
|
|
180
|
+
.description('Show statistics of saved commands by category')
|
|
181
181
|
.action(() => {
|
|
182
182
|
statsCommand();
|
|
183
183
|
});
|
|
@@ -190,9 +190,9 @@ program
|
|
|
190
190
|
* [category] → optional argument
|
|
191
191
|
*/
|
|
192
192
|
program
|
|
193
|
-
.command(
|
|
194
|
-
.description(
|
|
195
|
-
.argument(
|
|
193
|
+
.command('clear')
|
|
194
|
+
.description('Clear all saved commands or a specific category')
|
|
195
|
+
.argument('[category]', 'optional category to clear')
|
|
196
196
|
.action((category) => {
|
|
197
197
|
clearCommand(category);
|
|
198
198
|
});
|
|
@@ -206,9 +206,9 @@ program
|
|
|
206
206
|
* "--csv" → user types --csv to trigger CSV export
|
|
207
207
|
*/
|
|
208
208
|
program
|
|
209
|
-
.command(
|
|
210
|
-
.description(
|
|
211
|
-
.option(
|
|
209
|
+
.command('export')
|
|
210
|
+
.description('Export saved commands as JSON or CSV file')
|
|
211
|
+
.option('--csv', 'export as CSV instead of JSON')
|
|
212
212
|
.action((options) => {
|
|
213
213
|
exportCommand(options);
|
|
214
214
|
});
|
|
@@ -218,8 +218,8 @@ program
|
|
|
218
218
|
* tracker hook → installs shell hook for auto capture
|
|
219
219
|
*/
|
|
220
220
|
program
|
|
221
|
-
.command(
|
|
222
|
-
.description(
|
|
221
|
+
.command('hook')
|
|
222
|
+
.description('Enable automatic command capture via shell hook')
|
|
223
223
|
.action(() => {
|
|
224
224
|
hookCommand();
|
|
225
225
|
});
|
|
@@ -229,8 +229,8 @@ program
|
|
|
229
229
|
* tracker unhook → removes shell hook
|
|
230
230
|
*/
|
|
231
231
|
program
|
|
232
|
-
.command(
|
|
233
|
-
.description(
|
|
232
|
+
.command('unhook')
|
|
233
|
+
.description('Disable automatic command capture')
|
|
234
234
|
.action(() => {
|
|
235
235
|
unhookCommand();
|
|
236
236
|
});
|
|
@@ -241,9 +241,9 @@ program
|
|
|
241
241
|
* tracker favorite "git status" → toggles favorite
|
|
242
242
|
*/
|
|
243
243
|
program
|
|
244
|
-
.command(
|
|
245
|
-
.description(
|
|
246
|
-
.argument(
|
|
244
|
+
.command('favorite')
|
|
245
|
+
.description('Toggle a command as favorite')
|
|
246
|
+
.argument('<command>', 'command to mark as favorite')
|
|
247
247
|
.action((command) => {
|
|
248
248
|
favoriteCommand(command);
|
|
249
249
|
});
|
|
@@ -253,8 +253,8 @@ program
|
|
|
253
253
|
* tracker favorites → lists all favorites
|
|
254
254
|
*/
|
|
255
255
|
program
|
|
256
|
-
.command(
|
|
257
|
-
.description(
|
|
256
|
+
.command('favorites')
|
|
257
|
+
.description('List all favorited commands')
|
|
258
258
|
.action(() => {
|
|
259
259
|
favoritesCommand();
|
|
260
260
|
});
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const js = require('@eslint/js');
|
|
2
|
+
const globals = require('globals');
|
|
3
|
+
|
|
4
|
+
module.exports = [
|
|
5
|
+
js.configs.recommended,
|
|
6
|
+
{
|
|
7
|
+
files: ['**/*.js'],
|
|
8
|
+
languageOptions: {
|
|
9
|
+
ecmaVersion: 2021,
|
|
10
|
+
sourceType: 'commonjs',
|
|
11
|
+
globals: {
|
|
12
|
+
...globals.node,
|
|
13
|
+
...globals.es2021,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
rules: {
|
|
17
|
+
'no-unused-vars': ['error', {
|
|
18
|
+
argsIgnorePattern: '^_',
|
|
19
|
+
caughtErrors: 'none'
|
|
20
|
+
}],
|
|
21
|
+
'no-console': 'off',
|
|
22
|
+
'quotes': ['error', 'single'],
|
|
23
|
+
'semi': ['error', 'always'],
|
|
24
|
+
'indent': ['error', 2],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
ignores: ['node_modules/', '.tracker/', '*.json'],
|
|
29
|
+
},
|
|
30
|
+
];
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adithya-naik/cmd-tracker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "📟 A developer tool that auto-captures, categorizes and saves terminal commands per project for easy revision",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"tracker": "./bin/tracker.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"test": "echo \"No tests yet\""
|
|
10
|
+
"test": "echo \"No tests yet\"",
|
|
11
|
+
"lint": "eslint .",
|
|
12
|
+
"lint:fix": "eslint . --fix",
|
|
13
|
+
"prepare": "husky install"
|
|
11
14
|
},
|
|
12
15
|
"repository": {
|
|
13
16
|
"type": "git",
|
|
@@ -35,7 +38,19 @@
|
|
|
35
38
|
"node": ">=14.0.0"
|
|
36
39
|
},
|
|
37
40
|
"dependencies": {
|
|
38
|
-
"
|
|
39
|
-
"
|
|
41
|
+
"chalk": "^4.1.2",
|
|
42
|
+
"commander": "^11.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@eslint/js": "^10.0.1",
|
|
46
|
+
"eslint": "^10.6.0",
|
|
47
|
+
"globals": "^17.7.0",
|
|
48
|
+
"husky": "^9.1.7",
|
|
49
|
+
"lint-staged": "^16.4.0"
|
|
50
|
+
},
|
|
51
|
+
"lint-staged": {
|
|
52
|
+
"*.js": [
|
|
53
|
+
"eslint --fix"
|
|
54
|
+
]
|
|
40
55
|
}
|
|
41
56
|
}
|
package/src/commands/clear.js
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
* Now with proper error handling using validator.js
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const fs = require(
|
|
7
|
-
const path = require(
|
|
8
|
-
const readline = require(
|
|
9
|
-
const { readCommands } = require(
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const readline = require('readline');
|
|
9
|
+
const { readCommands } = require('../utils/storage');
|
|
10
10
|
const {
|
|
11
11
|
isInitialized,
|
|
12
12
|
showInitError,
|
|
13
13
|
isValidCategory,
|
|
14
14
|
showCategoryError
|
|
15
|
-
} = require(
|
|
15
|
+
} = require('../utils/validator');
|
|
16
16
|
|
|
17
|
-
const COMMANDS_FILE = path.join(process.cwd(),
|
|
17
|
+
const COMMANDS_FILE = path.join(process.cwd(), '.tracker', 'commands.json');
|
|
18
18
|
|
|
19
19
|
function ask(question) {
|
|
20
20
|
const rl = readline.createInterface({
|
|
@@ -63,8 +63,8 @@ async function clearCommand(category) {
|
|
|
63
63
|
`\n⚠️ Clear all ${data[cat].length} ${cat} commands? (yes/no): `
|
|
64
64
|
);
|
|
65
65
|
|
|
66
|
-
if (answer.toLowerCase() !==
|
|
67
|
-
console.log(
|
|
66
|
+
if (answer.toLowerCase() !== 'yes') {
|
|
67
|
+
console.log('❌ Cancelled\n');
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -79,7 +79,7 @@ async function clearCommand(category) {
|
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
if (total === 0) {
|
|
82
|
-
console.log(
|
|
82
|
+
console.log('\n📭 No commands saved yet\n');
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -87,8 +87,8 @@ async function clearCommand(category) {
|
|
|
87
87
|
`\n⚠️ Clear ALL ${total} saved commands? This cannot be undone! (yes/no): `
|
|
88
88
|
);
|
|
89
89
|
|
|
90
|
-
if (answer.toLowerCase() !==
|
|
91
|
-
console.log(
|
|
90
|
+
if (answer.toLowerCase() !== 'yes') {
|
|
91
|
+
console.log('❌ Cancelled\n');
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -101,8 +101,8 @@ async function clearCommand(category) {
|
|
|
101
101
|
console.log(`\n✅ Cleared all ${total} saved commands\n`);
|
|
102
102
|
|
|
103
103
|
} catch (error) {
|
|
104
|
-
console.log(
|
|
105
|
-
console.log(
|
|
104
|
+
console.log('\n❌ Error clearing commands');
|
|
105
|
+
console.log('💡 Try running tracker init again\n');
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
package/src/commands/export.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* Now with proper error handling using validator.js
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const fs = require(
|
|
7
|
-
const path = require(
|
|
8
|
-
const { readCommands } = require(
|
|
9
|
-
const { isInitialized, showInitError } = require(
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { readCommands } = require('../utils/storage');
|
|
9
|
+
const { isInitialized, showInitError } = require('../utils/validator');
|
|
10
10
|
|
|
11
11
|
function exportCommand(options) {
|
|
12
12
|
|
|
@@ -26,8 +26,8 @@ function exportCommand(options) {
|
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
if (total === 0) {
|
|
29
|
-
console.log(
|
|
30
|
-
console.log(
|
|
29
|
+
console.log('\n📭 No commands to export yet!');
|
|
30
|
+
console.log('💡 Use: tracker save "your command"\n');
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -38,8 +38,8 @@ function exportCommand(options) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
} catch (error) {
|
|
41
|
-
console.log(
|
|
42
|
-
console.log(
|
|
41
|
+
console.log('\n❌ Error exporting commands');
|
|
42
|
+
console.log('💡 Try running tracker init again\n');
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -52,22 +52,22 @@ function exportAsJSON(data, total) {
|
|
|
52
52
|
commands: data
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
const filePath = path.join(process.cwd(),
|
|
55
|
+
const filePath = path.join(process.cwd(), 'tracker-export.json');
|
|
56
56
|
fs.writeFileSync(filePath, JSON.stringify(exportData, null, 2));
|
|
57
57
|
|
|
58
58
|
console.log(`\n✅ Exported ${total} commands to tracker-export.json`);
|
|
59
59
|
console.log(`📁 Location: ${filePath}\n`);
|
|
60
60
|
|
|
61
61
|
} catch (error) {
|
|
62
|
-
console.log(
|
|
63
|
-
console.log(
|
|
62
|
+
console.log('\n❌ Error creating JSON file');
|
|
63
|
+
console.log('💡 Check if you have write permissions in this folder\n');
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function exportAsCSV(data, total) {
|
|
68
68
|
|
|
69
69
|
try {
|
|
70
|
-
let csvContent =
|
|
70
|
+
let csvContent = 'category,command,date\n';
|
|
71
71
|
|
|
72
72
|
for (const [category, commands] of Object.entries(data)) {
|
|
73
73
|
for (const item of commands) {
|
|
@@ -76,16 +76,16 @@ function exportAsCSV(data, total) {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
const filePath = path.join(process.cwd(),
|
|
79
|
+
const filePath = path.join(process.cwd(), 'tracker-export.csv');
|
|
80
80
|
fs.writeFileSync(filePath, csvContent);
|
|
81
81
|
|
|
82
82
|
console.log(`\n✅ Exported ${total} commands to tracker-export.csv`);
|
|
83
83
|
console.log(`📁 Location: ${filePath}`);
|
|
84
|
-
console.log(
|
|
84
|
+
console.log('💡 Open in Excel or Google Sheets for easy revision!\n');
|
|
85
85
|
|
|
86
86
|
} catch (error) {
|
|
87
|
-
console.log(
|
|
88
|
-
console.log(
|
|
87
|
+
console.log('\n❌ Error creating CSV file');
|
|
88
|
+
console.log('💡 Check if you have write permissions in this folder\n');
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
package/src/commands/favorite.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* in commands.json
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const { toggleFavorite, getFavorites } = require(
|
|
13
|
-
const { isInitialized, showInitError } = require(
|
|
12
|
+
const { toggleFavorite, getFavorites } = require('../utils/storage');
|
|
13
|
+
const { isInitialized, showInitError } = require('../utils/validator');
|
|
14
14
|
|
|
15
15
|
/*
|
|
16
16
|
* favoriteCommand() — toggles favorite on a specific command
|
|
@@ -25,8 +25,8 @@ function favoriteCommand(command) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
if (!command || !command.trim()) {
|
|
28
|
-
console.log(
|
|
29
|
-
console.log(
|
|
28
|
+
console.log('\n❌ Please provide a command to favorite');
|
|
29
|
+
console.log('💡 Usage: tracker favorite "git status"\n');
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -34,16 +34,16 @@ function favoriteCommand(command) {
|
|
|
34
34
|
const result = toggleFavorite(command.trim());
|
|
35
35
|
|
|
36
36
|
if (!result.success) {
|
|
37
|
-
if (result.reason ===
|
|
37
|
+
if (result.reason === 'command not found') {
|
|
38
38
|
console.log(`\n❌ Command not found: "${command}"`);
|
|
39
|
-
console.log(
|
|
39
|
+
console.log('💡 Run tracker list to see saved commands\n');
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
console.log(
|
|
42
|
+
console.log('\n❌ Failed to update favorite\n');
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
if (result.action ===
|
|
46
|
+
if (result.action === 'added') {
|
|
47
47
|
console.log(`\n⭐ Added to favorites: ${command}`);
|
|
48
48
|
console.log(`📁 Category: ${result.category}\n`);
|
|
49
49
|
} else {
|
|
@@ -51,8 +51,8 @@ function favoriteCommand(command) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
} catch (error) {
|
|
54
|
-
console.log(
|
|
55
|
-
console.log(
|
|
54
|
+
console.log('\n❌ Error updating favorite');
|
|
55
|
+
console.log('💡 Try running tracker init again\n');
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -70,13 +70,13 @@ function favoritesCommand() {
|
|
|
70
70
|
const favorites = getFavorites();
|
|
71
71
|
|
|
72
72
|
if (favorites.length === 0) {
|
|
73
|
-
console.log(
|
|
74
|
-
console.log(
|
|
73
|
+
console.log('\n⭐ No favorites yet!');
|
|
74
|
+
console.log('💡 Usage: tracker favorite "git status"\n');
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
console.log(
|
|
79
|
-
console.log(
|
|
78
|
+
console.log('\n⭐ CMD-TRACKER — Your Favorites\n');
|
|
79
|
+
console.log('─'.repeat(50));
|
|
80
80
|
|
|
81
81
|
favorites.forEach((item, index) => {
|
|
82
82
|
const date = new Date(item.time).toLocaleDateString();
|
|
@@ -84,11 +84,11 @@ function favoritesCommand() {
|
|
|
84
84
|
console.log(` 📁 ${item.category} 📅 ${date}`);
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
console.log(
|
|
87
|
+
console.log('\n' + '─'.repeat(50));
|
|
88
88
|
console.log(`⭐ Total favorites: ${favorites.length}\n`);
|
|
89
89
|
|
|
90
90
|
} catch (error) {
|
|
91
|
-
console.log(
|
|
91
|
+
console.log('\n❌ Error reading favorites\n');
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
package/src/commands/hook.js
CHANGED
|
@@ -12,9 +12,9 @@ const {
|
|
|
12
12
|
removeHook,
|
|
13
13
|
isHookInstalled,
|
|
14
14
|
detectShell
|
|
15
|
-
} = require(
|
|
15
|
+
} = require('../utils/hook');
|
|
16
16
|
|
|
17
|
-
const { isInitialized, showInitError } = require(
|
|
17
|
+
const { isInitialized, showInitError } = require('../utils/validator');
|
|
18
18
|
|
|
19
19
|
/*
|
|
20
20
|
* hookCommand() — runs when user types: tracker hook
|
|
@@ -30,7 +30,7 @@ function hookCommand() {
|
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
console.log(
|
|
33
|
+
console.log('\n🪄 Setting up automatic command capture...\n');
|
|
34
34
|
|
|
35
35
|
/*
|
|
36
36
|
* Show which shell was detected
|
|
@@ -42,9 +42,9 @@ function hookCommand() {
|
|
|
42
42
|
* Check if already installed
|
|
43
43
|
*/
|
|
44
44
|
if (isHookInstalled()) {
|
|
45
|
-
console.log(
|
|
46
|
-
console.log(
|
|
47
|
-
console.log(
|
|
45
|
+
console.log('\n⚠️ Shell hook is already installed!');
|
|
46
|
+
console.log('💡 Your commands are already being captured automatically');
|
|
47
|
+
console.log('💡 Run: tracker unhook to disable\n');
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -52,22 +52,22 @@ function hookCommand() {
|
|
|
52
52
|
* Install the hook
|
|
53
53
|
*/
|
|
54
54
|
const result = installHook();
|
|
55
|
-
console.log(
|
|
55
|
+
console.log('\n' + result.message);
|
|
56
56
|
|
|
57
57
|
if (result.success) {
|
|
58
|
-
console.log(
|
|
58
|
+
console.log('\n🎯 Almost done! Run this command to activate:');
|
|
59
59
|
/*
|
|
60
60
|
* Always show Unix style path for source command
|
|
61
61
|
* Even on Windows — Git Bash uses Unix paths
|
|
62
62
|
* ~/.bashrc works on all systems
|
|
63
63
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
const sourceCmd = {
|
|
65
|
+
zsh: '~/.zshrc',
|
|
66
|
+
bash: '~/.bashrc',
|
|
67
|
+
fish: '~/.config/fish/config.fish',
|
|
68
|
+
}[result.shell];
|
|
69
69
|
console.log(`\n source ${sourceCmd}\n`);
|
|
70
|
-
console.log(
|
|
70
|
+
console.log('After that — every command you type will be saved automatically! 🚀\n');
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -77,22 +77,22 @@ function hookCommand() {
|
|
|
77
77
|
*/
|
|
78
78
|
function unhookCommand() {
|
|
79
79
|
|
|
80
|
-
console.log(
|
|
80
|
+
console.log('\n🔌 Removing automatic command capture...\n');
|
|
81
81
|
|
|
82
82
|
const result = removeHook();
|
|
83
83
|
console.log(result.message);
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
85
|
+
if (result.success) {
|
|
86
|
+
console.log('\n🎯 Almost done! Run this to apply changes:');
|
|
87
|
+
const shell = result.shell || detectShell();
|
|
88
|
+
const sourceCmd = {
|
|
89
|
+
zsh: '~/.zshrc',
|
|
90
|
+
bash: '~/.bashrc',
|
|
91
|
+
fish: '~/.config/fish/config.fish',
|
|
92
|
+
}[shell];
|
|
93
|
+
console.log(`\n source ${sourceCmd}\n`);
|
|
94
|
+
console.log('After that — automatic capture will be disabled\n');
|
|
95
|
+
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
module.exports = { hookCommand, unhookCommand };
|