ãŠã«ãã©ã¯ã€ãã«8çªãäžçºæŽå â Swift+AppleScript åæã«ãŒããš5ã€ã®çœ
ãClaude Codeç°å¢ãã·ãªãŒãºã§ããååã®ç°å¢å£åã»ã³ããã«ã§Claude Codeç°å¢ã®èªå·±èšºæãæžããŸããããä»åã¯å¥ã®äœæ¥ã³ã¹ãã®è©±ã§ãã
ãŠã«ãã©ã¯ã€ãã¢ãã¿äžã« Terminal.app ã®çªã 8 ææ£ä¹±ããŠããç¶æ ããã³ãã³ãäžçºã§ 4Ã2 ã°ãªããã«æŽåãããŸãããosascript ã§çªã䞊ã¹ãã ããã«èŠããŠã座æšç³»ã®å€æã»AppleScript ã®éåææåã»macOS ã®è¡äžžããšãã 3 ã€ã®ã¬ã€ã€ãŒã«çœ ããããŸãããã®èšäºã§ã¯èšèšã® 2 ã€ã®æ žå¿ãšãå®è£ ã§ã¶ã€ãã£ã 5 ã€ã®çœ ãå®ã³ãŒãã§è§£èª¬ããŸãã
å°ãããšïŒãã©ãã°æŽåã« 1 åããã£ãŠãã
3440Ã1440 ã®ãŠã«ãã©ã¯ã€ãã§è€æ°ã® Claude Code ã»ãã·ã§ã³ã䞊ã¹ããšãçªã¯æ¯åãã©ãã©ã®äœçœ®ã«éããŸãããã«ã¹ã¯ãªãŒã³åå²ã§ã¯è¶³ããªããMission Control ã§ã¯äœçœ®ãåºå®ã§ããªããçµå±ããŠã¹ã§ 8 æããã©ãã°ã㊠4Ã2 ã«æããã®ã«æ¯æ 1 åãããŠããŸããã
AppleScript ã§ position ãš size ãçŽæžãããã°çµããã®ã¯ãã§ãããããå®éã«æžãå§ãããš 3 ã€ã®ããšãåãããŸããã
- 座æšç³»ã 2 ã€ããïŒCocoa ã® Y äžåããšã¹ã¯ãªãŒã³åº§æšã® Y äžåãïŒ
set positionãç¡é³ã§ç¡èŠãããç¶æ³ããã- çªã®é«ããæå®å€ã«ãªããªã
ãããããŸãšããŠè§£æ±ºããã¹ã¯ãªããïŒ~/.claude/scripts/terminal-grid8.shïŒã®èšèšãæžããŸãã
èšèšã®æ žå¿â ïŒSwift ã§ visibleFrame ãã°ããŒãã«åº§æšãžå€æããŠã·ã§ã«ã«æž¡ã
AppleScript 㯠position of window ã§ã°ããŒãã«åº§æšïŒå·Šäžåç¹ãY äžåãïŒãè¿ããŸããäžæ¹ macOS ã® NSScreen.visibleFrame 㯠Cocoa 座æšç³»ïŒY äžåãïŒã§ãããããæ··åšããããšèšç®ããããããªããŸãã倿ã Swift ã§ãŸãšããŠæžãŸããã·ã§ã«å€æ° GX GY GW GH ã«æž¡ããŸãã
GEOM=$(swift - <<'EOF'
import AppKit
let screens = NSScreen.screens
guard let main = screens.first else { exit(1) }
// æã暪é·ã®ç»é¢ã察象ã«ãã(ãŠã«ãã©ã¯ã€ã)ãåçãªãã¡ã€ã³ä»¥å€ãåªå
let target = screens.max(by: { $0.frame.width < $1.frame.width })!
let v = target.visibleFrame // Docké€å€(Cocoa座æš: å·Šäžåç¹Yäžåã)
let mainH = main.frame.height
var topY = mainH - (v.origin.y + v.height) // ã°ããŒãã«(å·Šäžåç¹)座æšãžå€æ
var h = v.height
// visibleFrameãã¡ãã¥ãŒããŒãåæ ããªãç»é¢ããã â æåã§å·®ãåŒã
if v.height == target.frame.height {
topY += 30
h -= 30
}
print("\(Int(v.origin.x)) \(Int(topY)) \(Int(v.width)) \(Int(h))")
EOF
)
read -r GX GY GW GH <<< "$GEOM"
mainH - (v.origin.y + v.height) ã®å€æåŒããã€ã³ãã§ããCocoa ã® visibleFrame.origin.y ã¯ã¡ã€ã³ç»é¢äžç«¯ããã®è·é¢ïŒY äžåãïŒãªã®ã§ãã°ããŒãã«ã®ãå·Šäžããã®è·é¢ïŒY äžåãïŒãã«ããã«ã¯ãã¡ã€ã³ç»é¢ã®é«ãããåŒãç®ããŸãã
if v.height == target.frame.height ã®åå²ã¯å®æž¬ã§åºãŠãããã©ãŒã«ããã¯ã§ããã¡ã€ã³ã§ãªãç»é¢ã§ã¯ visibleFrame ãã¡ãã¥ãŒã㌠30px ãå·®ãåŒãããã¬ãŒã ãšåå€ãè¿ãããšããããŸãããã®å Žå㯠Swift åŽã§æåã§åŒããŸãïŒåŸè¿°ã®çœ â£ïŒã
ã»ã«å¯žæ³ã¯åçŽãªæŽæ°é€ç®ã§ãã
CW=$(( GW / COLS )) # åå¹
CH=$(( GH / ROWS )) # è¡é«
èšèšã®æ žå¿â¡ïŒAppleScript ã®åæã«ãŒã
ååã§ã ID ã§ããªã ã«ãŒããã¹ããšã« index ãåã¹ãã£ã³ããã®ãåæã«ãŒãã®éªšåã§ãã
-- åæã«ãŒã: æ¯ãã¹åã¹ãã£ã³ããŠæªé
眮ã®çªã1æã ãåãã
repeat with pass from 1 to (nCells * 3)
set occupied to {}
repeat nCells times
set end of occupied to false
end repeat
set moverIdx to 0
set n to count windows
-- 1) 察象ç»é¢äžã®çªãèµ°æ»ããã»ã«äžèŽæžã¿ãããŒã¯ã»æåã®æªé
眮çªãèšé²
repeat with i from 1 to n
try
set p to position of window i
set px to item 1 of p
set py to item 2 of p
on error
set px to -99999
set py to -99999
end try
if px ⥠(gx - tol) and px < (gx + nCols * cw) and
py ⥠(gy - tol) and py < (gy + nRows * ch) then
-- ã»ã«äžèŽå€å® ...ïŒtol=40px ã®èª€å·®èš±å®¹ïŒ
if (not matched) and moverIdx = 0 then set moverIdx to i
end if
end repeat
-- 2) æªé
眮çªãç¡ããã°åæ
if moverIdx = 0 then exit repeat
-- 3) æåã®ç©ºãã»ã«ãžç§»å (sizeâdelayâpositionâdelayâsizeãdelay å¿
é )
set size of window moverIdx to {cw, ch}
delay 0.2
set position of window moverIdx to {tx, ty}
delay 0.2
set size of window moverIdx to {cw, ch}
delay 0.2
-- èªã¿è¿ã㊠position ãæçµè£æ£(ãªãµã€ãºã§ã®ããªãã察ç)
set p2 to position of window moverIdx
if (item 1 of p2) is not tx or (item 2 of p2) is not ty then
set position of window moverIdx to {tx, ty}
delay 0.2
end if
end repeat
ãforEach ã§å šçªãäžæ°ã«åãããã§ã¯ãªããæªé çœ®ãæ®ãéã 1 æã ãåãããŠåã¹ãã£ã³ããç¹°ãè¿ãèšèšã«ããŠããçç±ã¯ 2 ã€ãããŸãã
- åååç §ã䜿ããªãïŒçœ â ïŒã®ã§ãã¹ããŸããã§ãªããžã§ã¯ãåç §ãä¿æã§ããªã
- 1 æåãããšã»ã«ã®å æç¶æ ãå€ããã®ã§ã¹ãã£ã³ãããçŽãå¿ èŠããã
ææªã±ãŒã¹ïŒ8 çªãå
šéšå€ããŠããïŒã§ã nCells * 3 = 24 ãã¹ããã°åæããŸãã
delay 0.2ãæããšset positionãç¡é³ã§ç¡èŠãããŸãïŒçœ â¡ïŒãAppleScript åŽã®ãšã©ãŒãåºãŸãããsize â delay â position â delay â sizeã® 5 ã¹ããããšãèªã¿è¿ããŠåè£æ£ãããã©ãŒã«ããã¯ãå¿ èŠã§ãã
åæã«ãŒãã®åŸã«ãæäžæ®µã® y ãå®é«ã§çµ±äžããæ£èŠåãã¹ãå ¥ããŸãã
-- æäžæ®µyã®æ£èŠå: è¡äžžãã§ã»ã«é«ãè¶
ããå®é«ã®ã¯ã©ã³ãæºã察ç
set bottomEdge to gy + nRows * ch
set lastRowTop to gy + (nRows - 1) * ch
repeat with i from 1 to (count windows)
try
set p to position of window i
-- æäžæ®µã®çªã ãã察象ã«å®é«ã§äžç«¯æã
if py ⥠(lastRowTop - tol) and py < bottomEdge then
set s to size of window i
set wh to item 2 of s -- å®éã®ãã¯ã»ã«é«
set targetY to bottomEdge - wh
if py is not targetY then
set position of window i to {bestX, targetY}
delay 0.2
end if
end if
end try
end repeat
èžãã èœãšã穎
â çªã®åååç §ã¯ã¹ãããŒå転ã§å€±å¹ãã
Terminal.app ã¯ã¿ãã®ããŒãäžã«ã¿ã€ãã«ãã¹ãããŒæåïŒâ â â³ïŒã§çœ®ãæããŸããã»ãã·ã§ã³éå§çŽåŸã«ååã§çªãåç
§ãããš -1728ïŒobject not foundïŒãè¿ããŸããååã«ããåç
§ããããæ¯ãã¹ window i ã® index ã§çŽæ¥æäœããŸãã
â¡ size çŽåŸã® position èšå®ã¯ delay ãªãã§ç¡èŠããã
set position of window i to {tx, ty} ããªãµã€ãºçŽåŸã«çœ®ããšãmacOS ã®ãŠã£ã³ããŠãµãŒããåã®ãªãµã€ãºåŠçãå®äºãããåã«åº§æšå€æŽãå±ããŠæšãŠãããŸããdelay 0.2 ã 2 ç®æïŒsize åŸã»position åŸïŒã«å
¥ããŠããèªã¿è¿ãè£æ£ããŸãã
⢠Terminal ã®è¡é«äžžãã§ã»ã«é«ãæå®å€ã«ãªããªã
Terminal.app ã¯çªã®é«ãããè¡æ°Ãè¡é«ãã«äžžããŸããäŸãã°ã»ã«é«ã 705px ã«æå®ããŠãå®é㯠44è¡Ã16pxïŒ704px ã 45è¡Ã16pxïŒ720px ã«ãªããŸãããã®èª€å·®ã macOS ã®å¢çã¯ã©ã³ããšçµã¿åããããæäžæ®µã®çªã® y ãæ° px ãããŠã»ã«äžèŽå€å®ãéããªããªããŸããåæã«ãŒãã®åŸã«ãå®é«ã§äžç«¯æããã®æ£èŠåãã¹ãèµ°ãããŠåžåããŸãã
⣠visibleFrame ãã¡ãã¥ãŒããŒåãåŒããªãããšããã
ã¡ã€ã³ã§ãªãç»é¢ã§ã¯ NSScreen.visibleFrame ã NSScreen.frame ãšåãå€ãè¿ãå ŽåããããŸãïŒå®æž¬ïŒããã®å Žåãèšç®äžã®ã°ãªããäžç«¯ãã¡ãã¥ãŒããŒã«éãªããŸããSwift åŽã§ v.height == target.frame.height ãæ¡ä»¶ã« topY += 30 / h -= 30 ãæåé©çšããŸãã
if v.height == target.frame.height {
topY += 30
h -= 30
}
â€ éæž¡ãšã©ãŒïŒ-10006/-1728ïŒã¯å詊è¡ã§èªç¶å埩ãã
çªã®åæåäžãååå€åã®ã¿ã€ãã³ã°ã§ -10006ïŒinvalid indexïŒã -1728 ãé£ã³ãŸããon error ã§ delay 0.3 ãæãã§æ¬¡ãã¹ãžæãããšãåæã«ãŒããæ¬¡ã®ãã¹ã§åãçªãã¹ãã£ã³ãçŽããŠååããŸãããšã©ãŒãå³ abort ã«ããªãã®ããã€ã³ãã§ãã
on error
delay 0.3 -- éæž¡ãšã©ãŒã¯æ¬¡ãã¹ã§å詊è¡
end try
äœ¿ãæ¹ãšæ€èšŒ
~/.claude/scripts/terminal-grid8.sh
ã³ãã³ãäžçºã§ Terminal.app ã® 8 çªãæŽåããŸããå岿°ã¯åé ã® 2 è¡ã ãã§å€æŽã§ããŸãã
COLS=4
ROWS=2
6 åå²ã«ããããã° COLS=3 ROWS=2 ã«æžãæããŸãã
æçµã¬ããŒãã«åçªã® x,y WxH ã¿ã€ãã« ãåºåãããŸãã3440 å¹
ã®ç»é¢ãªã x ã 0/860/1720/2580 ã® 4 å€ã«æããy ãäžæ®µã»äžæ®µãããã 1 ã€ã®å€ã«åæããŠããã°æåã§ãã
ãŸãšã
- Cocoa Y-up â ã°ããŒãã« Y-down 倿ã¯
mainH - (v.origin.y + v.height)ã® Swift äžè¡ã§æžãŸããŠã·ã§ã«ã«æž¡ã - AppleScript ã®åæã«ãŒã㯠foreach ã§ãªãã1 æåãããŠåã¹ãã£ã³ãã®ç¹°ãè¿ããåååç §ãæšãŠãæ¯ãã¹ index ã§æäœãã
delay 0.2ã¯çç¥ãããšset positionãç¡é³ã§ç¡èŠããã- Terminal ã®è¡é«äžžãã«ãã y ããã¯ãåæåŸã®ãå®é«ã§äžç«¯æãããã¹ã§æ£èŠåãã
visibleFrameãã¡ãã¥ãŒããŒãåæ ããªãç»é¢ããããããheight == frame.heightã®æ¡ä»¶ã§æå 30px è£æ£ãå ¥ãã
次åã¯ããã®ã¹ã¯ãªãããããªã¬ãŒã«ãã Claude Code èµ·åæã®ç°å¢æŽåãã㯠ââ launchd ãã Terminal çªã»ã¹ããŒã¿ã¹ã©ã€ã³ã»Obsidian ãäžæ¬ã§å®äœçœ®ã«é 眮ããè©±ãæžããŸãã
LilyïŒ@bokuwalilyïŒâ å人éçºè ãClaude Code ã§èªåååºç€ãçµã¿ãªãããiOSã¢ããªãWebãµãŒãã¹ãéç£ããŠããŸã
- AIã§ãå¯ãŠãŠãåãä»çµã¿ããäœã£ãŠæ120äžã«ãã話㯠noteã®ææèšäº ã«ð°
- OSS: github.com/bokuwalily ð
- ææ°æ å ±ã»ãåãåãã㯠X @bokuwalily ãžð
çããã® â€ïž ãã·ã§ã¢ãå±ã¿ã«ãªããŸãïŒ