How to Manage Ollama Models (Download, Delete, List) in Project N.O.M.A.D.
Project N.O.M.A.D. provides REST endpoints to list, download, and delete Ollama models via the OllamaController and OllamaService, with downloads processed as background jobs that stream progress to the UI.
Project N.O.M.A.D. (Networked Operations Management and Deployment) is an open-source platform that wraps the Ollama container with a full-stack AdonisJS API. This guide explains how to manage Ollama models in Project N.O.M.A.D. using the built-in HTTP endpoints and underlying service architecture.
Core Architecture
The model management system follows a layered architecture with clear separation between HTTP handling, business logic, and background processing.
Controller Layer
The OllamaController at admin/app/controllers/ollama_controller.ts handles all HTTP requests under the /api/ollama route prefix defined in admin/start/routes.ts. It exposes four primary actions:
availableModels– Validates requests usinggetAvailableModelsSchemaand delegates toOllamaService.getAvailableModels()installedModels– Returns locally installed models viaOllamaService.getModels()dispatchModelDownload– Validates model names and enqueuesDownloadModelJobthroughOllamaService.dispatchModelDownload()deleteModel– Validates input and callsOllamaService.deleteModel()to remove models
Service Layer
The OllamaService in admin/app/services/ollama_service.ts manages the Ollama client lifecycle and implements all model operations:
- Client Initialization – Lazily creates an
Ollamaclient instance pointing to the Docker container URL - Remote Model Listing –
getAvailableModels()retrieves data from the Nomad API, caches results instorage/ollama-models-cache.json, and applies Fuse.js fuzzy search - Local Model Listing –
getModels()callsollama.list()and filters out embedding models - Download Management –
downloadModel()streams pull progress whiledispatchModelDownload()enqueues background jobs - Deletion –
deleteModel()forwards requests toollama.delete({ model })
Background Jobs and Broadcasting
Downloads run asynchronously via DownloadModelJob in admin/app/jobs/download_model_job.ts. The service broadcasts real-time progress via broadcastDownloadProgress() on the BROADCAST_CHANNELS.OLLAMA_MODEL_DOWNLOAD channel (defined in admin/constants/broadcast.ts), enabling Server-Sent Events (SSE) updates in the UI.
API Endpoints for Model Management
List Available Remote Models
Query the Nomad registry for downloadable models with optional filtering and sorting.
import axios from 'axios';
const response = await axios.get('/api/ollama/models', {
params: {
sort: 'pulls', // Sort by popularity
recommendedOnly: false,
query: 'llama', // Fuzzy search term
limit: 15,
force: false // Bypass cache if true
}
});
// Returns: { models: NomadOllamaModel[], hasMore: boolean }
The OllamaService.getAvailableModels() method checks storage/ollama-models-cache.json first, refreshing every 24 hours unless force=true.
List Installed Models
Retrieve models currently available in the local Ollama container.
const { data } = await axios.get('/api/ollama/installed-models');
// Returns array of installed model objects (embeddings excluded)
This endpoint calls OllamaService.getModels(includeEmbeddings = false), which wraps the native ollama.list() command.
Download a Model
Initiate a background download by posting the model name.
const { data } = await axios.post('/api/ollama/models', {
model: 'qwen2.5:3b'
});
// Response: { message: "Download job dispatched for qwen2.5:3b" }
The dispatchModelDownload() method enqueues DownloadModelJob, which executes downloadModel() to stream the pull from ollama.pull({ model, stream: true }).
Delete a Model
Remove a model from the local Ollama store.
const { data } = await axios.delete('/api/ollama/models', {
data: { model: 'qwen2.5:3b' }
});
// Response: { message: "Model deleted: qwen2.5:3b" }
This triggers OllamaService.deleteModel(), which calls the Ollama client's delete method.
Implementation Details
Caching Strategy
Remote model lists are cached in storage/ollama-models-cache.json to minimize API calls. The cache automatically refreshes after 24 hours or immediately when the force parameter is set to true in the request.
Fallback Data
If the remote Nomad API is unavailable, the system uses FALLBACK_RECOMMENDED_OLLAMA_MODELS from admin/constants/ollama.ts to ensure the UI remains functional.
Type Safety
All model structures are defined in admin/types/ollama.ts, including NomadOllamaModel, NomadOllamaModelTag, and chat request/response interfaces. The controller uses Zod validators from admin/app/validators/ollama.ts for runtime request validation.
Client-Side Integration Examples
Monitoring Download Progress
Listen to SSE events for real-time download status:
const source = new EventSource('/api/ollama/models');
source.addEventListener('message', (event) => {
const { model, percent, completed, total } = JSON.parse(event.data);
console.log(`Downloading ${model}: ${percent}% (${completed}/${total})`);
});
The OllamaService.broadcastDownloadProgress() method emits these events through the Transmit broadcasting layer.
Complete Model Management Workflow
class OllamaModelManager {
async listAvailable() {
return axios.get('/api/ollama/models');
}
async listInstalled() {
return axios.get('/api/ollama/installed-models');
}
async download(name: string) {
return axios.post('/api/ollama/models', { model: name });
}
async remove(name: string) {
return axios.delete('/api/ollama/models', { data: { model: name } });
}
}
Summary
- Listing – Use
GET /api/ollama/modelsfor remote registry data (with caching) andGET /api/ollama/installed-modelsfor local container models - Downloading –
POST /api/ollama/modelsenqueues background jobs viaDownloadModelJob, streaming progress throughBROADCAST_CHANNELS.OLLAMA_MODEL_DOWNLOAD - Deleting –
DELETE /api/ollama/modelsremoves models viaOllamaService.deleteModel() - Architecture – Clean separation between
OllamaController(HTTP),OllamaService(business logic), and background jobs for heavy operations
Frequently Asked Questions
How does Project N.O.M.A.D. handle large model downloads without blocking the API?
Downloads run asynchronously through DownloadModelJob in admin/app/jobs/download_model_job.ts. The controller immediately returns a success response after enqueueing the job, while the service streams download progress via Server-Sent Events on the OLLAMA_MODEL_DOWNLOAD broadcast channel.
Where does Project N.O.M.A.D. store the list of available Ollama models?
Remote model metadata is cached in storage/ollama-models-cache.json on the server. The OllamaService.getAvailableModels() method checks this file first and refreshes it every 24 hours or when the force parameter is specified.
Can I filter or search through available models in the API?
Yes. The GET /api/ollama/models endpoint accepts a query parameter that triggers Fuse.js fuzzy searching in OllamaService.getAvailableModels(). You can also filter by recommendedOnly and sort results by pulls or other criteria.
What happens if the remote Nomad API is unavailable when listing models?
The system falls back to FALLBACK_RECOMMENDED_OLLAMA_MODELS defined in admin/constants/ollama.ts, ensuring the model selection UI remains functional even during network outages.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →