shellwise 0.2.4 → 0.2.6
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/README.md +25 -3
- package/package.json +1 -1
- package/src/cli/add.ts +1 -6
- package/src/cli/import.ts +61 -20
- package/src/daemon/server.ts +0 -4
- package/src/db/queries.ts +10 -0
- package/src/utils/constants.ts +0 -1
package/README.md
CHANGED
|
@@ -34,10 +34,13 @@ Tab/Shift+Tab to navigate, Enter to select, Esc to dismiss
|
|
|
34
34
|
> **Important:** This is a CLI tool — install it **globally**.
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
#
|
|
37
|
+
# Homebrew
|
|
38
|
+
brew install kurovu146/tap/shellwise
|
|
39
|
+
|
|
40
|
+
# Bun
|
|
38
41
|
bun install -g shellwise
|
|
39
42
|
|
|
40
|
-
#
|
|
43
|
+
# npm
|
|
41
44
|
npm install -g shellwise
|
|
42
45
|
```
|
|
43
46
|
|
|
@@ -55,6 +58,19 @@ eval "$(shellwise init zsh)"
|
|
|
55
58
|
eval "$(shellwise init bash)"
|
|
56
59
|
```
|
|
57
60
|
|
|
61
|
+
## Update
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Homebrew
|
|
65
|
+
brew upgrade shellwise
|
|
66
|
+
|
|
67
|
+
# Bun
|
|
68
|
+
bun install -g shellwise@latest
|
|
69
|
+
|
|
70
|
+
# npm
|
|
71
|
+
npm install -g shellwise@latest
|
|
72
|
+
```
|
|
73
|
+
|
|
58
74
|
## Usage
|
|
59
75
|
|
|
60
76
|
### Auto-suggest (while typing)
|
|
@@ -139,8 +155,14 @@ shellwise import bash # Import from ~/.bash_history
|
|
|
139
155
|
## Uninstall
|
|
140
156
|
|
|
141
157
|
```bash
|
|
158
|
+
# Homebrew
|
|
159
|
+
brew uninstall shellwise
|
|
160
|
+
|
|
161
|
+
# Bun
|
|
142
162
|
bun remove -g shellwise
|
|
143
|
-
|
|
163
|
+
|
|
164
|
+
# npm
|
|
165
|
+
npm uninstall -g shellwise
|
|
144
166
|
```
|
|
145
167
|
|
|
146
168
|
Shell integration is automatically removed on uninstall. If you still see errors after uninstalling, manually remove these lines from your `~/.zshrc` (or `~/.bashrc`):
|
package/package.json
CHANGED
package/src/cli/add.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { insertCommand } from "../db/queries";
|
|
2
2
|
import { getHostname } from "../utils/platform";
|
|
3
|
-
import { IGNORED_COMMANDS } from "../utils/constants";
|
|
4
3
|
|
|
5
4
|
interface AddOptions {
|
|
6
5
|
command: string;
|
|
@@ -14,7 +13,7 @@ interface AddOptions {
|
|
|
14
13
|
export function runAdd(opts: AddOptions): void {
|
|
15
14
|
const cmd = opts.command.trim();
|
|
16
15
|
|
|
17
|
-
// Skip empty
|
|
16
|
+
// Skip empty or very short commands
|
|
18
17
|
if (!cmd || cmd.length < 2) return;
|
|
19
18
|
|
|
20
19
|
// Skip commands starting with space (convention)
|
|
@@ -23,10 +22,6 @@ export function runAdd(opts: AddOptions): void {
|
|
|
23
22
|
// Only save successful commands (exit code 0)
|
|
24
23
|
if (opts.exitCode !== undefined && opts.exitCode !== 0) return;
|
|
25
24
|
|
|
26
|
-
// Skip ignored commands (only the base command, not arguments)
|
|
27
|
-
const baseCmd = cmd.split(/\s+/)[0];
|
|
28
|
-
if (IGNORED_COMMANDS.has(baseCmd)) return;
|
|
29
|
-
|
|
30
25
|
insertCommand({
|
|
31
26
|
command: cmd,
|
|
32
27
|
cwd: opts.cwd,
|
package/src/cli/import.ts
CHANGED
|
@@ -1,34 +1,65 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "fs";
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { join } from "path";
|
|
4
|
-
import { insertCommand } from "../db/queries";
|
|
4
|
+
import { insertCommand, getExistingHashes, hashCommand } from "../db/queries";
|
|
5
5
|
import { getHostname } from "../utils/platform";
|
|
6
6
|
|
|
7
7
|
export function runImport(shell?: string): void {
|
|
8
8
|
const home = homedir();
|
|
9
|
+
const existing = getExistingHashes();
|
|
10
|
+
const seen = new Set<string>();
|
|
9
11
|
let imported = 0;
|
|
12
|
+
let skipped = 0;
|
|
10
13
|
|
|
11
14
|
if (!shell || shell === "zsh") {
|
|
12
15
|
const zshPath = join(home, ".zsh_history");
|
|
13
16
|
if (existsSync(zshPath)) {
|
|
14
|
-
|
|
17
|
+
const result = importZshHistory(zshPath, existing, seen);
|
|
18
|
+
imported += result.imported;
|
|
19
|
+
skipped += result.skipped;
|
|
15
20
|
}
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
if (!shell || shell === "bash") {
|
|
19
24
|
const bashPath = join(home, ".bash_history");
|
|
20
25
|
if (existsSync(bashPath)) {
|
|
21
|
-
|
|
26
|
+
const result = importBashHistory(bashPath, existing, seen);
|
|
27
|
+
imported += result.imported;
|
|
28
|
+
skipped += result.skipped;
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
31
|
|
|
25
|
-
console.log(`Imported ${imported} commands.`);
|
|
32
|
+
console.log(`Imported ${imported} commands. Skipped ${skipped} duplicates.`);
|
|
26
33
|
}
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
interface ImportResult {
|
|
36
|
+
imported: number;
|
|
37
|
+
skipped: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function tryInsert(
|
|
41
|
+
cmd: string,
|
|
42
|
+
shell: string,
|
|
43
|
+
hostname: string,
|
|
44
|
+
existing: Set<string>,
|
|
45
|
+
seen: Set<string>
|
|
46
|
+
): boolean {
|
|
47
|
+
const hash = hashCommand(cmd);
|
|
48
|
+
if (existing.has(hash) || seen.has(hash)) return false;
|
|
49
|
+
seen.add(hash);
|
|
50
|
+
insertCommand({ command: cmd, hostname, shell });
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function importZshHistory(
|
|
55
|
+
path: string,
|
|
56
|
+
existing: Set<string>,
|
|
57
|
+
seen: Set<string>
|
|
58
|
+
): ImportResult {
|
|
29
59
|
const content = readFileSync(path, "utf-8");
|
|
30
60
|
const lines = content.split("\n");
|
|
31
|
-
let
|
|
61
|
+
let imported = 0;
|
|
62
|
+
let skipped = 0;
|
|
32
63
|
const hostname = getHostname();
|
|
33
64
|
|
|
34
65
|
for (const line of lines) {
|
|
@@ -37,12 +68,11 @@ function importZshHistory(path: string): number {
|
|
|
37
68
|
if (extMatch) {
|
|
38
69
|
const cmd = extMatch[2].trim();
|
|
39
70
|
if (cmd && cmd.length >= 2) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
count++;
|
|
71
|
+
if (tryInsert(cmd, "zsh", hostname, existing, seen)) {
|
|
72
|
+
imported++;
|
|
73
|
+
} else {
|
|
74
|
+
skipped++;
|
|
75
|
+
}
|
|
46
76
|
}
|
|
47
77
|
continue;
|
|
48
78
|
}
|
|
@@ -50,27 +80,38 @@ function importZshHistory(path: string): number {
|
|
|
50
80
|
// Plain format
|
|
51
81
|
const cmd = line.trim();
|
|
52
82
|
if (cmd && cmd.length >= 2 && !cmd.startsWith("#")) {
|
|
53
|
-
|
|
54
|
-
|
|
83
|
+
if (tryInsert(cmd, "zsh", hostname, existing, seen)) {
|
|
84
|
+
imported++;
|
|
85
|
+
} else {
|
|
86
|
+
skipped++;
|
|
87
|
+
}
|
|
55
88
|
}
|
|
56
89
|
}
|
|
57
90
|
|
|
58
|
-
return
|
|
91
|
+
return { imported, skipped };
|
|
59
92
|
}
|
|
60
93
|
|
|
61
|
-
function importBashHistory(
|
|
94
|
+
function importBashHistory(
|
|
95
|
+
path: string,
|
|
96
|
+
existing: Set<string>,
|
|
97
|
+
seen: Set<string>
|
|
98
|
+
): ImportResult {
|
|
62
99
|
const content = readFileSync(path, "utf-8");
|
|
63
100
|
const lines = content.split("\n");
|
|
64
|
-
let
|
|
101
|
+
let imported = 0;
|
|
102
|
+
let skipped = 0;
|
|
65
103
|
const hostname = getHostname();
|
|
66
104
|
|
|
67
105
|
for (const line of lines) {
|
|
68
106
|
const cmd = line.trim();
|
|
69
107
|
if (cmd && cmd.length >= 2 && !cmd.startsWith("#")) {
|
|
70
|
-
|
|
71
|
-
|
|
108
|
+
if (tryInsert(cmd, "bash", hostname, existing, seen)) {
|
|
109
|
+
imported++;
|
|
110
|
+
} else {
|
|
111
|
+
skipped++;
|
|
112
|
+
}
|
|
72
113
|
}
|
|
73
114
|
}
|
|
74
115
|
|
|
75
|
-
return
|
|
116
|
+
return { imported, skipped };
|
|
76
117
|
}
|
package/src/daemon/server.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { getDb, closeDb } from "../db/connection";
|
|
|
2
2
|
import { insertCommand } from "../db/queries";
|
|
3
3
|
import { getHostname } from "../utils/platform";
|
|
4
4
|
import { getCommonSuggestions } from "../data/common-commands";
|
|
5
|
-
import { IGNORED_COMMANDS } from "../utils/constants";
|
|
6
5
|
import { parseRequest, getSocketPath, getPidPath, getDaemonPort } from "./protocol";
|
|
7
6
|
import { unlinkSync, writeFileSync, existsSync } from "fs";
|
|
8
7
|
import type { Socket } from "bun";
|
|
@@ -95,9 +94,6 @@ function handleRequest(raw: string): string {
|
|
|
95
94
|
const cmd = req.command.trim();
|
|
96
95
|
if (!cmd || cmd.length < 2 || cmd.startsWith(" ")) return "OK\n\n";
|
|
97
96
|
if (req.exitCode !== 0) return "OK\n\n"; // Only save successful commands
|
|
98
|
-
const baseCmd = cmd.split(/\s+/)[0];
|
|
99
|
-
if (IGNORED_COMMANDS.has(baseCmd)) return "OK\n\n";
|
|
100
|
-
|
|
101
97
|
insertCommand({
|
|
102
98
|
command: cmd,
|
|
103
99
|
cwd: req.cwd || undefined,
|
package/src/db/queries.ts
CHANGED
|
@@ -166,6 +166,16 @@ export function pruneOlderThan(days: number): number {
|
|
|
166
166
|
return result.changes;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
export function getExistingHashes(): Set<string> {
|
|
170
|
+
const db = getDb();
|
|
171
|
+
const rows = db
|
|
172
|
+
.query<{ command_hash: string }, []>(
|
|
173
|
+
"SELECT command_hash FROM command_stats"
|
|
174
|
+
)
|
|
175
|
+
.all();
|
|
176
|
+
return new Set(rows.map((r) => r.command_hash));
|
|
177
|
+
}
|
|
178
|
+
|
|
169
179
|
export function refreshAllFrecency(): void {
|
|
170
180
|
const db = getDb();
|
|
171
181
|
const now = Date.now();
|
package/src/utils/constants.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const IGNORED_COMMANDS = new Set(["ls", "cd", "pwd", "exit", "clear", "sw"]);
|