Run ImageJ directly in your browser - no installation, no server, just powerful image analysis anywhere.
ImageJ.JS brings the full power of ImageJ to the web, enabling professional image analysis on any device with a modern browser. Originally created during a hackathon in Dresden and evolved through the ImJoy project, ImageJ.JS now serves 1,000-1,500 unique users daily for scientific image analysis, education, and research.
The new version is now available at https://ij.aicell.io
If you want to try our previous version: https://ij.imjoy.io
This is a complete reimagining of ImageJ.JS, powered by CheerpJ 3 - a breakthrough WebAssembly compiler that runs Java applications directly in your browser without any preprocessing. This unlocks capabilities that were impossible in previous versions:
- ❌ 4GB file size limit - Could not handle large microscopy datasets
- ❌ Limited plugin support - Most ImageJ plugins required extensive modifications
- ❌ No local file access - Files had to be manually uploaded and downloaded
- ❌ Pre-compilation required - Every Java class needed conversion before use
- ✅ No file size limits - Process files larger than available memory
- ✅ Universal plugin support - Load any ImageJ plugin (MorphoLibJ, ThunderSTORM, etc.) without modification
- ✅ Direct file system access - Read and write files directly from your computer (Chrome/Edge)
- ✅ Zero compilation - Load JARs directly, just like desktop ImageJ
- ✅ AI-powered assistance - Connect to Large Language Models via Model Context Protocol
- ✅ GitHub plugin repositories - Share and load custom plugins via URL
- ✅ Better JavaScript integration - Call Java classes directly from JavaScript
Open ImageJ.JS in your browser and start analyzing images immediately - no software installation required. Works on:
- 💻 Desktop computers (Windows, Mac, Linux)
- 📱 Tablets and iPads - Full ImageJ interface optimized for touch
- 🌐 Any modern browser - Chrome, Edge, Safari, Firefox
Unlike other web apps that force you to upload files, ImageJ.JS can access your computer's folders directly:
- Click "Mount Local Folder" to give ImageJ access to a folder
- Open, process, and save images directly to your disk
- Changes appear instantly in your file explorer
- No file size limits, no uploads, no downloads
Perfect for: Large microscopy files, batch processing folders, real-time workflows
Create a shareable link that loads ImageJ with your custom plugins pre-installed:
https://ij.aicell.io/?mount=github:yourname/yourplugins@main&plugins.dir=/github/yourname/yourplugins@main/plugins
Anyone who opens this link gets ImageJ with your plugins ready to use!
Use cases:
- 🎓 Teaching - Share ImageJ with pre-configured plugins for students
- 🔬 Research - Distribute reproducible analysis pipelines
- 🤝 Collaboration - Share workflows without complicated setup
- 📦 Plugin development - Test plugins without local installation
See the Plugin Repository Guide →
Connect ImageJ.JS to AI assistants (ChatGPT, Claude, etc.) via the Model Context Protocol to:
- 💬 Describe what you want - AI generates ImageJ macros for you
- 📸 Show results - AI can see screenshots of your images
- 🧠 Learn from examples - Built-in knowledge base of working code
- 🔄 Iterate quickly - AI helps debug and refine your analysis
Example workflow:
- Open your image in ImageJ.JS
- Click "Connect to Hypha" and add to your AI assistant
- Tell the AI: "Segment the cells and measure their areas"
- AI generates and runs the macro automatically
- View results and refine as needed
Don't want to mount folders? Just drag files or folders from your computer directly into the browser window. They'll be available instantly at /local/ for processing.
Process images directly from public GitHub repositories without downloading:
https://ij.aicell.io/?mount=github:owner/repo@main
Files appear at /github/owner/repo/ in ImageJ's file dialogs.
Perfect for: Shared datasets, collaborative projects, public image databases, reproducible research
Seamlessly convert ImageJ ROIs to/from standard GeoJSON format:
- 📤 Export ROIs - Convert any ImageJ ROI (rectangle, polygon, ellipse, etc.) to GeoJSON
- 📥 Import ROIs - Load ROIs from GeoJSON into ImageJ and ROI Manager
- 🔄 Interoperability - Integrate with web mapping tools, QuPath, spatial databases
- 🤖 AI Integration - Let AI assistants create and modify ROIs using standard formats
Supported geometry types: Point, MultiPoint, LineString, Polygon, MultiPolygon, GeometryCollection
Learn more about ROI ↔ GeoJSON conversion →
- No installation barriers - Students start analyzing images in seconds
- Consistent environment - Everyone uses the exact same ImageJ version
- Pre-configured setups - Share URLs with plugins and datasets ready to go
- Cross-platform - Works on university computers, personal laptops, even iPads
- Version control - Store ImageJ plugins alongside your data in Git
- Shareable analysis - Send collaborators a single URL with everything needed
- Document workflows - Link to specific ImageJ configurations in papers
- Long-term preservation - Analysis stays accessible even if software evolves
- No file transfers - Work directly with files in shared GitHub repositories
- Universal access - Analyze images from anywhere with internet
- Real-time updates - Push plugin updates to GitHub, everyone gets them instantly
https://ij.aicell.io/?mount=github:university/microscopy-course@2024&plugins.dir=/github/university/microscopy-course@2024/plugins
- Repository contains sample images and custom plugins for exercises
- Students click the link and immediately have ImageJ ready
- No software installation or configuration required
- Professor updates examples by pushing to GitHub
https://ij.aicell.io/
- Mount your lab's shared network folder (Chrome/Edge)
- Process images with full file system integration
- Save results directly back to shared storage
- AI assistant helps write custom macros for your analysis
https://ij.aicell.io/?mount=github:yourlab/paper-2024@main&plugins.dir=/github/yourlab/paper-2024@main/plugins
- Share this URL in your presentation
- Audience can reproduce your analysis during the talk
- All data, plugins, and configurations are pre-loaded
- Works on conference WiFi, no installation needed
| Feature | Description | Browser Support |
|---|---|---|
| Drag & Drop | Drop files/folders into browser to process | All browsers |
| GitHub Integration | Access files and plugins from GitHub repos | All browsers |
| Plugin Support | Load any ImageJ/Fiji plugin without modification | All browsers |
| AI Assistant Integration | Connect to ChatGPT, Claude, etc. via MCP | All browsers |
| ROI ↔ GeoJSON | Export/import ROIs in standard GeoJSON format | All browsers |
| Large Files | No file size limits with mounted folders | All browsers |
| Mobile Support | Full ImageJ interface on tablets/iPads | All browsers |
| Offline Capable | IndexedDB storage for offline work | All browsers |
| Native Folder Access | Read/write files directly from your computer | Chrome, Edge |
This version includes several groundbreaking technical achievements:
- Multiple file systems running simultaneously:
- Native FS: Direct access to local folders via File System Access API
- GitHub FS: HTTP-based access to repositories with zero API calls using
index.listfiles - Local FS: In-memory storage for drag-and-drop files
- IndexedDB FS: Persistent browser storage for offline work
- Novel
index.listformat with type prefixes (dir:foldervsfile.jar) - Recursive validation ensures non-existent paths fail immediately
- HEAD requests only for files that exist in index
- No rate limiting issues, unlimited requests
Rich API for AI assistants and remote control:
Core Tools:
runMacro(macro)- Execute ImageJ macro codeexecuteJavaScript(code)- Direct Java API accesstakeScreenshot()- Capture visual resultsgetImageInfo(),listImages()- Query image state
Knowledge Base Tools:
searchCommands(query)- Find ImageJ commandslistExamples(category)- Browse working examplesreadExample(path)- Get full code examplessearchExamples(query)- Keyword searchsaveExample(path, content)- Contribute new examples
ROI & Analysis Tools:
getRoisAsGeoJson()- Export ROIs as GeoJSON FeatureCollectionsetRoisFromGeoJson()- Import ROIs from GeoJSON formatgetTextFromTable()- Extract measurement tables as textlistFiles(pattern)- List and read files from virtual file system
See full MCP API documentation → ROI ↔ GeoJSON Conversion Guide →
Deep integration with CheerpJ internals:
- Patched
IdbOpsfor custom file system routing - Patched
DirectDownloaderfor flexible HTTP handling - Patched
Interpreterfor silent macro execution - Dynamic Java-JavaScript interop via
window.lib
- Visit https://ij.aicell.io/ (or run locally)
- ImageJ loads automatically
- Start analyzing images!
- Create a GitHub repository with your plugins
- Add
index.listfiles (see guide) - Share this URL:
https://ij.aicell.io/?mount=github:you/repo@main&plugins.dir=/github/you/repo@main/plugins
# Clone repository
git clone https://github.com/imjoy-team/imagej.js2.git
cd imagej.js2
# Download ImageJ
sh prepare.sh
# Install dependencies
npm install
# Start dev server (supports Range headers)
npm run dev
# Open browser
open http://localhost:8000- Plugin Repository Setup - Host plugins on GitHub
- Knowledge Base Examples - Working code examples
- ROI ↔ GeoJSON Conversion - Export/import ROIs in standard format
- Browser Compatibility - What works where
- Technical Architecture - How it all works
- File System Implementation - Custom FS backends
- MCP API Reference - Remote control interface
- Debugging Tips - Troubleshooting guide
- Original Journey: CheerpJ 3 to 4.x - Early development story
- Chrome 86+ (Desktop) - All features including native folder mounting
- Edge 86+ (Desktop) - All features including native folder mounting
- Safari - No native folder mounting, use drag-and-drop or GitHub mounting
- Firefox - No native folder mounting, use drag-and-drop or GitHub mounting
- Mobile browsers - Full ImageJ functionality, limited file system features
| Feature | Chrome/Edge | Safari/Firefox | Mobile |
|---|---|---|---|
| Native Folder Mount | ✅ Full | ❌ | ❌ |
| Drag & Drop Files | ✅ Full | ✅ Full | |
| GitHub Repositories | ✅ Full | ✅ Full | ✅ Full |
| Plugin Support | ✅ Full | ✅ Full | ✅ Full |
| AI/MCP Integration | ✅ Full | ✅ Full | ✅ Full |
- ✅ Most ImageJ plugins (MorphoLibJ, ThunderSTORM, etc.)
- ✅ Batch processing with mounted folders
- ✅ Large file handling (>4GB) with native FS
- ✅ Real-time file system integration
⚠️ Performance: Worse than desktop due to WebAssembly overhead and also it only run in a single thread (although it appears that multi-thread in java can run through the cheerpj emulation)⚠️ Multi-threading: Limited by browser security (no shared memory)⚠️ Native libraries: Plugins requiring native code may not work⚠️ GitHub rate limits: Repositories withoutindex.listfiles hit API limits
- 💡 Use mounted folders for large datasets (Chrome/Edge)
- 💡 Create
index.listfiles for GitHub repositories to avoid rate limits - 💡 Use drag-and-drop for quick one-off file processing
- 💡 Enable AI assistance to help write efficient macros
We welcome contributions to make ImageJ.JS better!
- 🐛 Report bugs - Help us improve stability
- 📖 Add knowledge base examples - Share working code
- 🔌 Test plugins - Report compatibility issues
- 🌍 Improve documentation - Help others get started
- 💻 Code contributions - Performance, features, browser support
- Safari/Firefox file system alternatives
- Additional plugin compatibility testing
- Performance optimizations
- Mobile user experience
- AI integration improvements
- CheerpJ - WebAssembly JVM compiler
- ImageJ - The foundational image analysis software, developed and maintained mainly by Wayne Rasband.
- Hypha - Model Context Protocol server
- ImJoy - The project that evolved this tool
- ImJoy.io - Plugin framework for scientific computing
- BioImage.IO - AI model repository
- Fiji - ImageJ distribution for scientific image analysis
- Improving ImageJ.JS - Development journey
- CheerpJ Documentation - WebAssembly JVM docs
- File System Access API - Native FS standard
ImageJ.JS started as an experimental project at a hackathon in Dresden, exploring whether powerful desktop applications could truly run in web browsers. That experiment evolved through the ImJoy project, serving researchers who needed image analysis on iPads and in Jupyter notebooks.
With the advent of CheerpJ 3 and now CheerpJ 4.2, we've reached a turning point: ImageJ.JS is no longer a proof-of-concept, but a production-ready tool serving over 1,000 users daily for real scientific work.
The addition of AI integration via Model Context Protocol represents another leap forward - making professional image analysis accessible not just to those who can install desktop software, but to anyone who can describe what they want to achieve.
This is ImageJ, unbound from desktop constraints, ready for the next generation of scientists.
- ImageJ: Public domain
- CheerpJ: Community Edition (free for non-commercial use, commercial license required for commercial use)
- This project: Open source (see individual component licenses)
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
- 📧 Contact: Open an issue or discussion
For developers who want to understand the internals...
CheerpJ is a WebAssembly-based Java Virtual Machine that runs entirely in the browser:
- Direct JAR Loading: Load
.jarfiles directly without preprocessing - JVM in WASM: Complete Java runtime compiled to WebAssembly
- Dynamic Patching: Override Java methods with JavaScript at runtime
- Virtual File System: Complete POSIX-like file system via IndexedDB
// Initialize CheerpJ
await cheerpjInit({
clipboardMode: "java",
javaProperties: [
"user.dir=/files",
"plugins.dir=/app/lib/ImageJ/plugins"
]
});
// Create display area
cheerpjCreateDisplay(-1, -1, element);
// Run ImageJ
await cheerpjRunJar("/app/lib/ImageJ/ij.jar");/ # Root (CheerpJRootFolder)
├── /app/ # HTTP-served files (CheerpJWebFolder)
│ └── /lib/ImageJ/ # ImageJ installation
├── /files/ # Native/IndexedDB storage (persistent)
├── /local/ # Drag-and-drop files (in-memory, temporary)
├── /github/ # GitHub repos (HTTP, read-only)
│ └── owner/repo@branch/
├── /lt/ # CheerpJ runtime
└── /dev/ # Device files
Located in utils.js, this patches CheerpJ's internal file system operations:
class NativeFileSystemHandler {
async loadDirectory() {
// File System Access API
this.directoryHandle = await window.showDirectoryPicker();
}
async getFileHandle(path) {
// Navigate path segments
let handle = this.directoryHandle;
const parts = path.split('/').filter(p => p);
for (let i = 0; i < parts.length - 1; i++) {
handle = await handle.getDirectoryHandle(parts[i]);
}
return await handle.getFileHandle(parts[parts.length - 1]);
}
}Zero-API-call implementation using index.list files:
class GitHubFileSystemHandler {
// index.list format:
// dir:foldername <- directory
// file.jar <- file
async getTypeFromParentIndexList(path) {
// 1. Verify all ancestor directories exist
// 2. Check parent's index.list for entry
// 3. Return 'directory', 'file', or null
}
async getFileInfo(path) {
const type = await this.getTypeFromParentIndexList(path);
if (type === 'directory') {
return { type: 'directory', size: 0 };
} else if (type === 'file') {
// HEAD request only for confirmed files
const response = await fetch(url, { method: 'HEAD' });
return {
type: 'file',
size: parseInt(response.headers.get('content-length')),
downloadUrl: url
};
} else {
return null; // Doesn't exist
}
}
}Key optimization: Recursive ancestor validation ensures we never make requests for non-existent paths.
CheerpJ exposes internal file system operations:
var IdbOps = {
statAsync, // Get file metadata
listAsync, // List directory
makeFileData, // Open file
createDirAsync, // Make directory
renameAsync, // Rename
linkAsync, // Symlink
unlinkAsync // Delete
};
// We patch each to route to custom handlers:
function patchedStatAsync(mp, path, cb) {
if (path.startsWith('/github/')) {
return githubStatAsync(mp, path, cb);
} else if (window.nativeDirectoryHandle && path.startsWith('/files/')) {
return nativeStatAsync(mp, path, cb);
} else {
return originalStatAsync(mp, path, cb);
}
}Reading:
ImageJ calls File API
↓
CheerpJ intercepts
↓
IdbOps.makeFileData (patched)
↓
Check path prefix
↓
Route to handler (native/github/local)
↓
Fetch file data
↓
Create CheerpJFileData object
↓
Return to ImageJ
Writing (Native FS only):
ImageJ writes data
↓
IdbInodeOps.writeAsync (patched)
↓
Buffer data in memory
↓
IdbInodeOps.close (patched)
↓
Create writable stream
↓
Write all buffered data
↓
Close stream
↓
File appears on disk immediately
CheerpJ 4.2 requires Range header support. We patch the downloader:
function patchDownloader() {
function ddlSend() {
var downloader = this;
var headers = {};
if (downloader.rangeHeader) {
headers["Range"] = downloader.rangeHeader;
}
fetch(downloader.url, { method: "GET", headers: headers })
.then(response => ddlOnLoad(response, downloader))
.catch(err => ddlOnError(downloader, err));
}
DirectDownloader.prototype.send = ddlSend;
}| Parameter | Description | Example |
|---|---|---|
mount |
Mount GitHub repo | ?mount=github:owner/repo@branch |
plugins.dir |
Set plugins directory | ?plugins.dir=/github/owner/repo@branch/plugins |
Multiple parameters: ?mount=github:user/repo@main&plugins.dir=/github/user/repo@main/plugins
- Node.js and npm
- Modern browser (Chrome 86+, Edge 86+)
# Clone repository
git clone https://github.com/imjoy-team/imagej.js2.git
cd imagej.js2
# Download ImageJ
sh prepare.sh
# Install dependencies
npm install
# Start dev server
npm run devImportant: Must use npm run dev (not Python's HTTP server) because CheerpJ 4.2 requires Range header support.
await cheerpjInit({
enablePreciseAppEnv: true,
logCanvasUpdates: true
});console.log({
hasDirectDownloader: typeof DirectDownloader !== 'undefined',
hasIdbOps: typeof IdbOps !== 'undefined',
nativeFolderMounted: !!window.nativeDirectoryHandle,
githubFSReady: !!window.githubFS
});"HTTP server does not support Range header"
→ Use npm run dev, not Python's http.server
"File not found" in mounted folder → Check folder was mounted and browser supports File System Access API
ImageJ fails to start
→ Verify lib/ImageJ/ij.jar exists and check console for errors
imagej.js2/
├── index.html # Main entry point
├── utils.js # File system integration
├── hypha-imagej-service.js # MCP/Hypha integration
├── package.json # Dev dependencies
├── prepare.sh # Download ImageJ
├── imagej-examples/ # Knowledge base
│ ├── README.md
│ ├── USAGE.md
│ └── */ # Category folders
├── docs/
│ └── cheerpOS.js # CheerpJ internals reference
└── lib/ImageJ/ # ImageJ (gitignored)
├── ij.jar
├── plugins/
└── macros/
index.html
- CheerpJ initialization
- DirectDownloader patching
- Application bootstrap
- UI event handlers
utils.js
NativeFileSystemHandler- File System Access API integrationLocalFileSystemHandler- Drag-and-drop in-memory filesGitHubFileSystemHandler- HTTP-based GitHub access withindex.listoptimizationcreateNativeFileSystemPatches()- IdbOps patching for native FScreateLocalFileSystemPatches()-/local/mount pointcreateGitHubFileSystemPatches()-/github/mount point- File I/O wrappers and async operations
hypha-imagej-service.js
- MCP service registration
- Remote macro execution
- Screenshot capture
- ROI ↔ GeoJSON bidirectional conversion
- Knowledge base tools
- Results table extraction
CheerpJ 2:
- Pre-compilation Java → JavaScript required
- No dynamic JAR loading
- Limited plugin support
CheerpJ 3:
- ✅ Direct JAR loading
- ✅ Dynamic patching
- ✅ Full classloader support
CheerpJ 4.2 (current):
- ✅ Java 8, 11, 17 support
⚠️ Stricter Range header requirements- ✅ Improved WASM performance
- ✅ Better stability
- Range headers now required - Had to switch from Python's
http.servertohttp-servernpm package - Path concatenation fix - Fixed
baseUrlhandling for/index.htmlvs/routes - API stability - Internal APIs (
IdbOps,DirectDownloader) remained stable

