greptile 2.4.0 → 3.0.1
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 +108 -0
- package/dist/greptile.js +467 -0
- package/package.json +51 -20
- package/bin/greptile-fix.js +0 -10
- package/build-app.sh +0 -81
- package/com.greptile.health.plist +0 -23
- package/greptile-fix +0 -243
- package/greptile-fix.applescript +0 -78
- package/health-server.js +0 -264
- package/postinstall.sh +0 -77
- package/preuninstall.sh +0 -23
package/package.json
CHANGED
|
@@ -1,37 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "greptile",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Greptile code review from your terminal",
|
|
5
6
|
"bin": {
|
|
6
|
-
"greptile
|
|
7
|
+
"greptile": "dist/greptile.js"
|
|
7
8
|
},
|
|
8
9
|
"scripts": {
|
|
9
|
-
"
|
|
10
|
-
"
|
|
10
|
+
"test": "bun test",
|
|
11
|
+
"build": "bun scripts/bundle.ts",
|
|
12
|
+
"dev": "bun run src/main.ts",
|
|
13
|
+
"lint": "oxlint --type-aware src --ignore-pattern '**/__tests__/**' --ignore-pattern '**/*.test.ts' --ignore-pattern '**/*.test.tsx'",
|
|
14
|
+
"format": "oxfmt src package.json tsconfig.json",
|
|
15
|
+
"prepack": "bun scripts/bundle.ts",
|
|
16
|
+
"prepublishOnly": "bun run typecheck && bun scripts/bundle.ts",
|
|
17
|
+
"typecheck": "tsc --noEmit"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@clack/prompts": "^1.4.0",
|
|
21
|
+
"@inkjs/ui": "^2.0.0",
|
|
22
|
+
"@pierre/theme": "^1.0.3",
|
|
23
|
+
"@types/bun": "^1.3.11",
|
|
24
|
+
"@types/react": "^19.2.14",
|
|
25
|
+
"citty": "^0.2.2",
|
|
26
|
+
"cli-truncate": "^6.0.0",
|
|
27
|
+
"ink": "^7.0.3",
|
|
28
|
+
"picocolors": "^1.1.1",
|
|
29
|
+
"react": "^19.2.6",
|
|
30
|
+
"shiki": "^4.1.0",
|
|
31
|
+
"string-width": "^8.2.1",
|
|
32
|
+
"strip-ansi": "^7.2.0",
|
|
33
|
+
"terminal-link": "^5.0.0",
|
|
34
|
+
"typescript": "^6.0.3",
|
|
35
|
+
"wrap-ansi": "^9.0.2",
|
|
36
|
+
"zod": "^3.25.76"
|
|
11
37
|
},
|
|
12
38
|
"files": [
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"greptile-fix.applescript",
|
|
16
|
-
"build-app.sh",
|
|
17
|
-
"postinstall.sh",
|
|
18
|
-
"preuninstall.sh",
|
|
19
|
-
"health-server.js",
|
|
20
|
-
"com.greptile.health.plist"
|
|
39
|
+
"dist/",
|
|
40
|
+
"README.md"
|
|
21
41
|
],
|
|
22
42
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
43
|
+
"node": ">=22.0.0"
|
|
24
44
|
},
|
|
25
|
-
"os": [
|
|
26
|
-
"darwin"
|
|
27
|
-
],
|
|
28
45
|
"keywords": [
|
|
29
46
|
"greptile",
|
|
30
47
|
"code-review",
|
|
48
|
+
"cli",
|
|
31
49
|
"claude-code",
|
|
32
|
-
"codex"
|
|
33
|
-
"ide"
|
|
50
|
+
"codex"
|
|
34
51
|
],
|
|
35
52
|
"license": "MIT",
|
|
36
|
-
"homepage": "https://greptile.com"
|
|
53
|
+
"homepage": "https://greptile.com",
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/greptileai/cli.git"
|
|
57
|
+
},
|
|
58
|
+
"bugs": {
|
|
59
|
+
"url": "https://github.com/greptileai/cli/issues"
|
|
60
|
+
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
},
|
|
64
|
+
"overrides": {
|
|
65
|
+
"react": "^19.2.6",
|
|
66
|
+
"react-dom": "^19.2.6"
|
|
67
|
+
}
|
|
37
68
|
}
|
package/bin/greptile-fix.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const { execFileSync } = require('child_process')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
|
|
5
|
-
const script = path.join(__dirname, '..', 'greptile-fix')
|
|
6
|
-
try {
|
|
7
|
-
execFileSync(script, process.argv.slice(2), { stdio: 'inherit' })
|
|
8
|
-
} catch (e) {
|
|
9
|
-
process.exit(e.status || 1)
|
|
10
|
-
}
|
package/build-app.sh
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# build-app.sh — Builds the Greptile Fix .app bundle from AppleScript.
|
|
4
|
-
#
|
|
5
|
-
# This compiles greptile-fix.applescript into a macOS .app bundle,
|
|
6
|
-
# adds the greptile:// URL scheme to its Info.plist, and registers it
|
|
7
|
-
# with Launch Services so macOS knows to open it for greptile:// URLs.
|
|
8
|
-
#
|
|
9
|
-
# Usage: ./build-app.sh [output_dir]
|
|
10
|
-
# output_dir defaults to the current directory
|
|
11
|
-
|
|
12
|
-
set -euo pipefail
|
|
13
|
-
|
|
14
|
-
# Only run on macOS
|
|
15
|
-
if [ "$(uname)" != "Darwin" ]; then
|
|
16
|
-
echo "build-app.sh: Skipping (macOS only)"
|
|
17
|
-
exit 0
|
|
18
|
-
fi
|
|
19
|
-
|
|
20
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
21
|
-
OUTPUT_DIR="${1:-$SCRIPT_DIR}"
|
|
22
|
-
APP_NAME="Greptile Fix"
|
|
23
|
-
APP_PATH="$OUTPUT_DIR/$APP_NAME.app"
|
|
24
|
-
|
|
25
|
-
echo "Building $APP_NAME.app..."
|
|
26
|
-
|
|
27
|
-
# Resolve the absolute path to greptile-fix at install time so the .app
|
|
28
|
-
# works even when launched by macOS with a minimal PATH (e.g. nvm/fnm/volta users).
|
|
29
|
-
GREPTILE_FIX_BIN="$(command -v greptile-fix 2>/dev/null || echo "")"
|
|
30
|
-
if [ -z "$GREPTILE_FIX_BIN" ]; then
|
|
31
|
-
# Fallback: it should be next to this script in bin/
|
|
32
|
-
GREPTILE_FIX_BIN="$SCRIPT_DIR/bin/greptile-fix.js"
|
|
33
|
-
fi
|
|
34
|
-
GREPTILE_FIX_DIR="$(dirname "$GREPTILE_FIX_BIN")"
|
|
35
|
-
echo "Resolved greptile-fix: $GREPTILE_FIX_BIN"
|
|
36
|
-
|
|
37
|
-
# 1. Compile AppleScript into .app bundle — inject the resolved bin directory
|
|
38
|
-
# into the PATH so it works regardless of node version manager.
|
|
39
|
-
if [ -d "$APP_PATH" ]; then
|
|
40
|
-
rm -rf "$APP_PATH"
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
TEMP_SCRIPT="$(mktemp /tmp/greptile-fix-XXXXXX.applescript)"
|
|
44
|
-
# Clean up temp file on exit (success or failure)
|
|
45
|
-
trap 'rm -f "$TEMP_SCRIPT"' EXIT
|
|
46
|
-
|
|
47
|
-
# Escape sed special characters in the directory path (& \ /)
|
|
48
|
-
ESCAPED_DIR="$(printf '%s' "$GREPTILE_FIX_DIR" | sed 's/[&\\/]/\\&/g')"
|
|
49
|
-
sed "s|PATH=/opt/homebrew/bin:/usr/local/bin:|PATH=$ESCAPED_DIR:/opt/homebrew/bin:/usr/local/bin:|" \
|
|
50
|
-
"$SCRIPT_DIR/greptile-fix.applescript" > "$TEMP_SCRIPT"
|
|
51
|
-
|
|
52
|
-
osacompile -o "$APP_PATH" "$TEMP_SCRIPT"
|
|
53
|
-
|
|
54
|
-
if [ ! -d "$APP_PATH" ]; then
|
|
55
|
-
echo "Error: osacompile failed to create $APP_PATH"
|
|
56
|
-
exit 1
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
# 2. Add URL scheme to Info.plist
|
|
60
|
-
PLIST="$APP_PATH/Contents/Info.plist"
|
|
61
|
-
|
|
62
|
-
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes array" "$PLIST"
|
|
63
|
-
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0 dict" "$PLIST"
|
|
64
|
-
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLName string com.greptile.fix" "$PLIST"
|
|
65
|
-
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLSchemes array" "$PLIST"
|
|
66
|
-
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLSchemes:0 string greptile" "$PLIST"
|
|
67
|
-
|
|
68
|
-
# Set a bundle identifier
|
|
69
|
-
/usr/libexec/PlistBuddy -c "Add :CFBundleIdentifier string com.greptile.fix" "$PLIST" 2>/dev/null || \
|
|
70
|
-
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.greptile.fix" "$PLIST"
|
|
71
|
-
|
|
72
|
-
echo "URL scheme added to Info.plist"
|
|
73
|
-
|
|
74
|
-
# 3. Register with Launch Services
|
|
75
|
-
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -R "$APP_PATH"
|
|
76
|
-
|
|
77
|
-
echo "Registered with Launch Services"
|
|
78
|
-
echo ""
|
|
79
|
-
echo "Built: $APP_PATH"
|
|
80
|
-
echo ""
|
|
81
|
-
echo "To test: open 'greptile://claude-code?prompt=hello&repo=test/repo'"
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
-
<plist version="1.0">
|
|
4
|
-
<dict>
|
|
5
|
-
<key>Label</key>
|
|
6
|
-
<string>com.greptile.health</string>
|
|
7
|
-
<key>ProgramArguments</key>
|
|
8
|
-
<array>
|
|
9
|
-
<string>/usr/local/bin/node</string>
|
|
10
|
-
<string>health-server.js</string>
|
|
11
|
-
</array>
|
|
12
|
-
<key>WorkingDirectory</key>
|
|
13
|
-
<string>__PACKAGE_DIR__</string>
|
|
14
|
-
<key>RunAtLoad</key>
|
|
15
|
-
<true/>
|
|
16
|
-
<key>KeepAlive</key>
|
|
17
|
-
<true/>
|
|
18
|
-
<key>StandardOutPath</key>
|
|
19
|
-
<string>__HOME__/.cache/greptile/greptile-health.log</string>
|
|
20
|
-
<key>StandardErrorPath</key>
|
|
21
|
-
<string>__HOME__/.cache/greptile/greptile-health.log</string>
|
|
22
|
-
</dict>
|
|
23
|
-
</plist>
|
package/greptile-fix
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# greptile-fix — Bridge script for "Fix in <IDE>" links.
|
|
4
|
-
#
|
|
5
|
-
# Receives greptile://<ide>?prompt=...&repo=... URLs from the macOS URL scheme handler,
|
|
6
|
-
# looks up the local repo path, and opens the appropriate CLI in Terminal with the prompt.
|
|
7
|
-
#
|
|
8
|
-
# Supported URL paths:
|
|
9
|
-
# greptile://claude-code?prompt=... → opens `claude` CLI
|
|
10
|
-
# greptile://codex?prompt=... → opens `codex` CLI
|
|
11
|
-
# greptile://fix?prompt=... → opens `claude` CLI (legacy)
|
|
12
|
-
#
|
|
13
|
-
# Repo path mappings are stored in ~/.greptile/repos.json.
|
|
14
|
-
# On first use for a repo, a Finder dialog asks the user to select the local folder.
|
|
15
|
-
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
|
|
18
|
-
# Verify python3 is available (used for URL decoding and JSON operations)
|
|
19
|
-
if ! command -v python3 &>/dev/null; then
|
|
20
|
-
echo "Error: python3 is required but not found in PATH." >&2
|
|
21
|
-
osascript -e 'display dialog "Greptile Fix requires Python 3, which was not found on this system.\n\nPlease install it via: xcode-select --install" buttons {"OK"} default button "OK" with icon caution' 2>/dev/null || true
|
|
22
|
-
exit 1
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
CONFIG_DIR="$HOME/.greptile"
|
|
26
|
-
REPOS_FILE="$CONFIG_DIR/repos.json"
|
|
27
|
-
CACHE_DIR="$HOME/.cache/greptile"
|
|
28
|
-
LOG_FILE="$CACHE_DIR/greptile-fix.log"
|
|
29
|
-
|
|
30
|
-
log() {
|
|
31
|
-
# Rotate log if it exceeds 1MB
|
|
32
|
-
if [ -f "$LOG_FILE" ] && [ "$(wc -c < "$LOG_FILE" 2>/dev/null || echo 0)" -gt 1048576 ]; then
|
|
33
|
-
mv -f "$LOG_FILE" "$LOG_FILE.old" 2>/dev/null || true
|
|
34
|
-
fi
|
|
35
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
# URL-decode a string (percent-decode)
|
|
39
|
-
urldecode() {
|
|
40
|
-
local encoded="$1"
|
|
41
|
-
# Use Python for reliable percent-decoding
|
|
42
|
-
python3 -c "import urllib.parse, sys; print(urllib.parse.unquote(sys.argv[1]))" "$encoded"
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
# Parse query parameters from a URL
|
|
46
|
-
parse_url_param() {
|
|
47
|
-
local url="$1"
|
|
48
|
-
local param_name="$2"
|
|
49
|
-
|
|
50
|
-
# Extract everything after '?'
|
|
51
|
-
local query_string="${url#*\?}"
|
|
52
|
-
if [ "$query_string" = "$url" ]; then
|
|
53
|
-
# No query string
|
|
54
|
-
return
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
# Split by '&' and find the parameter
|
|
58
|
-
local IFS='&'
|
|
59
|
-
for pair in $query_string; do
|
|
60
|
-
local key="${pair%%=*}"
|
|
61
|
-
local value="${pair#*=}"
|
|
62
|
-
if [ "$key" = "$param_name" ]; then
|
|
63
|
-
urldecode "$value"
|
|
64
|
-
return
|
|
65
|
-
fi
|
|
66
|
-
done
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
# Ensure config and cache directories exist
|
|
70
|
-
ensure_config_dir() {
|
|
71
|
-
if [ ! -d "$CONFIG_DIR" ]; then
|
|
72
|
-
mkdir -p "$CONFIG_DIR"
|
|
73
|
-
fi
|
|
74
|
-
if [ ! -d "$CACHE_DIR" ]; then
|
|
75
|
-
mkdir -p "$CACHE_DIR"
|
|
76
|
-
chmod 700 "$CACHE_DIR"
|
|
77
|
-
fi
|
|
78
|
-
if [ ! -f "$REPOS_FILE" ]; then
|
|
79
|
-
echo '{}' > "$REPOS_FILE"
|
|
80
|
-
fi
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
# Look up local path for a repo from repos.json
|
|
84
|
-
lookup_repo_path() {
|
|
85
|
-
local repo="$1"
|
|
86
|
-
python3 -c "
|
|
87
|
-
import json, sys, os
|
|
88
|
-
repos_file = os.path.expanduser(sys.argv[2])
|
|
89
|
-
try:
|
|
90
|
-
with open(repos_file) as f:
|
|
91
|
-
data = json.load(f)
|
|
92
|
-
path = data.get(sys.argv[1], '')
|
|
93
|
-
if path:
|
|
94
|
-
print(path)
|
|
95
|
-
except:
|
|
96
|
-
pass
|
|
97
|
-
" "$repo" "$REPOS_FILE"
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
# Save a repo path mapping
|
|
101
|
-
save_repo_path() {
|
|
102
|
-
local repo="$1"
|
|
103
|
-
local path="$2"
|
|
104
|
-
python3 -c "
|
|
105
|
-
import json, sys, os
|
|
106
|
-
repos_file = os.path.expanduser(sys.argv[3])
|
|
107
|
-
try:
|
|
108
|
-
with open(repos_file) as f:
|
|
109
|
-
data = json.load(f)
|
|
110
|
-
except:
|
|
111
|
-
data = {}
|
|
112
|
-
data[sys.argv[1]] = sys.argv[2]
|
|
113
|
-
with open(repos_file, 'w') as f:
|
|
114
|
-
json.dump(data, f, indent=2)
|
|
115
|
-
" "$repo" "$path" "$REPOS_FILE"
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
# Ask user to select a folder via macOS Finder dialog
|
|
119
|
-
ask_for_repo_folder() {
|
|
120
|
-
local repo="$1"
|
|
121
|
-
# Pass repo name safely via environment variable to avoid AppleScript injection
|
|
122
|
-
GREPTILE_REPO_NAME="$repo" osascript -e '
|
|
123
|
-
set repoName to system attribute "GREPTILE_REPO_NAME"
|
|
124
|
-
set chosenFolder to choose folder with prompt ("Select the local folder for " & repoName) default location (path to home folder)
|
|
125
|
-
return POSIX path of chosenFolder
|
|
126
|
-
' 2>/dev/null
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
# Create a self-contained runner script that opens the CLI with the prompt.
|
|
130
|
-
# Prints the runner path to stdout so the caller (AppleScript) can execute it in Terminal.
|
|
131
|
-
create_runner_script() {
|
|
132
|
-
local repo_path="$1"
|
|
133
|
-
local prompt="$2"
|
|
134
|
-
local cli_cmd="$3"
|
|
135
|
-
|
|
136
|
-
# Write args to a temp file — avoids all shell quoting issues.
|
|
137
|
-
# Line 1: repo path, Line 2+: prompt (may be multiline)
|
|
138
|
-
local argsfile
|
|
139
|
-
argsfile=$(mktemp "$CACHE_DIR/greptile-fix-args-XXXXXX")
|
|
140
|
-
printf '%s\n' "$repo_path" > "$argsfile"
|
|
141
|
-
printf '%s' "$prompt" >> "$argsfile"
|
|
142
|
-
|
|
143
|
-
# Write a runner script that reads args from the file, then cleans up
|
|
144
|
-
local runner
|
|
145
|
-
runner=$(mktemp "$CACHE_DIR/greptile-fix-run-XXXXXX")
|
|
146
|
-
chmod +x "$runner"
|
|
147
|
-
|
|
148
|
-
# Note: $argsfile and $cli_cmd are safe to interpolate (mktemp path and validated CLI name)
|
|
149
|
-
cat > "$runner" <<RUNNER_EOF
|
|
150
|
-
#!/bin/bash
|
|
151
|
-
ARGSFILE="$argsfile"
|
|
152
|
-
REPO_PATH=\$(head -1 "\$ARGSFILE")
|
|
153
|
-
PROMPT=\$(tail -n +2 "\$ARGSFILE")
|
|
154
|
-
rm -f "\$ARGSFILE"
|
|
155
|
-
cd "\$REPO_PATH" || exit 1
|
|
156
|
-
$cli_cmd "\$PROMPT"
|
|
157
|
-
rm -f "\$0"
|
|
158
|
-
RUNNER_EOF
|
|
159
|
-
|
|
160
|
-
# Print the runner path — the AppleScript app will use this to open Terminal
|
|
161
|
-
echo "$runner"
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
# --- Main ---
|
|
165
|
-
|
|
166
|
-
log "greptile-fix invoked with: $*"
|
|
167
|
-
|
|
168
|
-
if [ $# -lt 1 ]; then
|
|
169
|
-
log "ERROR: No URL argument provided"
|
|
170
|
-
echo "Usage: greptile-fix 'greptile://claude-code?prompt=...&repo=...'" >&2
|
|
171
|
-
exit 1
|
|
172
|
-
fi
|
|
173
|
-
|
|
174
|
-
URL="$1"
|
|
175
|
-
|
|
176
|
-
# Determine IDE from URL path (greptile://<path>?...)
|
|
177
|
-
# Extract the path segment between :// and ?
|
|
178
|
-
URL_PATH="${URL#*://}" # remove scheme prefix
|
|
179
|
-
URL_PATH="${URL_PATH%%\?*}" # remove query string
|
|
180
|
-
|
|
181
|
-
case "$URL_PATH" in
|
|
182
|
-
codex) IDE="codex" ;;
|
|
183
|
-
claude-code) IDE="claude" ;;
|
|
184
|
-
*) IDE="claude" ;; # legacy "fix" path and fallback
|
|
185
|
-
esac
|
|
186
|
-
|
|
187
|
-
# Parse URL parameters
|
|
188
|
-
PROMPT=$(parse_url_param "$URL" "prompt")
|
|
189
|
-
REPO=$(parse_url_param "$URL" "repo")
|
|
190
|
-
ACK_ID=$(parse_url_param "$URL" "ack")
|
|
191
|
-
|
|
192
|
-
if [ -z "$PROMPT" ]; then
|
|
193
|
-
log "ERROR: No prompt parameter in URL"
|
|
194
|
-
osascript -e 'display dialog "Greptile Fix: No prompt found in the URL." buttons {"OK"} default button "OK" with icon caution'
|
|
195
|
-
exit 1
|
|
196
|
-
fi
|
|
197
|
-
|
|
198
|
-
log "Prompt: ${PROMPT:0:100}..."
|
|
199
|
-
log "Repo: $REPO"
|
|
200
|
-
|
|
201
|
-
ensure_config_dir
|
|
202
|
-
|
|
203
|
-
# Determine local repo path
|
|
204
|
-
REPO_PATH=""
|
|
205
|
-
if [ -n "$REPO" ]; then
|
|
206
|
-
REPO_PATH=$(lookup_repo_path "$REPO")
|
|
207
|
-
|
|
208
|
-
if [ -z "$REPO_PATH" ] || [ ! -d "$REPO_PATH" ]; then
|
|
209
|
-
log "Repo path not found or invalid for $REPO, asking user..."
|
|
210
|
-
REPO_PATH=$(ask_for_repo_folder "$REPO")
|
|
211
|
-
|
|
212
|
-
if [ -z "$REPO_PATH" ]; then
|
|
213
|
-
log "User cancelled folder selection"
|
|
214
|
-
exit 0
|
|
215
|
-
fi
|
|
216
|
-
|
|
217
|
-
# Remove trailing slash if present
|
|
218
|
-
REPO_PATH="${REPO_PATH%/}"
|
|
219
|
-
|
|
220
|
-
save_repo_path "$REPO" "$REPO_PATH"
|
|
221
|
-
log "Saved repo path: $REPO -> $REPO_PATH"
|
|
222
|
-
fi
|
|
223
|
-
fi
|
|
224
|
-
|
|
225
|
-
# Fallback: if no repo was specified, use current directory
|
|
226
|
-
if [ -z "$REPO_PATH" ]; then
|
|
227
|
-
REPO_PATH="$HOME"
|
|
228
|
-
log "No repo specified, using home directory"
|
|
229
|
-
fi
|
|
230
|
-
|
|
231
|
-
log "Creating runner script for: $REPO_PATH (IDE: $IDE)"
|
|
232
|
-
RUNNER=$(create_runner_script "$REPO_PATH" "$PROMPT" "$IDE")
|
|
233
|
-
log "Runner script: $RUNNER"
|
|
234
|
-
|
|
235
|
-
# Print the runner path to stdout — the AppleScript app reads this
|
|
236
|
-
# and uses it to open Terminal (which requires Automation permission
|
|
237
|
-
# that only the .app bundle has).
|
|
238
|
-
# Line 1: runner path, Line 2 (optional): ACK ID for auto-redirect
|
|
239
|
-
echo "$RUNNER"
|
|
240
|
-
if [ -n "$ACK_ID" ]; then
|
|
241
|
-
echo "$ACK_ID"
|
|
242
|
-
fi
|
|
243
|
-
log "Done"
|
package/greptile-fix.applescript
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
-- greptile-fix.applescript
|
|
2
|
-
-- URL scheme handler for greptile:// protocol.
|
|
3
|
-
-- Compiled into a .app bundle that registers the URL scheme with macOS.
|
|
4
|
-
--
|
|
5
|
-
-- Flow:
|
|
6
|
-
-- 1. macOS sends us the greptile:// URL
|
|
7
|
-
-- 2. We call greptile-fix CLI to parse the URL, resolve the repo path, and create a runner script
|
|
8
|
-
-- 3. greptile-fix prints the runner script path to stdout
|
|
9
|
-
-- 4. We detect the user's terminal and execute the runner script in it
|
|
10
|
-
|
|
11
|
-
on open location theURL
|
|
12
|
-
try
|
|
13
|
-
-- Ensure log directory exists
|
|
14
|
-
do shell script "mkdir -p $HOME/.cache/greptile"
|
|
15
|
-
-- Call greptile-fix to parse URL and create runner script
|
|
16
|
-
-- Output: line 1 = runner path, line 2 (optional) = ACK ID for auto-redirect
|
|
17
|
-
set fixOutput to do shell script "PATH=/opt/homebrew/bin:/usr/local/bin:$PATH greptile-fix " & quoted form of theURL & " 2>> $HOME/.cache/greptile/greptile-fix.log"
|
|
18
|
-
|
|
19
|
-
set outputLines to paragraphs of fixOutput
|
|
20
|
-
set runnerPath to item 1 of outputLines
|
|
21
|
-
set ackId to ""
|
|
22
|
-
if (count of outputLines) > 1 then
|
|
23
|
-
set ackId to item 2 of outputLines
|
|
24
|
-
end if
|
|
25
|
-
|
|
26
|
-
if runnerPath is not "" then
|
|
27
|
-
-- Detect terminal by checking running processes via shell (no accessibility permissions needed).
|
|
28
|
-
-- Check non-default terminals first; fall back to Terminal.app.
|
|
29
|
-
set termApp to "Terminal"
|
|
30
|
-
try
|
|
31
|
-
set ps to do shell script "ps -eo comm= 2>/dev/null"
|
|
32
|
-
if ps contains "/Ghostty.app/" then
|
|
33
|
-
set termApp to "Ghostty"
|
|
34
|
-
else if ps contains "/iTerm.app/" then
|
|
35
|
-
set termApp to "iTerm"
|
|
36
|
-
else if ps contains "/Warp.app/" then
|
|
37
|
-
set termApp to "Warp"
|
|
38
|
-
else if ps contains "/kitty.app/" then
|
|
39
|
-
set termApp to "kitty"
|
|
40
|
-
else if ps contains "/WezTerm.app/" then
|
|
41
|
-
set termApp to "WezTerm"
|
|
42
|
-
else if ps contains "/Alacritty.app/" then
|
|
43
|
-
set termApp to "Alacritty"
|
|
44
|
-
end if
|
|
45
|
-
end try
|
|
46
|
-
|
|
47
|
-
do shell script "echo 'Detected terminal: " & termApp & "' >> $HOME/.cache/greptile/greptile-fix.log"
|
|
48
|
-
|
|
49
|
-
-- Terminal-specific launch commands for macOS.
|
|
50
|
-
-- Ghostty/kitty/WezTerm/Alacritty close the window when the -e command exits,
|
|
51
|
-
-- so we launch bash and source the runner script to keep the shell session alive
|
|
52
|
-
-- after the IDE command (claude/codex/cursor) finishes.
|
|
53
|
-
-- Unset CLAUDECODE so the new session doesn't think it's nested inside an existing one.
|
|
54
|
-
set cleanEnv to "unset CLAUDECODE; source " & quoted form of runnerPath & " ; exec zsh"
|
|
55
|
-
if termApp is "Ghostty" then
|
|
56
|
-
do shell script "open -na Ghostty --args -e zsh -li -c " & quoted form of cleanEnv & " &>/dev/null &"
|
|
57
|
-
else if termApp is "kitty" then
|
|
58
|
-
do shell script "open -na kitty --args zsh -li -c " & quoted form of cleanEnv & " &>/dev/null &"
|
|
59
|
-
else if termApp is "WezTerm" then
|
|
60
|
-
do shell script "open -na WezTerm --args start -- zsh -li -c " & quoted form of cleanEnv & " &>/dev/null &"
|
|
61
|
-
else if termApp is "Alacritty" then
|
|
62
|
-
do shell script "open -na Alacritty --args -e zsh -li -c " & quoted form of cleanEnv & " &>/dev/null &"
|
|
63
|
-
else
|
|
64
|
-
-- Terminal.app, iTerm, and Warp natively execute scripts via "open -a"
|
|
65
|
-
do shell script "open -a " & quoted form of termApp & " " & quoted form of runnerPath
|
|
66
|
-
end if
|
|
67
|
-
|
|
68
|
-
-- Send ACK to health server so the web page can auto-redirect back to the PR
|
|
69
|
-
if ackId is not "" then
|
|
70
|
-
try
|
|
71
|
-
do shell script "curl -s -X POST http://127.0.0.1:4747/ack/" & quoted form of ackId & " --max-time 2 &>/dev/null &"
|
|
72
|
-
end try
|
|
73
|
-
end if
|
|
74
|
-
end if
|
|
75
|
-
on error errMsg
|
|
76
|
-
do shell script "echo '[ERROR] " & quoted form of errMsg & "' >> $HOME/.cache/greptile/greptile-fix.log"
|
|
77
|
-
end try
|
|
78
|
-
end open location
|