#!/bin/bash # Script to build, install, and start Obsidian with the Scriptorium plugin # Usage: ./start-obsidian.sh [path-to-obsidian-vault] # On first run, path is required. Subsequent runs will use the saved path. set -e # Exit on error # Function to show help show_help() { cat << EOF Scriptorium Nostr - Obsidian Plugin Startup Script USAGE: $0 [OPTIONS] [vault-path] OPTIONS: -h, --help Show this help message --generate-key Generate a new Nostr private key ARGUMENTS: vault-path Path to your Obsidian vault folder Required on first run, optional afterwards EXAMPLES: $0 ~/Documents/MyVault # First run $0 # Use saved vault path $0 --generate-key # Generate new Nostr key $0 --help # Show this help WHAT THIS SCRIPT DOES: 1. Installs npm dependencies (if needed) 2. Builds the Scriptorium plugin 3. Installs plugin to your vault 4. Installs obsidian-asciidoc plugin (for .adoc files) 5. Starts Obsidian with console logging NOTES: • Vault path is saved after first run • obsidian-asciidoc is installed automatically • Plugin logs appear in this terminal • Press Ctrl+C to stop Obsidian EOF exit 0 } # Check for help flag if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then show_help fi # Check for generate-key flag GENERATE_KEY=false if [ "$1" = "--generate-key" ]; then GENERATE_KEY=true # Remove the flag from arguments shift fi # Get the directory where this script is located SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" VAULT_CONFIG_FILE="${SCRIPT_DIR}/.scriptorium-vault-path" # Function to check if a vault path is valid is_valid_vault_path() { local path="$1" # Empty path is invalid if [ -z "$path" ]; then return 1 fi # Check if path exists as a directory, or if parent directory exists (so we can create it) if [ -d "$path" ]; then return 0 elif [ -d "$(dirname "$path" 2>/dev/null)" ]; then # Parent exists, so we can create the vault directory return 0 fi return 1 } # Function to load saved vault path load_vault_path() { if [ -f "$VAULT_CONFIG_FILE" ]; then local saved_path=$(cat "$VAULT_CONFIG_FILE" | head -n 1 | tr -d '\n\r') if [ -n "$saved_path" ] && is_valid_vault_path "$saved_path"; then echo "$saved_path" return 0 fi fi return 1 } # Function to save vault path save_vault_path() { local path="$1" echo "$path" > "$VAULT_CONFIG_FILE" echo "[Scriptorium] Saved vault path to $VAULT_CONFIG_FILE" } # Function to generate a new Nostr private key generate_nostr_key() { echo "[Scriptorium] Generating new Nostr private key..." # Check if Node.js is available if ! command -v node &> /dev/null; then echo "Error: Node.js is required to generate a Nostr key" echo "Please install Node.js and try again" exit 1 fi # Generate key using Node.js and nostr-tools # We'll use a temporary script to generate the key local temp_script=$(mktemp) cat > "$temp_script" << 'NODE_SCRIPT' const { generatePrivateKey, getPublicKey } = require('nostr-tools'); const { nip19 } = require('nostr-tools'); try { // Generate a new private key (32 bytes, hex encoded) const privkey = generatePrivateKey(); // Get the public key to verify const pubkey = getPublicKey(privkey); // Encode as nsec1 (bech32) const nsec = nip19.nsecEncode(privkey); const npub = nip19.npubEncode(pubkey); // Output both formats console.log(JSON.stringify({ nsec: nsec, hex: privkey, npub: npub, pubkey: pubkey })); } catch (error) { console.error(JSON.stringify({ error: error.message })); process.exit(1); } NODE_SCRIPT # Run the script local key_data=$(node "$temp_script" 2>/dev/null) rm -f "$temp_script" if [ -z "$key_data" ] || echo "$key_data" | grep -q '"error"'; then echo "Error: Failed to generate Nostr key" echo "Make sure nostr-tools is installed: npm install" exit 1 fi # Parse the JSON output local nsec=$(echo "$key_data" | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log(d.nsec)") local npub=$(echo "$key_data" | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log(d.npub)") echo "" echo "Generated new Nostr key:" echo " Public key (npub): $npub" echo "" echo "To use this key, add to your shell profile (~/.bashrc, ~/.zshrc, etc.):" echo "" echo " export SCRIPTORIUM_OBSIDIAN_KEY=\"$nsec\"" echo "" echo "Then restart your shell or run: source ~/.bashrc" echo "" echo "⚠️ Keep your private key secure! Do not share it with anyone." } # If generating key, handle it separately (no vault path needed) if [ "$GENERATE_KEY" = true ]; then cd "$SCRIPT_DIR" generate_nostr_key exit 0 fi # Determine vault path VAULT_PATH="" # If path is provided as argument, use it if [ -n "$1" ]; then VAULT_PATH="$1" # Expand ~ and resolve relative paths VAULT_PATH=$(eval echo "$VAULT_PATH") # Try to resolve to absolute path if [ -d "$VAULT_PATH" ]; then VAULT_PATH=$(cd "$VAULT_PATH" && pwd) elif [ -d "$(dirname "$VAULT_PATH")" ]; then # Parent exists, resolve parent and append basename VAULT_PATH=$(cd "$(dirname "$VAULT_PATH")" && pwd)/$(basename "$VAULT_PATH") else # Can't resolve, use as-is VAULT_PATH="$VAULT_PATH" fi # Validate provided path if ! is_valid_vault_path "$VAULT_PATH"; then echo "Error: Invalid vault path: $VAULT_PATH" echo "Please provide a valid path to your Obsidian vault folder" exit 1 fi # Save the path for next time save_vault_path "$VAULT_PATH" echo "[Scriptorium] Using vault path: $VAULT_PATH" else # Try to load saved path # Use || true to prevent set -e from exiting if load_vault_path fails SAVED_PATH=$(load_vault_path || true) if [ -n "$SAVED_PATH" ]; then # Re-validate the saved path if is_valid_vault_path "$SAVED_PATH"; then VAULT_PATH="$SAVED_PATH" echo "[Scriptorium] Using saved vault path: $VAULT_PATH" else echo "Error: Saved vault path is no longer valid: $SAVED_PATH" echo "" echo "Please provide a new vault path:" echo " $0 ~/Documents/MyVault" echo "" echo "Run '$0 --help' for more information" exit 1 fi else echo "Error: No vault path provided" echo "" echo "First run requires a vault path:" echo " $0 ~/Documents/MyVault" echo "" echo "The path will be saved for future runs." echo "Run '$0 --help' for more information" exit 1 fi fi # Final validation if [ -z "$VAULT_PATH" ]; then echo "Error: Could not determine vault path" exit 1 fi OBSIDIAN_FOLDER="${VAULT_PATH}/.obsidian" PLUGIN_FOLDER="${OBSIDIAN_FOLDER}/plugins/scriptorium-obsidian" # Change to script directory cd "$SCRIPT_DIR" echo "[Scriptorium] Starting build and install process..." echo "[Scriptorium] Vault path: $VAULT_PATH" echo "[Scriptorium] Plugin folder: $PLUGIN_FOLDER" # Check if npm dependencies need to be installed if [ ! -d "node_modules" ] || [ "package.json" -nt "node_modules" ]; then echo "Installing dependencies..." npm install --silent if [ $? -ne 0 ]; then echo "Error: npm install failed" exit 1 fi echo "✓ Dependencies installed" else echo "✓ Dependencies up to date" fi # Create necessary directories mkdir -p "$PLUGIN_FOLDER" # Build the plugin echo "Building plugin..." npm run build --silent 2>&1 | grep -v "^$" || true # Check if build was successful if [ ! -f "main.js" ] || [ ! -f "manifest.json" ]; then echo "Error: Build failed - main.js or manifest.json not found" exit 1 fi # Copy plugin files cp "main.js" "${PLUGIN_FOLDER}/main.js" cp "manifest.json" "${PLUGIN_FOLDER}/manifest.json" echo "✓ Plugin installed" # Function to enable a plugin in Obsidian enable_plugin() { local plugin_id="$1" local plugins_json="${OBSIDIAN_FOLDER}/community-plugins.json" # Create plugins JSON file if it doesn't exist if [ ! -f "$plugins_json" ]; then echo "[]" > "$plugins_json" fi # Check if plugin is already enabled if grep -q "\"$plugin_id\"" "$plugins_json" 2>/dev/null; then return 0 fi # Add plugin to enabled list using Node.js or Python if command -v node &> /dev/null; then # Use Node.js to update JSON node << NODE_SCRIPT const fs = require('fs'); const pluginsJson = '${plugins_json}'; let plugins = []; try { const content = fs.readFileSync(pluginsJson, 'utf8'); plugins = JSON.parse(content); } catch (e) { plugins = []; } if (!Array.isArray(plugins)) { plugins = []; } if (!plugins.includes('${plugin_id}')) { plugins.push('${plugin_id}'); fs.writeFileSync(pluginsJson, JSON.stringify(plugins, null, 2)); console.log('Enabled plugin: ${plugin_id}'); } NODE_SCRIPT if [ $? -ne 0 ]; then echo "Warning: Could not enable plugin $plugin_id automatically" fi elif command -v python3 &> /dev/null; then # Fallback to Python python3 << PYTHON_SCRIPT import json import os plugins_json = '${plugins_json}' plugin_id = '${plugin_id}' try: with open(plugins_json, 'r') as f: plugins = json.load(f) except: plugins = [] if not isinstance(plugins, list): plugins = [] if plugin_id not in plugins: plugins.append(plugin_id) with open(plugins_json, 'w') as f: json.dump(plugins, f, indent=2) print(f'Enabled plugin: {plugin_id}') PYTHON_SCRIPT if [ $? -ne 0 ]; then echo "Warning: Could not enable plugin $plugin_id automatically" fi else echo "Warning: Node.js or Python3 required to auto-enable plugins" echo "Please enable $plugin_id manually in Obsidian settings" fi } # Enable scriptorium-obsidian plugin enable_plugin "scriptorium-obsidian" > /dev/null 2>&1 # Install obsidian-asciidoc plugin (required for .adoc file support) ASCIIDOC_PLUGIN_DIR="${OBSIDIAN_FOLDER}/plugins/obsidian-asciidoc" ASCIIDOC_PLUGIN_REPO="https://github.com/dzruyk/obsidian-asciidoc.git" echo "Installing obsidian-asciidoc plugin..." if [ -d "$ASCIIDOC_PLUGIN_DIR" ]; then cd "$ASCIIDOC_PLUGIN_DIR" if [ -d ".git" ]; then git pull --quiet 2>/dev/null || true if [ -f "package.json" ]; then npm install --silent > /dev/null 2>&1 && npm run build --silent > /dev/null 2>&1 || true fi fi cd "$SCRIPT_DIR" ASCIIDOC_PLUGIN_ID=$(node -e "const m=require('${ASCIIDOC_PLUGIN_DIR}/manifest.json'); console.log(m.id)" 2>/dev/null || echo "obsidian-asciidoc") enable_plugin "$ASCIIDOC_PLUGIN_ID" > /dev/null 2>&1 echo "✓ obsidian-asciidoc plugin ready" else if command -v git &> /dev/null; then git clone --quiet "$ASCIIDOC_PLUGIN_REPO" "$ASCIIDOC_PLUGIN_DIR" 2>/dev/null || { echo "Error: Could not clone obsidian-asciidoc plugin" echo "Make sure git is installed and you have internet access" exit 1 } if [ -d "$ASCIIDOC_PLUGIN_DIR" ]; then cd "$ASCIIDOC_PLUGIN_DIR" if [ -f "package.json" ]; then npm install --silent > /dev/null 2>&1 && npm run build --silent > /dev/null 2>&1 || { echo "Error: Could not build obsidian-asciidoc plugin" exit 1 } fi cd "$SCRIPT_DIR" if [ -f "${ASCIIDOC_PLUGIN_DIR}/main.js" ] && [ -f "${ASCIIDOC_PLUGIN_DIR}/manifest.json" ]; then ASCIIDOC_PLUGIN_ID=$(node -e "const m=require('${ASCIIDOC_PLUGIN_DIR}/manifest.json'); console.log(m.id)" 2>/dev/null || echo "obsidian-asciidoc") enable_plugin "$ASCIIDOC_PLUGIN_ID" > /dev/null 2>&1 echo "✓ obsidian-asciidoc plugin installed" else echo "Error: Plugin files not found after installation" exit 1 fi fi else echo "Error: git is required to install obsidian-asciidoc plugin" exit 1 fi fi # Start Obsidian echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo " Starting Obsidian..." echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" # Try to find Obsidian command if command -v obsidian &> /dev/null; then obsidian "$VAULT_PATH" & echo "Obsidian started (PID: $!)" echo "Plugin logs will appear in this terminal" echo "Press Ctrl+C to stop" wait elif command -v flatpak &> /dev/null && flatpak list | grep -q "md.obsidian"; then flatpak run md.obsidian.Obsidian "$VAULT_PATH" & echo "Obsidian started via Flatpak (PID: $!)" echo "Plugin logs will appear in this terminal" echo "Press Ctrl+C to stop" wait else echo "Error: Could not find Obsidian" echo "Please install Obsidian or start manually:" echo " obsidian \"$VAULT_PATH\"" exit 1 fi