@ytspar/sweetlink 1.26.0 → 1.26.1-canary.0a1121a
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.
|
@@ -17,10 +17,10 @@ Resize images to optimal dimensions for Claude's vision capabilities. Claude pro
|
|
|
17
17
|
|
|
18
18
|
## How It Works
|
|
19
19
|
|
|
20
|
-
The
|
|
20
|
+
The `resize-for-claude` script **bundled in this skill's directory** (next to this SKILL.md):
|
|
21
21
|
|
|
22
22
|
1. Reads the image dimensions
|
|
23
|
-
2. If the image aspect ratio is < 3:1, resizes proportionally so the longest side
|
|
23
|
+
2. If the image aspect ratio is < 3:1, resizes proportionally so the longest side is ≤ 1568px (downscale only — already-small images are copied unchanged, never upscaled)
|
|
24
24
|
3. If the image is very tall (≥ 3:1 height:width), splits into overlapping tiles before resizing each
|
|
25
25
|
4. Outputs to a `<filename>-claude/` directory next to the original
|
|
26
26
|
|
|
@@ -37,20 +37,25 @@ Images exceeding these dimensions get downscaled by Claude anyway, wasting token
|
|
|
37
37
|
## Usage
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
#
|
|
41
|
-
|
|
40
|
+
# The script ships WITH this skill — invoke it from the skill's own base
|
|
41
|
+
# directory (announced when the skill loads). No tools-repo lookup, no
|
|
42
|
+
# project-root derivation: the skill and its script are one unit, so this
|
|
43
|
+
# works identically from any repo the skill is linked into.
|
|
44
|
+
# Always invoke via `bash` (as below): npm packing does not preserve the
|
|
45
|
+
# executable bit, so `./resize-for-claude` breaks for package consumers.
|
|
46
|
+
SKILL_DIR="<this skill's base directory>"
|
|
42
47
|
|
|
43
48
|
# Basic usage — resize to 1568px longest side
|
|
44
|
-
"$
|
|
49
|
+
bash "$SKILL_DIR/resize-for-claude" ~/Downloads/mockup.jpg
|
|
45
50
|
|
|
46
51
|
# Custom max side
|
|
47
|
-
"$
|
|
52
|
+
bash "$SKILL_DIR/resize-for-claude" ~/Downloads/mockup.png 1200
|
|
48
53
|
```
|
|
49
54
|
|
|
50
|
-
### Direct invocation (
|
|
55
|
+
### Direct invocation (absolute path)
|
|
51
56
|
|
|
52
57
|
```bash
|
|
53
|
-
|
|
58
|
+
bash /path/to/<skill-dir>/resize-for-claude ~/Downloads/image.jpg
|
|
54
59
|
```
|
|
55
60
|
|
|
56
61
|
## Output
|
|
@@ -72,11 +77,12 @@ Input: ~/Downloads/full-page.png
|
|
|
72
77
|
Size: 1440x8640 (4200KB)
|
|
73
78
|
|
|
74
79
|
Image is very tall (6:1 ratio). Splitting into tiles...
|
|
75
|
-
Part 1:
|
|
76
|
-
Part 2:
|
|
77
|
-
Part 3:
|
|
80
|
+
Part 1: 784x1568 (180KB) -> ~/Downloads/full-page-claude/full-page-part1.png
|
|
81
|
+
Part 2: 784x1568 (165KB) -> ~/Downloads/full-page-claude/full-page-part2.png
|
|
82
|
+
Part 3: 784x1568 (172KB) -> ~/Downloads/full-page-claude/full-page-part3.png
|
|
83
|
+
Part 4: 261x1568 (48KB) -> ~/Downloads/full-page-claude/full-page-part4.png
|
|
78
84
|
|
|
79
|
-
Output: ~/Downloads/full-page-claude/ (
|
|
85
|
+
Output: ~/Downloads/full-page-claude/ (4 parts)
|
|
80
86
|
```
|
|
81
87
|
|
|
82
88
|
## Requirements
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Resize an image for optimal Claude vision consumption.
|
|
3
|
+
# Claude works best with images where the longest side is ≤1568px.
|
|
4
|
+
# For very tall images, splits into multiple parts to preserve detail.
|
|
5
|
+
#
|
|
6
|
+
# Usage: resize-for-claude <image-path> [max-long-side]
|
|
7
|
+
#
|
|
8
|
+
# Examples:
|
|
9
|
+
# resize-for-claude ~/Downloads/mockup.jpg
|
|
10
|
+
# resize-for-claude ~/Downloads/mockup.png 1200
|
|
11
|
+
#
|
|
12
|
+
# Requires: macOS (uses sips)
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
if [[ "${1:-}" == "" ]]; then
|
|
17
|
+
echo "Usage: resize-for-claude <image-path> [max-long-side]" >&2
|
|
18
|
+
echo "" >&2
|
|
19
|
+
echo " max-long-side Maximum pixel length of longest side (default: 1568)" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
MAX_SIDE="${2:-1568}"
|
|
24
|
+
INPUT="$1"
|
|
25
|
+
|
|
26
|
+
if [[ ! -f "$INPUT" ]]; then
|
|
27
|
+
echo "Error: File not found: $INPUT" >&2
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Get image dimensions
|
|
32
|
+
WIDTH=$(sips -g pixelWidth "$INPUT" | tail -1 | awk '{print $2}')
|
|
33
|
+
HEIGHT=$(sips -g pixelHeight "$INPUT" | tail -1 | awk '{print $2}')
|
|
34
|
+
FILESIZE=$(stat -f "%z" "$INPUT")
|
|
35
|
+
|
|
36
|
+
# A non-image (or a format sips can't read) yields empty/zero dimensions,
|
|
37
|
+
# which would otherwise surface as a cryptic arithmetic abort below.
|
|
38
|
+
if ! [[ "$WIDTH" =~ ^[0-9]+$ && "$HEIGHT" =~ ^[0-9]+$ ]] || [[ "$WIDTH" -eq 0 || "$HEIGHT" -eq 0 ]]; then
|
|
39
|
+
echo "Error: Could not read image dimensions from $INPUT (not an image, or a format sips can't read)" >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
echo "Input: $INPUT"
|
|
44
|
+
echo "Size: ${WIDTH}x${HEIGHT} ($(( FILESIZE / 1024 ))KB)"
|
|
45
|
+
|
|
46
|
+
# Determine output path
|
|
47
|
+
DIR=$(dirname "$INPUT")
|
|
48
|
+
BASE=$(basename "$INPUT")
|
|
49
|
+
EXT="${BASE##*.}"
|
|
50
|
+
NAME="${BASE%.*}"
|
|
51
|
+
OUTDIR="$DIR/${NAME}-claude"
|
|
52
|
+
mkdir -p "$OUTDIR"
|
|
53
|
+
|
|
54
|
+
# Aspect ratio: if height > 3x width, split into tiles to preserve detail
|
|
55
|
+
RATIO=$(( HEIGHT / WIDTH ))
|
|
56
|
+
|
|
57
|
+
if [[ "$RATIO" -ge 3 ]]; then
|
|
58
|
+
# Very tall image — split into overlapping tiles then resize each
|
|
59
|
+
TILE_HEIGHT=$(( WIDTH * 2 )) # Each tile is ~2:1 aspect ratio
|
|
60
|
+
OVERLAP=$(( TILE_HEIGHT / 10 ))
|
|
61
|
+
STEP=$(( TILE_HEIGHT - OVERLAP ))
|
|
62
|
+
PART=1
|
|
63
|
+
Y=0
|
|
64
|
+
|
|
65
|
+
# A re-run can produce fewer tiles than the previous run left behind;
|
|
66
|
+
# clear stale parts so the output dir never mixes runs.
|
|
67
|
+
rm -f "$OUTDIR/${NAME}-part"*."$EXT"
|
|
68
|
+
|
|
69
|
+
echo ""
|
|
70
|
+
echo "Image is very tall (${RATIO}:1 ratio). Splitting into tiles..."
|
|
71
|
+
|
|
72
|
+
while [[ "$Y" -lt "$HEIGHT" ]]; do
|
|
73
|
+
REMAINING=$(( HEIGHT - Y ))
|
|
74
|
+
CROP_H=$(( REMAINING < TILE_HEIGHT ? REMAINING : TILE_HEIGHT ))
|
|
75
|
+
|
|
76
|
+
OUTFILE="$OUTDIR/${NAME}-part${PART}.${EXT}"
|
|
77
|
+
|
|
78
|
+
# Crop tile
|
|
79
|
+
sips -c "$CROP_H" "$WIDTH" --cropOffset "$Y" 0 "$INPUT" --out "$OUTFILE" >/dev/null 2>&1 || {
|
|
80
|
+
TMPFILE=$(mktemp "/tmp/resize-claude-XXXX.$EXT")
|
|
81
|
+
cp "$INPUT" "$TMPFILE"
|
|
82
|
+
sips -c "$CROP_H" "$WIDTH" --cropOffset "$Y" 0 "$TMPFILE" --out "$OUTFILE" >/dev/null 2>&1
|
|
83
|
+
rm -f "$TMPFILE"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Resize tile to fit within max side
|
|
87
|
+
TILE_W=$(sips -g pixelWidth "$OUTFILE" | tail -1 | awk '{print $2}')
|
|
88
|
+
TILE_H=$(sips -g pixelHeight "$OUTFILE" | tail -1 | awk '{print $2}')
|
|
89
|
+
|
|
90
|
+
if [[ "$TILE_W" -gt "$MAX_SIDE" || "$TILE_H" -gt "$MAX_SIDE" ]]; then
|
|
91
|
+
if [[ "$TILE_W" -ge "$TILE_H" ]]; then
|
|
92
|
+
sips --resampleWidth "$MAX_SIDE" "$OUTFILE" --out "$OUTFILE" >/dev/null 2>&1
|
|
93
|
+
else
|
|
94
|
+
sips --resampleHeight "$MAX_SIDE" "$OUTFILE" --out "$OUTFILE" >/dev/null 2>&1
|
|
95
|
+
fi
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
NEW_W=$(sips -g pixelWidth "$OUTFILE" | tail -1 | awk '{print $2}')
|
|
99
|
+
NEW_H=$(sips -g pixelHeight "$OUTFILE" | tail -1 | awk '{print $2}')
|
|
100
|
+
NEW_SIZE=$(stat -f "%z" "$OUTFILE")
|
|
101
|
+
echo " Part $PART: ${NEW_W}x${NEW_H} ($(( NEW_SIZE / 1024 ))KB) -> $OUTFILE"
|
|
102
|
+
|
|
103
|
+
Y=$(( Y + STEP ))
|
|
104
|
+
PART=$(( PART + 1 ))
|
|
105
|
+
done
|
|
106
|
+
|
|
107
|
+
echo ""
|
|
108
|
+
echo "Output: $OUTDIR/ ($(( PART - 1 )) parts)"
|
|
109
|
+
else
|
|
110
|
+
# Single image — just resize
|
|
111
|
+
OUTFILE="$OUTDIR/${NAME}.${EXT}"
|
|
112
|
+
cp "$INPUT" "$OUTFILE"
|
|
113
|
+
|
|
114
|
+
if [[ "$WIDTH" -ge "$HEIGHT" ]]; then
|
|
115
|
+
LONG="$WIDTH"
|
|
116
|
+
else
|
|
117
|
+
LONG="$HEIGHT"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [[ "$LONG" -gt "$MAX_SIDE" ]]; then
|
|
121
|
+
if [[ "$WIDTH" -ge "$HEIGHT" ]]; then
|
|
122
|
+
sips --resampleWidth "$MAX_SIDE" "$OUTFILE" --out "$OUTFILE" >/dev/null 2>&1
|
|
123
|
+
else
|
|
124
|
+
sips --resampleHeight "$MAX_SIDE" "$OUTFILE" --out "$OUTFILE" >/dev/null 2>&1
|
|
125
|
+
fi
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
NEW_W=$(sips -g pixelWidth "$OUTFILE" | tail -1 | awk '{print $2}')
|
|
129
|
+
NEW_H=$(sips -g pixelHeight "$OUTFILE" | tail -1 | awk '{print $2}')
|
|
130
|
+
NEW_SIZE=$(stat -f "%z" "$OUTFILE")
|
|
131
|
+
|
|
132
|
+
echo ""
|
|
133
|
+
echo "Output: $OUTFILE"
|
|
134
|
+
echo "Size: ${NEW_W}x${NEW_H} ($(( NEW_SIZE / 1024 ))KB)"
|
|
135
|
+
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ytspar/sweetlink",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.1-canary.0a1121a",
|
|
4
4
|
"description": "Autonomous development toolkit for AI agents - screenshots, DOM queries, console logs, and JavaScript execution via WebSocket and Chrome DevTools Protocol",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"autonomous-development",
|