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
+50 -10
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 |
@@ -141,4 +181,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
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];
}
}