iterm-neovim-launcher
# iTerm2 Neovim Launcher Skill
What this skill does
# iTerm2 Neovim Launcher Skill
**Purpose**: Create macOS scripts that open files in Neovim within the active iTerm2 window, handling automation reliably despite AppleScript limitations.
**Use this skill when**:
- Creating scripts to launch terminal applications from macOS GUI
- Debugging AppleScript iTerm2 automation issues
- Setting up file associations to open in terminal editors
- Working with iTerm2, tmux, or terminal-based workflows on macOS
---
## The Working Script
**Location**: `~/.local/bin/open-in-neovim`
```bash
#!/bin/bash
# Opens files in Neovim within the latest active iTerm2 window
FILE="$1"
# Guard: require file argument
if [[ -z "$FILE" ]]; then
echo "Usage: open-in-neovim <file>"
exit 1
fi
# Get absolute path
if [[ ! "$FILE" = /* ]]; then
FILE="$(cd "$(dirname "$FILE")" && pwd)/$(basename "$FILE")"
fi
# Send command to iTerm2 using System Events (more reliable than write text)
osascript - "$FILE" <<'APPLESCRIPT'
on run argv
set filePath to item 1 of argv
set cmd to "nvim \"" & filePath & "\""
tell application "iTerm"
activate
delay 0.2
if (count of windows) = 0 then
create window with default profile
delay 0.3
end if
end tell
tell application "System Events"
keystroke cmd
keystroke return
end tell
end run
APPLESCRIPT
exit $?
```
**Setup**:
```bash
chmod +x ~/.local/bin/open-in-neovim
# Ensure ~/.local/bin is in PATH
```
---
## Critical Lessons Learned
### 1. **AppleScript String Escaping is Treacherous**
❌ **What Doesn't Work**: Passing complex command strings with nested quotes
```applescript
# This causes AppleEvent errors
set cmd to "tmux send-keys -t '{last}' 'nvim \"$FILE\"' Enter"
tell targetSession
write text cmd
end tell
```
✅ **What Works**: Construct commands in AppleScript, not bash
```applescript
# Build the command in AppleScript
set filePath to item 1 of argv
set cmd to "nvim \"" & filePath & "\""
```
**Key Insight**: When passing data from bash to AppleScript, pass simple values (like file paths) and let AppleScript do the string construction.
---
### 2. **iTerm2's `write text` is Unreliable**
❌ **Fails Intermittently**:
```applescript
tell targetSession
write text cmd # AppleEvent handler failed (-10000)
end tell
```
**Symptoms**:
- Works sometimes, fails randomly
- Error: "iTerm got an error: AppleEvent handler failed. (-10000)"
- No clear pattern to failures
- Happens regardless of string escaping approach
✅ **Reliable Alternative**: Use `System Events` keystroke
```applescript
tell application "System Events"
keystroke cmd # Simulates typing
keystroke return # Simulates Enter key
end tell
```
**Why This Works**:
- Simulates actual keyboard input rather than using iTerm's API
- Works regardless of iTerm's internal state
- Independent of session, tmux, or shell state
- More robust across iTerm2 versions
---
### 3. **Passing Arguments to AppleScript via Heredoc**
✅ **Correct Pattern**:
```bash
osascript - "$ARG1" "$ARG2" <<'APPLESCRIPT'
on run argv
set arg1 to item 1 of argv
set arg2 to item 2 of argv
# ... use args here
end run
APPLESCRIPT
```
**Critical Details**:
- Use `osascript -` to read from stdin
- Pass arguments BEFORE the heredoc
- Use **quoted heredoc** (`<<'APPLESCRIPT'`) to prevent bash expansion
- Access via `argv` in AppleScript's `on run` handler
- Items are 1-indexed: `item 1 of argv`, not `item 0`
❌ **Common Mistakes**:
```bash
# Don't put variables inside the heredoc expecting bash substitution
osascript <<APPLESCRIPT # Unquoted = bash expands $vars
set cmd to "$BASH_VAR" # Won't work as expected
APPLESCRIPT
# Don't try to construct complex commands in bash then pass them
CMD="tmux send-keys 'nvim \"$FILE\"'"
osascript - "$CMD" <<'APPLESCRIPT' # Too complex, escaping nightmare
```
---
### 4. **Timing and Delays Matter**
✅ **Add small delays for reliability**:
```applescript
tell application "iTerm"
activate
delay 0.2 # Wait for iTerm to come to foreground
if (count of windows) = 0 then
create window with default profile
delay 0.3 # Wait for window creation
end if
end tell
tell application "System Events"
keystroke cmd # Now iTerm is guaranteed to be ready
end tell
```
**Why**:
- AppleScript commands are asynchronous
- `activate` doesn't guarantee the app is ready
- `create window` takes time to complete
- Without delays, keystrokes may be sent before window is active
---
### 5. **File Path Handling Best Practices**
```bash
# Always convert to absolute path
if [[ ! "$FILE" = /* ]]; then
FILE="$(cd "$(dirname "$FILE")" && pwd)/$(basename "$FILE")"
fi
```
**Why**:
- Relative paths depend on current working directory
- When script is called from different contexts (Finder, terminal, file associations), `pwd` differs
- Absolute paths work regardless of where Neovim opens
**Handles**:
- Regular filenames: `file.txt`
- Paths with spaces: `my file.txt`
- Relative paths: `../other/file.txt`
- Already absolute: `/full/path/file.txt`
---
## Common AppleEvent Errors and Solutions
| Error Code | Message | Cause | Solution |
|------------|---------|-------|----------|
| -10000 | AppleEvent handler failed | iTerm's `write text` in bad state | Use System Events keystroke |
| -2741 | Syntax error: Expected """ but found unknown token | Unescaped quotes in strings | Use AppleScript string concatenation `&` |
| -1708 | Can't get item 1 of argv | No arguments passed to osascript | Pass args before heredoc: `osascript - "$ARG"` |
---
## Testing Methodology
**Progressive Testing Approach**:
```bash
# 1. Test basic iTerm communication
osascript <<'APPLESCRIPT'
tell application "iTerm"
activate
display dialog "iTerm is responding"
end tell
APPLESCRIPT
# 2. Test window/session access
osascript <<'APPLESCRIPT'
tell application "iTerm"
activate
set targetWindow to current window
set targetSession to current session of targetWindow
# If this works, iTerm API is accessible
end tell
APPLESCRIPT
# 3. Test write text (will likely fail)
osascript <<'APPLESCRIPT'
tell application "iTerm"
tell current session of current window
write text "echo test"
end tell
end tell
APPLESCRIPT
# 4. Test System Events alternative (should work)
osascript <<'APPLESCRIPT'
tell application "iTerm"
activate
delay 0.2
end tell
tell application "System Events"
keystroke "echo test"
keystroke return
end tell
APPLESCRIPT
# 5. Test with actual file path via argv
osascript - "/tmp/test.md" <<'APPLESCRIPT'
on run argv
set filePath to item 1 of argv
set cmd to "nvim \"" & filePath & "\""
tell application "iTerm"
activate
delay 0.2
end tell
tell application "System Events"
keystroke cmd
keystroke return
end tell
end run
APPLESCRIPT
```
**Key Testing Insights**:
- Test in isolation before integrating
- Start simple, add complexity gradually
- Verify each layer works before moving up
- Test with edge cases: spaces, special chars, long paths
---
## Tmux Integration Considerations
**Original Goal**: Detect tmux and use `tmux send-keys`
**Reality**: Not necessary with `System Events` approach
```bash
# This was attempted but abandoned
if command -v tmux &>/dev/null && tmux list-sessions &>/dev/null 2>&1; then
CMD="tmux send-keys -t '{last}' 'nvim \"$FILE\"' Enter"
else
CMD="nvim \"$FILE\""
fi
```
**Why It Was Removed**:
- System Events keystroke simulates typing, which works in ANY shell state
- If you're in tmux, typing `nvim file` works naturally
- No need to detect or special-case tmux
- Simpler = more reliable
**When You WOULD Need Tmux Detection**:
- Opening files in a specific tmux pane (not current)
- Remote tmux sessions
- Scripted tmux workflows requiring precise pane targeting
---
## Setting Up File Associations (Optional)
Once the script works, you can set it as the default openeRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.