fix: plugin cannot be installed — manifest path, deps, and install script

- manifest.json: fix 'main' from 'src/main.js' to 'dist/main.js'
  (TypeScript compiles to dist/, not src/ — Obsidian could not find the entry point)
- manifest.json: set isDesktopOnly to true (plugin requires a local Ollama server)
- package.json: remove unused node-fetch dependency (ESM-only, conflicts with CommonJS build)
- src/semantic-cache.ts: use dynamic import for chromadb instead of top-level import
  (prevents plugin load crash when chromadb is not installed; cache defaults to disabled)
- install.sh: new script that installs deps, builds, and copies the plugin into a vault
- README.md: add quick install, manual install, and expanded troubleshooting sections
This commit is contained in:
2026-05-19 17:39:10 +02:00
parent 26d86d01db
commit 378642152e
5 changed files with 192 additions and 23 deletions
+49 -9
View File
@@ -11,11 +11,6 @@ A plugin that integrates [Ollama](https://ollama.ai) with Obsidian, allowing you
- Semantic response cache — repeated or similar queries are answered instantly without hitting the model (requires ChromaDB)
- Customisable model, URL, and cache settings
## Installation
1. Install the plugin via Obsidian's community plugins
2. Make sure you have Ollama installed and running
## Prerequisites
1. **Install Ollama**: Follow the instructions at [ollama.ai](https://ollama.ai)
@@ -40,14 +35,58 @@ The semantic cache stores responses in a local [ChromaDB](https://www.trychroma.
```
4. Enable the cache in the plugin settings and configure the ChromaDB URL.
## Installation
### Quick install (recommended)
Use the included install script. It handles dependency installation, building, and copying the plugin into your vault:
```bash
# Clone or download this repository, then run:
./install.sh /path/to/your/obsidian/vault
```
The script will:
- Install npm dependencies (excluding Ollama — you install that separately)
- Compile the TypeScript plugin
- Copy the built plugin into `<vault>/.obsidian/plugins/ollama-plugin/`
### Manual install
If you prefer to install manually:
```bash
npm install
npm run build
```
Then copy the plugin into your vault:
```bash
mkdir -p /path/to/vault/.obsidian/plugins/ollama-plugin
cp manifest.json /path/to/vault/.obsidian/plugins/ollama-plugin/
cp -r dist /path/to/vault/.obsidian/plugins/ollama-plugin/
cp -r node_modules/chromadb /path/to/vault/.obsidian/plugins/ollama-plugin/node_modules/ # optional: only needed for semantic cache
```
> **Note:** The `obsidian` npm package is a dev-only type stub — Obsidian provides its own API at runtime. The `chromadb` package is only needed if you enable the semantic cache feature.
### After installation
1. Restart Obsidian (or reload: `Ctrl+Shift+P` → "Reload app without saving")
2. Go to **Settings → Community plugins** → enable **Ollama Plugin**
3. Configure the plugin at **Settings → Ollama Settings**
## Configuration
Open **Settings → Ollama Chat** to configure the plugin.
Open **Settings → Ollama Settings** to configure the plugin.
| Setting | Default | Description |
|-----|- -- ----|-------|
|---------|---------|-------------|
| Ollama URL | `http://localhost:11434` | Base URL of your Ollama instance |
| Model | `llama3` | Model used for chat responses |
| Vault Search Limit | `3` | Maximum number of vault entries to include in context |
| Max Message History | `50` | Maximum number of messages kept in conversation history |
| Enable Semantic Cache | Off | Cache responses for fast repeated queries |
| ChromaDB URL | `http://localhost:8000` | URL of your running ChromaDB instance |
| Cache Embedding Model | `nomic-embed-text` | Ollama model used to generate cache embeddings |
@@ -56,7 +95,7 @@ Open **Settings → Ollama Chat** to configure the plugin.
## Usage
1. Click the ribbon icon to open the chat view
1. Open the chat view via the command palette (`Ctrl+P` → "Open Ollama Chat") or the ribbon icon
2. Type your message in the input box
3. Press **Enter** or click **Send** to send your message
4. Press **Shift+Enter** to insert a line break
@@ -104,7 +143,8 @@ npm test
## Troubleshooting
| Symptom | Likely cause | Fix |
|-----|- -----|---|
|---------|-------------|-----|
| Plugin doesn't appear in Obsidian | Install script was not run or failed | Run `./install.sh /path/to/vault` and reload Obsidian |
| Cannot connect to Ollama | Ollama is not running | Run `ollama serve` |
| Model not found | Model not pulled | Run `ollama pull <model>` |
| Semantic cache unavailable (notice shown) | ChromaDB is not running, or the ChromaDB URL is wrong | Start ChromaDB (`chroma run`) and verify the URL in settings |
Executable
+133
View File
@@ -0,0 +1,133 @@
#!/usr/bin/env bash
#
# install.sh — Install the Ollama Plugin into an Obsidian vault
#
# Usage:
# ./install.sh /path/to/your/vault
#
# The script will:
# 1. Install npm dependencies (excluding Ollama itself — you need that separately)
# 2. Compile the TypeScript plugin
# 3. Copy the built plugin into <vault>/.obsidian/plugins/ollama-plugin/
#
# Prerequisites:
# - Node.js and npm
# - Ollama installed and running (https://ollama.ai)
#
set -euo pipefail
# ── Helpers ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BOLD='\033[1m'
NC='\033[0m' # No Color
info() { printf "${GREEN}${NC} %s\n" "$1"; }
warn() { printf "${YELLOW}${NC} %s\n" "$1"; }
error() { printf "${RED}${NC} %s\n" "$1"; }
step() { printf "\n${BOLD}══ %s ══${NC}\n" "$1"; }
# ── Argument validation ──────────────────────────────────────────────────────
VAULT_PATH="${1:-}"
if [ -z "$VAULT_PATH" ]; then
echo "Usage: ./install.sh /path/to/your/vault"
echo ""
echo " Provide the path to your Obsidian vault directory."
echo " The plugin will be installed into <vault>/.obsidian/plugins/ollama-plugin/"
exit 1
fi
if [ ! -d "$VAULT_PATH" ]; then
error "Vault directory does not exist: $VAULT_PATH"
exit 1
fi
if [ ! -d "$VAULT_PATH/.obsidian" ]; then
warn "No .obsidian folder found in $VAULT_PATH — this may not be a valid Obsidian vault."
warn "Continuing anyway, but the plugin may not load."
fi
PLUGIN_DIR="$VAULT_PATH/.obsidian/plugins/ollama-plugin"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# ── Check prerequisites ──────────────────────────────────────────────────────
step "Checking prerequisites"
if ! command -v node &> /dev/null; then
error "Node.js is required but not found. Install it from https://nodejs.org"
exit 1
fi
info "Node.js $(node --version)"
if ! command -v npm &> /dev/null; then
error "npm is required but not found."
exit 1
fi
info "npm $(npm --version)"
# ── Install dependencies ─────────────────────────────────────────────────────
step "Installing npm dependencies"
cd "$SCRIPT_DIR"
npm install --production
info "Dependencies installed"
# ── Build ────────────────────────────────────────────────────────────────────
step "Building the plugin"
npm run build
info "Build complete"
# ── Install into vault ───────────────────────────────────────────────────────
step "Installing into vault"
mkdir -p "$PLUGIN_DIR"
# Copy manifest and built output
cp "$SCRIPT_DIR/manifest.json" "$PLUGIN_DIR/"
cp -r "$SCRIPT_DIR/dist" "$PLUGIN_DIR/"
# Copy only necessary runtime dependencies (obsidian and chromadb stubs)
# The obsidian package is only used for type definitions at build time —
# at runtime Obsidian provides its own API, so we don't need it in node_modules.
# chromadb is loaded dynamically and only needed when the cache is enabled.
mkdir -p "$PLUGIN_DIR/node_modules"
if [ -d "$SCRIPT_DIR/node_modules/chromadb" ]; then
cp -r "$SCRIPT_DIR/node_modules/chromadb" "$PLUGIN_DIR/node_modules/"
fi
info "Plugin installed to $PLUGIN_DIR"
# ── Verify ────────────────────────────────────────────────────────────────────
step "Verifying installation"
if [ -f "$PLUGIN_DIR/manifest.json" ] && [ -f "$PLUGIN_DIR/dist/main.js" ]; then
info "manifest.json ✓"
info "dist/main.js ✓"
else
error "Installation verification failed — missing files in $PLUGIN_DIR"
exit 1
fi
echo ""
echo " ${GREEN}${BOLD}Done!${NC} The plugin has been installed."
echo ""
echo " Next steps:"
echo " 1. Restart Obsidian (or reload plugins: Ctrl+Shift+P → 'Reload app without saving')"
echo " 2. Go to Settings → Community plugins → enable 'Ollama Plugin'"
echo " 3. Configure the plugin: Settings → Ollama Settings"
echo ""
echo " Make sure Ollama is running:"
echo " ollama serve"
echo " ollama pull llama3 (or your preferred model)"
echo ""
+1 -1
View File
@@ -6,7 +6,7 @@
"description": "Ollama integration plugin for Obsidian",
"author": "Anonymous",
"authorUrl": "",
"isDesktopOnly": false,
"isDesktopOnly": true,
"main": "dist/main.js",
"authorization": [],
"permissions": [],
-1
View File
@@ -33,7 +33,6 @@
},
"dependencies": {
"chromadb": "^1.5.3",
"node-fetch": "^3.3.2",
"obsidian": "^1.4.11"
}
}
+8 -11
View File
@@ -1,13 +1,11 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
/* eslint-disable */
// src/semantic-cache.ts
import { ChromaClient } from 'chromadb';
import { Logger } from './utils';
import { CacheConfig } from './types';
export class SemanticCacheService {
private client: ChromaClient;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private client: any | null = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private collection: any | null = null;
private config: CacheConfig;
@@ -16,15 +14,17 @@ export class SemanticCacheService {
constructor(ollamaURL: string, config: CacheConfig) {
this.ollamaURL = ollamaURL.replace(/\/+$/, '');
this.config = config;
// Use configurable ChromaDB URL or default to localhost
const chromaURL = config.chromaURL || 'http://localhost:8000';
this.client = new ChromaClient({ path: chromaURL });
}
async initialize(): Promise<void> {
if (!this.config.enabled) return;
try {
// Dynamic import — chromadb is optional and may not be installed.
// This prevents the plugin from crashing at load time if chromadb is absent.
const { ChromaClient } = await import('chromadb');
const chromaURL = this.config.chromaURL || 'http://localhost:8000';
this.client = new ChromaClient({ path: chromaURL });
this.collection = await this.client.getOrCreateCollection({
name: this.config.collectionName,
metadata: { 'hnsw:space': 'cosine' },
@@ -49,11 +49,8 @@ export class SemanticCacheService {
});
if (results.ids[0] && results.ids[0].length > 0) {
const [id] = results.ids[0];
const [content] = results.documents[0];
if (results.distances[0] && results.distances[0][0] > this.config.similarityThreshold) {
return content;
return results.documents[0][0];
}
}