Merge pull request #8 from heyitsnoah/feature/icloud-support-and-launcher-command
feat: add iCloud vault support and launcher command installation
This commit is contained in:
@@ -51,7 +51,13 @@ Then generate a customized CLAUDE.md file tailored to their needs.
|
|||||||
|
|
||||||
3. **Gather Vault Information**
|
3. **Gather Vault Information**
|
||||||
- Search common locations for existing Obsidian vaults (.obsidian folder)
|
- Search common locations for existing Obsidian vaults (.obsidian folder)
|
||||||
- Check: ~/Documents, ~/Desktop, home directory, current directory parent
|
- Check these paths with appropriate depth limits:
|
||||||
|
- `~/Documents` (maxdepth 3) - all platforms
|
||||||
|
- `~/Desktop` (maxdepth 3) - all platforms
|
||||||
|
- `~/Library/Mobile Documents/iCloud~md~obsidian/Documents` (maxdepth 5 -
|
||||||
|
**macOS only**, iCloud vaults)
|
||||||
|
- Home directory `~/` (maxdepth 2) - all platforms
|
||||||
|
- Current directory parent (maxdepth 2) - all platforms
|
||||||
- If found, ask: "Found Obsidian vault at [path]. Is this the vault you want
|
- If found, ask: "Found Obsidian vault at [path]. Is this the vault you want
|
||||||
to import?"
|
to import?"
|
||||||
- Count files correctly: `find [path] -type f -name "*.md" | wc -l` (no depth
|
- Count files correctly: `find [path] -type f -name "*.md" | wc -l` (no depth
|
||||||
@@ -64,8 +70,15 @@ Then generate a customized CLAUDE.md file tailored to their needs.
|
|||||||
- Check for daily notes folder and format
|
- Check for daily notes folder and format
|
||||||
- Identify most active folders by file count
|
- Identify most active folders by file count
|
||||||
- Detect if using PARA, Zettelkasten, Johnny Decimal, or custom
|
- Detect if using PARA, Zettelkasten, Johnny Decimal, or custom
|
||||||
- If not the right one or none found, ask for path to existing vault
|
- If not the right one or none found:
|
||||||
- If no existing vault, they're starting fresh
|
- **On macOS only:** Ask: "Is your vault stored in iCloud Drive? (yes/no)"
|
||||||
|
- If yes (macOS): "Please enter the full path to your vault (e.g.,
|
||||||
|
~/Library/Mobile Documents/iCloud~md~obsidian/Documents/YourVault)"
|
||||||
|
- If no, or on Linux/Windows: "Please enter the path to your existing
|
||||||
|
vault, or type 'skip' to start fresh"
|
||||||
|
- **Validate user-provided paths** (see "User Path Validation" section
|
||||||
|
below)
|
||||||
|
- If no existing vault or user skips, they're starting fresh
|
||||||
|
|
||||||
4. **Ask Configuration Questions**
|
4. **Ask Configuration Questions**
|
||||||
- "What's your name?" (for personalization)
|
- "What's your name?" (for personalization)
|
||||||
@@ -349,6 +362,185 @@ If the user's response is unclear:
|
|||||||
- Example: "I want to make sure I import the right vault. Please type the number
|
- Example: "I want to make sure I import the right vault. Please type the number
|
||||||
of your choice (1, 2, or 3)."
|
of your choice (1, 2, or 3)."
|
||||||
|
|
||||||
|
### Platform Compatibility
|
||||||
|
|
||||||
|
This command is designed to work across Linux, macOS, and Windows (WSL/Git
|
||||||
|
Bash), with platform-specific features:
|
||||||
|
|
||||||
|
**All Platforms:**
|
||||||
|
|
||||||
|
- Search ~/Documents, ~/Desktop, home directory
|
||||||
|
- Standard Obsidian vault detection
|
||||||
|
- Full vault import and setup
|
||||||
|
|
||||||
|
**macOS Only:**
|
||||||
|
|
||||||
|
- iCloud Drive vault detection and import
|
||||||
|
- Obsidian's iCloud sync is macOS-only, so iCloud features are disabled on other
|
||||||
|
platforms
|
||||||
|
|
||||||
|
**Platform Detection:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check platform
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
# macOS - enable iCloud features
|
||||||
|
PLATFORM="macOS"
|
||||||
|
ICLOUD_SUPPORTED=true
|
||||||
|
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||||
|
# Linux
|
||||||
|
PLATFORM="Linux"
|
||||||
|
ICLOUD_SUPPORTED=false
|
||||||
|
elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
|
||||||
|
# Windows (Git Bash or WSL)
|
||||||
|
PLATFORM="Windows"
|
||||||
|
ICLOUD_SUPPORTED=false
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### iCloud Vault Search Implementation
|
||||||
|
|
||||||
|
When searching for vaults, use this find command pattern:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard locations (shallow search)
|
||||||
|
# Note: 2>/dev/null suppresses expected permission errors from system directories
|
||||||
|
# If no vaults are found, we'll ask the user for their vault path
|
||||||
|
find ~/Documents ~/Desktop -maxdepth 3 -type d -name ".obsidian" 2>/dev/null
|
||||||
|
|
||||||
|
# iCloud location (deeper search needed due to nested structure)
|
||||||
|
# Only search on macOS
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
find ~/Library/Mobile\ Documents/iCloud~md~obsidian/Documents -maxdepth 5 -type d -name ".obsidian" 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Home directory (shallow to avoid deep recursion)
|
||||||
|
find ~ -maxdepth 2 -type d -name ".obsidian" 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
The iCloud path requires:
|
||||||
|
|
||||||
|
- Higher maxdepth (5) due to nested folder structure
|
||||||
|
- Escaped spaces in path name
|
||||||
|
- Silent error handling (2>/dev/null) as many users won't have iCloud
|
||||||
|
- Platform check (macOS only)
|
||||||
|
|
||||||
|
**Error Handling Note:** Permission errors are suppressed (2>/dev/null) because
|
||||||
|
they're expected when searching system directories. If no vaults are found, the
|
||||||
|
script gracefully prompts the user for their vault path.
|
||||||
|
|
||||||
|
### User Path Validation
|
||||||
|
|
||||||
|
When users manually provide a vault path, validate it thoroughly with helpful
|
||||||
|
error messages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# User provided path
|
||||||
|
USER_PATH="$1"
|
||||||
|
|
||||||
|
# Expand tilde and resolve to absolute path
|
||||||
|
USER_PATH="${USER_PATH/#\~/$HOME}"
|
||||||
|
REAL_PATH=$(realpath "$USER_PATH" 2>/dev/null)
|
||||||
|
|
||||||
|
# Validation 1: Path exists
|
||||||
|
if [ -z "$REAL_PATH" ]; then
|
||||||
|
echo "❌ Error: Path does not exist: $USER_PATH"
|
||||||
|
echo ""
|
||||||
|
echo "💡 Suggestions:"
|
||||||
|
echo " • Check for typos in the path"
|
||||||
|
echo " • Make sure you're using the full path (e.g., /Users/name/vault)"
|
||||||
|
echo " • You can use ~ for your home directory (e.g., ~/Documents/vault)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validation 2: Is a directory
|
||||||
|
if [ ! -d "$REAL_PATH" ]; then
|
||||||
|
echo "❌ Error: Not a directory: $REAL_PATH"
|
||||||
|
echo ""
|
||||||
|
echo "💡 The path exists but points to a file, not a folder."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validation 3: Contains .obsidian folder
|
||||||
|
if [ ! -d "$REAL_PATH/.obsidian" ]; then
|
||||||
|
echo "❌ Error: Not a valid Obsidian vault (no .obsidian folder)"
|
||||||
|
echo " Looking in: $REAL_PATH"
|
||||||
|
echo ""
|
||||||
|
echo "💡 Suggestions:"
|
||||||
|
echo " • Make sure the path points to your vault root (not a subfolder)"
|
||||||
|
echo " • Check that you've opened this vault in Obsidian at least once"
|
||||||
|
echo " • Try the path without trailing slash"
|
||||||
|
echo " • For iCloud: ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/YourVault"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validation 4: Readable permissions
|
||||||
|
if [ ! -r "$REAL_PATH/.obsidian" ]; then
|
||||||
|
echo "❌ Error: Cannot read vault directory (permission denied)"
|
||||||
|
echo " Path: $REAL_PATH"
|
||||||
|
echo ""
|
||||||
|
echo "💡 You may need to:"
|
||||||
|
echo " • Check file permissions with: ls -la \"$REAL_PATH\""
|
||||||
|
echo " • Make sure you own this directory"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show resolved path if different from input
|
||||||
|
if [ "$USER_PATH" != "$REAL_PATH" ]; then
|
||||||
|
echo "✓ Resolved path: $REAL_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Valid vault path
|
||||||
|
VAULT_PATH="$REAL_PATH"
|
||||||
|
echo "✓ Valid Obsidian vault found"
|
||||||
|
```
|
||||||
|
|
||||||
|
This validation:
|
||||||
|
|
||||||
|
- Expands `~` to home directory properly
|
||||||
|
- Resolves symlinks and relative paths to absolute paths
|
||||||
|
- Checks all essential requirements (exists, is directory, has .obsidian,
|
||||||
|
readable)
|
||||||
|
- Provides helpful, actionable error messages with suggestions
|
||||||
|
- Shows the resolved path so users understand what's being checked
|
||||||
|
- Trusts users (allows symlinks, paths outside home directory)
|
||||||
|
- Cross-platform compatible (works on Linux, macOS, Windows/WSL)
|
||||||
|
|
||||||
|
### iCloud Sync State Checking
|
||||||
|
|
||||||
|
When a user selects an iCloud vault, check sync state and warn if needed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# After user confirms vault selection
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]] && [[ "$vault_path" == *"iCloud"* ]]; then
|
||||||
|
# Check for common iCloud sync indicators
|
||||||
|
if [ -f "$vault_path/.icloud" ] || [ -f "$vault_path/.obsidian/.icloud" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "📱 iCloud Sync Notice:"
|
||||||
|
echo " This vault appears to be still downloading from iCloud."
|
||||||
|
echo " For best results, open it in Obsidian first to ensure files are synced."
|
||||||
|
echo ""
|
||||||
|
read -p "Continue anyway? (yes/no): " sync_answer
|
||||||
|
if [[ ! "$sync_answer" =~ ^[Yy] ]]; then
|
||||||
|
echo "No problem! Open the vault in Obsidian, then re-run /init-bootstrap"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "📱 iCloud vault detected. If import seems incomplete, make sure sync is complete."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
This provides a soft warning that:
|
||||||
|
|
||||||
|
- Only runs on macOS for iCloud paths
|
||||||
|
- Checks for placeholder files that indicate incomplete download
|
||||||
|
- Asks for confirmation if sync issues detected
|
||||||
|
- Gives gentle reminder even when no issues found
|
||||||
|
- Lets users proceed if they choose
|
||||||
|
|
||||||
## Interactive Example
|
## Interactive Example
|
||||||
|
|
||||||
````
|
````
|
||||||
@@ -408,7 +600,8 @@ First-run marker removed
|
|||||||
Now let me ask you a few questions to customize your setup:
|
Now let me ask you a few questions to customize your setup:
|
||||||
|
|
||||||
🔍 **Searching for existing Obsidian vaults...** [Searches ~/Documents,
|
🔍 **Searching for existing Obsidian vaults...** [Searches ~/Documents,
|
||||||
~/Desktop, ~/, and parent directories]
|
~/Desktop, home directory, and parent directories. On macOS, also searches
|
||||||
|
iCloud Drive]
|
||||||
|
|
||||||
### Case 1: Single Vault Found
|
### Case 1: Single Vault Found
|
||||||
|
|
||||||
@@ -457,6 +650,39 @@ User: yes
|
|||||||
Great! I'll import your vault to OLD_VAULT/ where it will be safely preserved.
|
Great! I'll import your vault to OLD_VAULT/ where it will be safely preserved.
|
||||||
You can migrate files to the PARA folders at your own pace.
|
You can migrate files to the PARA folders at your own pace.
|
||||||
|
|
||||||
|
### Case 3: No Vaults Found (Platform-Aware)
|
||||||
|
|
||||||
|
🔍 **No Obsidian vaults found in common locations.**
|
||||||
|
|
||||||
|
**On macOS:** Is your vault stored in iCloud Drive? (yes/no)
|
||||||
|
|
||||||
|
User: yes
|
||||||
|
|
||||||
|
Please enter the full path to your vault: (Example: ~/Library/Mobile
|
||||||
|
Documents/iCloud~md~obsidian/Documents/YourVault)
|
||||||
|
|
||||||
|
User: ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/MyVault
|
||||||
|
|
||||||
|
[Validates path and shows vault stats]
|
||||||
|
|
||||||
|
Found vault at: ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/MyVault
|
||||||
|
📊 Vault stats: 1,248 markdown files, 523MB total size
|
||||||
|
|
||||||
|
Would you like to import this vault? (yes/skip)
|
||||||
|
|
||||||
|
**On Linux/Windows:** Please enter the path to your existing Obsidian vault, or
|
||||||
|
type 'skip' to start fresh: (Example: ~/Documents/MyVault or
|
||||||
|
/home/user/obsidian-vault)
|
||||||
|
|
||||||
|
User: ~/Documents/MyVault
|
||||||
|
|
||||||
|
[Validates path and shows vault stats]
|
||||||
|
|
||||||
|
Found vault at: ~/Documents/MyVault 📊 Vault stats: 1,248 markdown files, 523MB
|
||||||
|
total size
|
||||||
|
|
||||||
|
Would you like to import this vault? (yes/skip)
|
||||||
|
|
||||||
📦 **Analyzing your vault structure...** [Running tree to see folder hierarchy]
|
📦 **Analyzing your vault structure...** [Running tree to see folder hierarchy]
|
||||||
[Sampling notes to understand content] [Detecting naming patterns from recent
|
[Sampling notes to understand content] [Detecting naming patterns from recent
|
||||||
files]
|
files]
|
||||||
|
|||||||
@@ -0,0 +1,343 @@
|
|||||||
|
---
|
||||||
|
allowed-tools: [Read, Write, Bash]
|
||||||
|
description: Install claudesidian shell command to launch Claude Code from anywhere
|
||||||
|
argument-hint: (optional shell: bash/zsh/fish)
|
||||||
|
---
|
||||||
|
|
||||||
|
# Install Claudesidian Command
|
||||||
|
|
||||||
|
Creates a shell alias/function that allows you to run `claudesidian` from
|
||||||
|
anywhere to open your vault in Claude Code.
|
||||||
|
|
||||||
|
## Task
|
||||||
|
|
||||||
|
Install a shell command that:
|
||||||
|
|
||||||
|
1. Changes to your claudesidian vault directory
|
||||||
|
2. Launches Claude Code
|
||||||
|
3. Works from any directory in your terminal
|
||||||
|
|
||||||
|
Similar to having a quick launcher for your vault.
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
### 1. **Detect Current Setup**
|
||||||
|
|
||||||
|
- Check which shell the user is using (bash/zsh/fish)
|
||||||
|
- Find the current working directory (vault path)
|
||||||
|
- Determine the appropriate config file
|
||||||
|
|
||||||
|
### 2. **Create the Command**
|
||||||
|
|
||||||
|
The command will be an alias that:
|
||||||
|
|
||||||
|
- Changes to the vault directory: `cd /path/to/your/vault`
|
||||||
|
- Tries to resume existing session: `claude --resume 2>/dev/null`
|
||||||
|
- Falls back to new session if no existing one: `|| claude`
|
||||||
|
- All in one command with properly escaped path:
|
||||||
|
`(cd "/path/to/vault" && (claude --resume 2>/dev/null || claude))`
|
||||||
|
|
||||||
|
**Important:** The path must be properly escaped to handle spaces and special
|
||||||
|
characters.
|
||||||
|
|
||||||
|
This automatically enters resume mode if there's an existing session, or starts
|
||||||
|
a new one if not.
|
||||||
|
|
||||||
|
### 3. **Install to Shell Config**
|
||||||
|
|
||||||
|
Add the alias to the appropriate config file:
|
||||||
|
|
||||||
|
- **Bash**: `~/.bashrc` or `~/.bash_profile`
|
||||||
|
- **Zsh**: `~/.zshrc`
|
||||||
|
- **Fish**: `~/.config/fish/config.fish`
|
||||||
|
|
||||||
|
### 4. **Verify Installation**
|
||||||
|
|
||||||
|
- Show the added line
|
||||||
|
- Remind user to reload their shell or source the config
|
||||||
|
- Provide test command
|
||||||
|
|
||||||
|
## Shell Detection
|
||||||
|
|
||||||
|
Detects the user's default shell, with support for command-line override:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if shell specified as argument (/install-claudesidian-command zsh)
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
# User provided shell type as argument
|
||||||
|
SHELL_TYPE="$1"
|
||||||
|
else
|
||||||
|
# Auto-detect from $SHELL (user's default shell, not current shell)
|
||||||
|
SHELL_TYPE=$(basename "$SHELL")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate shell type and set appropriate config file
|
||||||
|
case "$SHELL_TYPE" in
|
||||||
|
zsh)
|
||||||
|
CONFIG_FILE="$HOME/.zshrc"
|
||||||
|
;;
|
||||||
|
bash)
|
||||||
|
# Prefer .bashrc on Linux, .bash_profile on macOS
|
||||||
|
if [ -f "$HOME/.bashrc" ]; then
|
||||||
|
CONFIG_FILE="$HOME/.bashrc"
|
||||||
|
else
|
||||||
|
CONFIG_FILE="$HOME/.bash_profile"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
fish)
|
||||||
|
CONFIG_FILE="$HOME/.config/fish/config.fish"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "❌ Unsupported shell: $SHELL_TYPE"
|
||||||
|
echo " Supported shells: bash, zsh, fish"
|
||||||
|
echo " Usage: /install-claudesidian-command [bash|zsh|fish]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "🐚 Installing for: $SHELL_TYPE"
|
||||||
|
echo "📝 Config file: $CONFIG_FILE"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key improvements:**
|
||||||
|
|
||||||
|
- Uses `$SHELL` to detect default shell (not `$ZSH_VERSION`/`$BASH_VERSION`
|
||||||
|
which detect current session)
|
||||||
|
- Supports command-line argument to override auto-detection
|
||||||
|
- Shows detected shell and config file for transparency
|
||||||
|
- Validates shell type and provides clear error message for unsupported shells
|
||||||
|
|
||||||
|
## Installation Steps
|
||||||
|
|
||||||
|
1. **Detect shell**: Use argument if provided, otherwise auto-detect from
|
||||||
|
`$SHELL`
|
||||||
|
2. **Get vault path**: Use `pwd` to get current directory
|
||||||
|
3. **Escape the path**: Properly escape quotes and special characters for shell
|
||||||
|
safety
|
||||||
|
```bash
|
||||||
|
# Escape any double quotes in the path
|
||||||
|
ESCAPED_PATH="${VAULT_PATH//\"/\\\"}"
|
||||||
|
# Also escape backslashes
|
||||||
|
ESCAPED_PATH="${ESCAPED_PATH//\\/\\\\}"
|
||||||
|
```
|
||||||
|
4. **Check if already installed**: Search config file for existing
|
||||||
|
`claudesidian` alias/function
|
||||||
|
```bash
|
||||||
|
# Check for existing alias/function
|
||||||
|
if grep -q "alias claudesidian\|function claudesidian" "$CONFIG_FILE"; then
|
||||||
|
echo "⚠️ Found existing claudesidian command:"
|
||||||
|
grep -A 3 "claudesidian" "$CONFIG_FILE"
|
||||||
|
echo ""
|
||||||
|
read -p "Replace it? (yes/no): " replace_answer
|
||||||
|
if [[ ! "$replace_answer" =~ ^[Yy] ]]; then
|
||||||
|
echo "Installation cancelled. Existing command preserved."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Mark for replacement (will remove before adding new one)
|
||||||
|
REPLACING=true
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
5. **Get user confirmation**: Show what will be added and get final confirmation
|
||||||
|
6. **Create backup**: Only if proceeding with modification
|
||||||
|
```bash
|
||||||
|
# Create backup with timestamp
|
||||||
|
BACKUP_FILE="$CONFIG_FILE.backup-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
cp "$CONFIG_FILE" "$BACKUP_FILE"
|
||||||
|
echo "💾 Backup created: $BACKUP_FILE"
|
||||||
|
```
|
||||||
|
7. **Build the safe alias/function command**: Use the escaped path from step 3
|
||||||
|
```bash
|
||||||
|
# CRITICAL: Use $ESCAPED_PATH in the command (not raw $VAULT_PATH)
|
||||||
|
if [ "$SHELL_TYPE" = "fish" ]; then
|
||||||
|
# Fish uses function syntax, not alias
|
||||||
|
COMMAND_TEXT="function claudesidian
|
||||||
|
cd \"$ESCAPED_PATH\" && (claude --resume 2>/dev/null; or claude)
|
||||||
|
cd -
|
||||||
|
end"
|
||||||
|
else
|
||||||
|
# Bash/Zsh use alias syntax
|
||||||
|
# IMPORTANT: Use double quotes around $ESCAPED_PATH to preserve escaping
|
||||||
|
COMMAND_TEXT="alias claudesidian='(cd \"$ESCAPED_PATH\" && (claude --resume 2>/dev/null || claude))'"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
8. **Remove old command if replacing**:
|
||||||
|
```bash
|
||||||
|
if [ "$REPLACING" = true ]; then
|
||||||
|
# Remove old alias/function before adding new one
|
||||||
|
sed -i.tmp '/alias claudesidian\|function claudesidian/,/^end$/d' "$CONFIG_FILE"
|
||||||
|
rm -f "$CONFIG_FILE.tmp"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
9. **Add command to config file**: Append using the escaped command text
|
||||||
|
```bash
|
||||||
|
echo "$COMMAND_TEXT" >> "$CONFIG_FILE"
|
||||||
|
```
|
||||||
|
10. **Show success message**: With instructions to reload shell
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
**Bash/Zsh Example (with spaces in path to demonstrate escaping):**
|
||||||
|
|
||||||
|
```
|
||||||
|
🔧 Installing claudesidian command...
|
||||||
|
|
||||||
|
📁 Vault path: /home/user/My Obsidian Vault
|
||||||
|
🐚 Shell detected: zsh
|
||||||
|
📝 Config file: /home/user/.zshrc
|
||||||
|
|
||||||
|
💾 Backup created: /home/user/.zshrc.backup-20250107-143025
|
||||||
|
|
||||||
|
✅ Installed! Added to /home/user/.zshrc:
|
||||||
|
alias claudesidian='(cd "/home/user/My Obsidian Vault" && (claude --resume 2>/dev/null || claude))'
|
||||||
|
|
||||||
|
🔄 To activate, run:
|
||||||
|
source ~/.zshrc
|
||||||
|
|
||||||
|
Or start a new terminal session.
|
||||||
|
|
||||||
|
✨ Test it: Type 'claudesidian' from any directory!
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fish Shell Example:**
|
||||||
|
|
||||||
|
```
|
||||||
|
🔧 Installing claudesidian command...
|
||||||
|
|
||||||
|
📁 Vault path: /home/user/My Obsidian Vault
|
||||||
|
🐚 Shell detected: fish
|
||||||
|
📝 Config file: /home/user/.config/fish/config.fish
|
||||||
|
|
||||||
|
💾 Backup created: /home/user/.config/fish/config.fish.backup-20250107-143025
|
||||||
|
|
||||||
|
✅ Installed! Added to /home/user/.config/fish/config.fish:
|
||||||
|
function claudesidian
|
||||||
|
cd "/home/user/My Obsidian Vault" && (claude --resume 2>/dev/null; or claude)
|
||||||
|
cd -
|
||||||
|
end
|
||||||
|
|
||||||
|
🔄 To activate, run:
|
||||||
|
source ~/.config/fish/config.fish
|
||||||
|
|
||||||
|
Or start a new terminal session.
|
||||||
|
|
||||||
|
✨ Test it: Type 'claudesidian' from any directory!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Handling Special Characters
|
||||||
|
|
||||||
|
The implementation properly handles paths with:
|
||||||
|
|
||||||
|
- Spaces: `/Users/noah/My Vault`
|
||||||
|
- Quotes: `/Users/noah/vault's backup`
|
||||||
|
- Special characters that need escaping
|
||||||
|
|
||||||
|
Paths are double-quoted and any embedded quotes/backslashes are escaped.
|
||||||
|
|
||||||
|
## Fish Shell Support
|
||||||
|
|
||||||
|
Fish shell uses different syntax than Bash/Zsh:
|
||||||
|
|
||||||
|
**Bash/Zsh (alias):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
alias claudesidian='(cd "/path" && command)'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fish (function):**
|
||||||
|
|
||||||
|
```fish
|
||||||
|
function claudesidian
|
||||||
|
cd "/path" && (command; or fallback)
|
||||||
|
cd -
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Key differences:
|
||||||
|
|
||||||
|
- Fish uses `function` keyword instead of `alias` for complex commands
|
||||||
|
- Fish uses `; or` instead of `||` for fallback logic
|
||||||
|
- Fish uses `cd -` to return to previous directory (instead of subshell)
|
||||||
|
- Multi-line function definition instead of single-line alias
|
||||||
|
|
||||||
|
The installation automatically detects Fish and uses the correct syntax.
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
This command modifies your shell configuration file (a sensitive operation).
|
||||||
|
Safety measures:
|
||||||
|
|
||||||
|
- **You'll see exactly what will be added** before any changes
|
||||||
|
- **Timestamped backup is automatically created** before modification
|
||||||
|
- **Vault path is properly escaped** to prevent injection attacks
|
||||||
|
- **Only the claudesidian command is modified** - nothing else in your config
|
||||||
|
- **Asks permission** before replacing existing commands
|
||||||
|
|
||||||
|
If anything goes wrong, restore from: `$CONFIG_FILE.backup-YYYYMMDD-HHMMSS`
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
- The command uses a subshell `()` (or `cd -` in Fish) so it returns to your
|
||||||
|
original directory after
|
||||||
|
- Automatically tries to resume existing sessions, falls back to new session
|
||||||
|
- If alias/function already exists, asks user if they want to replace it
|
||||||
|
- Always shows what will be added before modifying config files
|
||||||
|
- **Always creates timestamped backup** of config file before modifying (format:
|
||||||
|
`YYYYMMDD-HHMMSS`)
|
||||||
|
- Backups are kept indefinitely - users can manually clean up old backups if
|
||||||
|
needed
|
||||||
|
- Shows backup location so users know where to restore from if needed
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
Install for your default shell (auto-detected):
|
||||||
|
|
||||||
|
```
|
||||||
|
/install-claudesidian-command
|
||||||
|
```
|
||||||
|
|
||||||
|
Install for specific shell (override auto-detection):
|
||||||
|
|
||||||
|
```
|
||||||
|
/install-claudesidian-command zsh
|
||||||
|
/install-claudesidian-command bash
|
||||||
|
/install-claudesidian-command fish
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to specify shell:**
|
||||||
|
|
||||||
|
- You use multiple shells and want to install for a specific one
|
||||||
|
- Auto-detection picked the wrong shell
|
||||||
|
- You're setting up for someone else
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
**Bash/Zsh (alias with subshell):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
alias claudesidian='(cd "/path/to/vault" && (claude --resume 2>/dev/null || claude))'
|
||||||
|
```
|
||||||
|
|
||||||
|
1. `(cd "/path/to/vault" && ...)` - Subshell that changes directory temporarily
|
||||||
|
(path is double-quoted for safety)
|
||||||
|
2. `claude --resume 2>/dev/null` - Tries to resume existing session, suppresses
|
||||||
|
error
|
||||||
|
3. `|| claude` - If resume fails (no session), starts new session
|
||||||
|
4. After Claude exits, subshell closes and returns to original directory
|
||||||
|
automatically
|
||||||
|
|
||||||
|
**Fish (function with cd -):**
|
||||||
|
|
||||||
|
```fish
|
||||||
|
function claudesidian
|
||||||
|
cd "/path/to/vault" && (claude --resume 2>/dev/null; or claude)
|
||||||
|
cd -
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
1. `cd "/path/to/vault"` - Changes to vault directory (path is double-quoted for
|
||||||
|
safety)
|
||||||
|
2. `claude --resume 2>/dev/null` - Tries to resume existing session, suppresses
|
||||||
|
error
|
||||||
|
3. `; or claude` - If resume fails (no session), starts new session (Fish
|
||||||
|
syntax)
|
||||||
|
4. `cd -` - Returns to previous directory after Claude exits
|
||||||
@@ -152,6 +152,8 @@ Pre-configured AI assistants ready to use:
|
|||||||
- `de-ai-ify` - Remove AI writing patterns from text
|
- `de-ai-ify` - Remove AI writing patterns from text
|
||||||
- `upgrade` - Update to the latest claudesidian version
|
- `upgrade` - Update to the latest claudesidian version
|
||||||
- `init-bootstrap` - Re-run the setup wizard
|
- `init-bootstrap` - Re-run the setup wizard
|
||||||
|
- `install-claudesidian-command` - Install shell command to launch vault from
|
||||||
|
anywhere
|
||||||
|
|
||||||
Run with: `/[command-name]` in Claude Code
|
Run with: `/[command-name]` in Claude Code
|
||||||
|
|
||||||
@@ -263,6 +265,34 @@ Run these with `pnpm`:
|
|||||||
|
|
||||||
## Advanced Setup
|
## Advanced Setup
|
||||||
|
|
||||||
|
### Quick Launch from Anywhere
|
||||||
|
|
||||||
|
Install a shell command to launch your vault from any directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Claude Code, run:
|
||||||
|
/install-claudesidian-command
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a `claudesidian` alias that:
|
||||||
|
|
||||||
|
- Changes to your vault directory automatically
|
||||||
|
- Tries to resume your existing session (if one exists)
|
||||||
|
- Falls back to starting a new session
|
||||||
|
- Returns to your original directory when done
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From anywhere in your terminal:
|
||||||
|
claudesidian
|
||||||
|
|
||||||
|
# It will automatically resume your last session or start a new one
|
||||||
|
```
|
||||||
|
|
||||||
|
The command is added to your shell config (~/.zshrc, ~/.bashrc, etc.) so it
|
||||||
|
persists across terminal sessions.
|
||||||
|
|
||||||
### Git Integration
|
### Git Integration
|
||||||
|
|
||||||
Initialize Git for version control:
|
Initialize Git for version control:
|
||||||
|
|||||||
Reference in New Issue
Block a user