@fredlackey/devutils 0.0.19 → 0.1.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/README.md +223 -32
- package/package.json +7 -5
- package/src/api/loader.js +229 -0
- package/src/api/registry.json +62 -0
- package/src/cli.js +305 -0
- package/src/commands/ai/index.js +16 -0
- package/src/commands/ai/launch.js +112 -0
- package/src/commands/ai/list.js +54 -0
- package/src/commands/ai/resume.js +70 -0
- package/src/commands/ai/sessions.js +121 -0
- package/src/commands/ai/set.js +131 -0
- package/src/commands/ai/show.js +74 -0
- package/src/commands/ai/tools.js +46 -0
- package/src/commands/alias/add.js +93 -0
- package/src/commands/alias/helpers.js +107 -0
- package/src/commands/alias/index.js +14 -0
- package/src/commands/alias/list.js +55 -0
- package/src/commands/alias/remove.js +62 -0
- package/src/commands/alias/sync.js +109 -0
- package/src/commands/api/disable.js +73 -0
- package/src/commands/api/enable.js +148 -0
- package/src/commands/api/index.js +15 -0
- package/src/commands/api/list.js +66 -0
- package/src/commands/api/update.js +87 -0
- package/src/commands/auth/index.js +15 -0
- package/src/commands/auth/list.js +49 -0
- package/src/commands/auth/login.js +384 -0
- package/src/commands/auth/logout.js +111 -0
- package/src/commands/auth/refresh.js +184 -0
- package/src/commands/auth/services.js +169 -0
- package/src/commands/auth/status.js +104 -0
- package/src/commands/config/export.js +224 -0
- package/src/commands/config/get.js +52 -0
- package/src/commands/config/import.js +308 -0
- package/src/commands/config/index.js +17 -0
- package/src/commands/config/init.js +143 -0
- package/src/commands/config/reset.js +57 -0
- package/src/commands/config/set.js +93 -0
- package/src/commands/config/show.js +35 -0
- package/src/commands/help.js +338 -0
- package/src/commands/identity/add.js +133 -0
- package/src/commands/identity/index.js +17 -0
- package/src/commands/identity/link.js +76 -0
- package/src/commands/identity/list.js +48 -0
- package/src/commands/identity/remove.js +72 -0
- package/src/commands/identity/show.js +65 -0
- package/src/commands/identity/sync.js +172 -0
- package/src/commands/identity/unlink.js +57 -0
- package/src/commands/ignore/add.js +165 -0
- package/src/commands/ignore/index.js +14 -0
- package/src/commands/ignore/list.js +89 -0
- package/src/commands/ignore/markers.js +43 -0
- package/src/commands/ignore/remove.js +164 -0
- package/src/commands/ignore/show.js +169 -0
- package/src/commands/machine/detect.js +122 -0
- package/src/commands/machine/index.js +14 -0
- package/src/commands/machine/list.js +74 -0
- package/src/commands/machine/set.js +106 -0
- package/src/commands/machine/show.js +35 -0
- package/src/commands/schema.js +152 -0
- package/src/commands/search/collections.js +134 -0
- package/src/commands/search/get.js +71 -0
- package/src/commands/search/index-cmd.js +54 -0
- package/src/commands/search/index.js +21 -0
- package/src/commands/search/keyword.js +60 -0
- package/src/commands/search/qmd.js +70 -0
- package/src/commands/search/query.js +64 -0
- package/src/commands/search/semantic.js +62 -0
- package/src/commands/search/status.js +46 -0
- package/src/commands/status.js +276 -0
- package/src/commands/tools/check.js +79 -0
- package/src/commands/tools/index.js +14 -0
- package/src/commands/tools/install.js +110 -0
- package/src/commands/tools/list.js +91 -0
- package/src/commands/tools/search.js +60 -0
- package/src/commands/update.js +113 -0
- package/src/commands/util/add.js +151 -0
- package/src/commands/util/index.js +15 -0
- package/src/commands/util/list.js +97 -0
- package/src/commands/util/remove.js +76 -0
- package/src/commands/util/run.js +79 -0
- package/src/commands/util/show.js +67 -0
- package/src/commands/version.js +33 -0
- package/src/installers/_template.js +104 -0
- package/src/installers/git.js +150 -0
- package/src/installers/homebrew.js +190 -0
- package/src/installers/node.js +223 -0
- package/src/installers/registry.json +29 -0
- package/src/lib/config.js +125 -0
- package/src/lib/detect.js +74 -0
- package/src/lib/errors.js +114 -0
- package/src/lib/github.js +315 -0
- package/src/lib/installer.js +225 -0
- package/src/lib/output.js +239 -0
- package/src/lib/platform.js +112 -0
- package/src/lib/platforms/amazon-linux.js +41 -0
- package/src/lib/platforms/gitbash.js +46 -0
- package/src/lib/platforms/macos.js +45 -0
- package/src/lib/platforms/raspbian.js +41 -0
- package/src/lib/platforms/ubuntu.js +39 -0
- package/src/lib/platforms/windows.js +45 -0
- package/src/lib/prompt.js +161 -0
- package/src/lib/schema.js +211 -0
- package/src/lib/shell.js +75 -0
- package/src/patterns/gitignore/claude-code.txt +25 -0
- package/src/patterns/gitignore/docker.txt +15 -0
- package/src/patterns/gitignore/go.txt +24 -0
- package/src/patterns/gitignore/java.txt +38 -0
- package/src/patterns/gitignore/jetbrains.txt +26 -0
- package/src/patterns/gitignore/linux.txt +18 -0
- package/src/patterns/gitignore/macos.txt +27 -0
- package/src/patterns/gitignore/node.txt +51 -0
- package/src/patterns/gitignore/python.txt +55 -0
- package/src/patterns/gitignore/rust.txt +14 -0
- package/src/patterns/gitignore/terraform.txt +30 -0
- package/src/patterns/gitignore/vscode.txt +15 -0
- package/src/patterns/gitignore/windows.txt +25 -0
- package/src/utils/clone/index.js +165 -0
- package/src/utils/git-push/index.js +230 -0
- package/src/utils/git-status/index.js +116 -0
- package/src/utils/git-status/unix.sh +75 -0
- package/src/utils/registry.json +41 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
name: 'git-status',
|
|
8
|
+
description: 'Scan directories for git repos and show a color-coded status summary',
|
|
9
|
+
platforms: ['macos', 'ubuntu', 'raspbian', 'amazon-linux', 'windows', 'gitbash'],
|
|
10
|
+
arguments: [
|
|
11
|
+
{ name: 'path', required: false, description: 'Directory to scan (defaults to current directory)' },
|
|
12
|
+
],
|
|
13
|
+
flags: [
|
|
14
|
+
{ name: 'depth', type: 'number', description: 'How many levels deep to scan for repos (default: 1)' },
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Run the Unix bash script for git status scanning.
|
|
20
|
+
* @param {string} dir - The directory to scan.
|
|
21
|
+
*/
|
|
22
|
+
async function runUnixScript(dir) {
|
|
23
|
+
const shell = require('../../lib/shell');
|
|
24
|
+
const scriptPath = path.join(__dirname, 'unix.sh');
|
|
25
|
+
|
|
26
|
+
const result = await shell.exec(`bash "${scriptPath}" "${dir}"`);
|
|
27
|
+
|
|
28
|
+
if (result.exitCode !== 0) {
|
|
29
|
+
console.error(result.stderr || 'git-status script failed');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (result.stdout) {
|
|
34
|
+
console.log(result.stdout);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Pure JavaScript fallback for platforms without bash (Windows, Git Bash).
|
|
40
|
+
* @param {string} dir - The directory to scan.
|
|
41
|
+
*/
|
|
42
|
+
async function runJsFallback(dir) {
|
|
43
|
+
const shell = require('../../lib/shell');
|
|
44
|
+
|
|
45
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
46
|
+
const repos = entries
|
|
47
|
+
.filter(e => e.isDirectory() && fs.existsSync(path.join(dir, e.name, '.git')))
|
|
48
|
+
.map(e => ({ name: e.name, path: path.join(dir, e.name) }));
|
|
49
|
+
|
|
50
|
+
if (repos.length === 0) {
|
|
51
|
+
console.log('No git repositories found in ' + dir);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for (const repo of repos) {
|
|
56
|
+
const opts = { cwd: repo.path };
|
|
57
|
+
|
|
58
|
+
// Get branch
|
|
59
|
+
let branch = shell.execSync('git symbolic-ref --short HEAD', opts);
|
|
60
|
+
if (branch === null) branch = 'detached';
|
|
61
|
+
|
|
62
|
+
// Get dirty count
|
|
63
|
+
const porcelain = shell.execSync('git status --porcelain', opts) || '';
|
|
64
|
+
const dirtyCount = porcelain ? porcelain.split('\n').filter(Boolean).length : 0;
|
|
65
|
+
|
|
66
|
+
// Get stash count
|
|
67
|
+
const stashList = shell.execSync('git stash list', opts) || '';
|
|
68
|
+
const stashCount = stashList ? stashList.split('\n').filter(Boolean).length : 0;
|
|
69
|
+
|
|
70
|
+
// Get ahead/behind
|
|
71
|
+
let ahead = 0;
|
|
72
|
+
let behind = 0;
|
|
73
|
+
const tracking = shell.execSync('git rev-parse --abbrev-ref @{upstream}', opts);
|
|
74
|
+
if (tracking) {
|
|
75
|
+
const counts = shell.execSync('git rev-list --left-right --count HEAD...@{upstream}', opts);
|
|
76
|
+
if (counts) {
|
|
77
|
+
const parts = counts.split(/\s+/);
|
|
78
|
+
ahead = parseInt(parts[0], 10) || 0;
|
|
79
|
+
behind = parseInt(parts[1], 10) || 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Build status string
|
|
84
|
+
const statusParts = [];
|
|
85
|
+
if (dirtyCount > 0) statusParts.push(`${dirtyCount} dirty`);
|
|
86
|
+
if (ahead > 0) statusParts.push(`+${ahead}`);
|
|
87
|
+
if (behind > 0) statusParts.push(`-${behind}`);
|
|
88
|
+
if (stashCount > 0) statusParts.push(`${stashCount} stash`);
|
|
89
|
+
if (statusParts.length === 0) statusParts.push('clean');
|
|
90
|
+
|
|
91
|
+
const nameCol = repo.name.padEnd(30);
|
|
92
|
+
const branchCol = branch.padEnd(20);
|
|
93
|
+
console.log(`${nameCol} ${branchCol} ${statusParts.join(' ')}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function run(args) {
|
|
98
|
+
const platform = require('../../lib/platform').detect();
|
|
99
|
+
const targetDir = args[0] || process.cwd();
|
|
100
|
+
const resolvedDir = path.resolve(targetDir);
|
|
101
|
+
|
|
102
|
+
if (!fs.existsSync(resolvedDir)) {
|
|
103
|
+
console.error(`Directory not found: ${resolvedDir}`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const unixPlatforms = ['macos', 'ubuntu', 'raspbian', 'amazon-linux'];
|
|
108
|
+
|
|
109
|
+
if (unixPlatforms.includes(platform.type)) {
|
|
110
|
+
await runUnixScript(resolvedDir);
|
|
111
|
+
} else {
|
|
112
|
+
await runJsFallback(resolvedDir);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# git-status: Scan directory for git repos and show status summary
|
|
3
|
+
|
|
4
|
+
TARGET_DIR="${1:-.}"
|
|
5
|
+
|
|
6
|
+
# Colors
|
|
7
|
+
RED='\033[0;31m'
|
|
8
|
+
GREEN='\033[0;32m'
|
|
9
|
+
YELLOW='\033[0;33m'
|
|
10
|
+
CYAN='\033[0;36m'
|
|
11
|
+
NC='\033[0m' # No Color
|
|
12
|
+
BOLD='\033[1m'
|
|
13
|
+
|
|
14
|
+
# Find git repos (immediate subdirectories with .git folders)
|
|
15
|
+
for dir in "$TARGET_DIR"/*/; do
|
|
16
|
+
if [ ! -d "$dir/.git" ]; then
|
|
17
|
+
continue
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
repo_name=$(basename "$dir")
|
|
21
|
+
|
|
22
|
+
# Get branch name
|
|
23
|
+
branch=$(git -C "$dir" symbolic-ref --short HEAD 2>/dev/null)
|
|
24
|
+
if [ -z "$branch" ]; then
|
|
25
|
+
branch="detached"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Get dirty file count
|
|
29
|
+
dirty_count=$(git -C "$dir" status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
30
|
+
|
|
31
|
+
# Get stash count
|
|
32
|
+
stash_count=$(git -C "$dir" stash list 2>/dev/null | wc -l | tr -d ' ')
|
|
33
|
+
|
|
34
|
+
# Get ahead/behind counts
|
|
35
|
+
ahead=0
|
|
36
|
+
behind=0
|
|
37
|
+
tracking=$(git -C "$dir" rev-parse --abbrev-ref '@{upstream}' 2>/dev/null)
|
|
38
|
+
if [ -n "$tracking" ]; then
|
|
39
|
+
counts=$(git -C "$dir" rev-list --left-right --count HEAD...'@{upstream}' 2>/dev/null)
|
|
40
|
+
if [ -n "$counts" ]; then
|
|
41
|
+
ahead=$(echo "$counts" | awk '{print $1}')
|
|
42
|
+
behind=$(echo "$counts" | awk '{print $2}')
|
|
43
|
+
fi
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Determine color based on status
|
|
47
|
+
color="$GREEN"
|
|
48
|
+
if [ "$dirty_count" -gt 0 ]; then
|
|
49
|
+
color="$YELLOW"
|
|
50
|
+
fi
|
|
51
|
+
if [ "$behind" -gt 0 ]; then
|
|
52
|
+
color="$RED"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Build status string
|
|
56
|
+
status_parts=""
|
|
57
|
+
if [ "$dirty_count" -gt 0 ]; then
|
|
58
|
+
status_parts="${status_parts} ${YELLOW}${dirty_count} dirty${NC}"
|
|
59
|
+
fi
|
|
60
|
+
if [ "$ahead" -gt 0 ]; then
|
|
61
|
+
status_parts="${status_parts} ${GREEN}+${ahead}${NC}"
|
|
62
|
+
fi
|
|
63
|
+
if [ "$behind" -gt 0 ]; then
|
|
64
|
+
status_parts="${status_parts} ${RED}-${behind}${NC}"
|
|
65
|
+
fi
|
|
66
|
+
if [ "$stash_count" -gt 0 ]; then
|
|
67
|
+
status_parts="${status_parts} ${CYAN}${stash_count} stash${NC}"
|
|
68
|
+
fi
|
|
69
|
+
if [ -z "$status_parts" ]; then
|
|
70
|
+
status_parts=" ${GREEN}clean${NC}"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# Print the line
|
|
74
|
+
printf "${color}${BOLD}%-30s${NC} ${CYAN}%-20s${NC}%s\n" "$repo_name" "$branch" "$status_parts"
|
|
75
|
+
done
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Built-in utility metadata. Name, description, supported platforms, and arguments for each utility.",
|
|
3
|
+
"utilities": [
|
|
4
|
+
{
|
|
5
|
+
"name": "git-status",
|
|
6
|
+
"description": "Scan directories for git repos and show a color-coded status summary",
|
|
7
|
+
"type": "built-in",
|
|
8
|
+
"platforms": ["macos", "ubuntu", "raspbian", "amazon-linux", "windows", "gitbash"],
|
|
9
|
+
"arguments": [
|
|
10
|
+
{ "name": "path", "required": false, "description": "Directory to scan (defaults to current directory)" }
|
|
11
|
+
],
|
|
12
|
+
"flags": [
|
|
13
|
+
{ "name": "depth", "type": "number", "description": "How many levels deep to scan for repos (default: 1)" }
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "clone",
|
|
18
|
+
"description": "Clone a git repo and auto-install dependencies using the detected package manager",
|
|
19
|
+
"type": "built-in",
|
|
20
|
+
"platforms": ["macos", "ubuntu", "raspbian", "amazon-linux", "windows", "gitbash"],
|
|
21
|
+
"arguments": [
|
|
22
|
+
{ "name": "url", "required": true, "description": "Git repository URL (SSH or HTTPS)" },
|
|
23
|
+
{ "name": "directory", "required": false, "description": "Target directory name (defaults to repo name)" }
|
|
24
|
+
],
|
|
25
|
+
"flags": []
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "git-push",
|
|
29
|
+
"description": "Safer git push: shows what will be pushed, confirms before pushing, and protects main/master",
|
|
30
|
+
"type": "built-in",
|
|
31
|
+
"platforms": ["macos", "ubuntu", "raspbian", "amazon-linux", "windows", "gitbash"],
|
|
32
|
+
"arguments": [
|
|
33
|
+
{ "name": "message", "required": true, "description": "Commit message" }
|
|
34
|
+
],
|
|
35
|
+
"flags": [
|
|
36
|
+
{ "name": "force", "type": "boolean", "description": "Allow pushing to protected branches" },
|
|
37
|
+
{ "name": "yes", "type": "boolean", "description": "Skip confirmation prompt" }
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|