A powerful command-line interface for opening local files via custom URL scheme (fileopener://). This tool enables developers to create clickable links that open specific files in their local editor directly from web pages, documentation, or shared links.
- π Custom URL Protocol: Register
fileopener://scheme with your operating system - π Project Aliases: Map project names to local directory paths
- π₯οΈ Cross-Platform: Works on macOS, Windows, and Linux
- π Enhanced Security: Whitelist-based path validation with protection against:
- Path traversal attacks (
../,~/) - Absolute path access outside project directories
- Symbolic link escapes
- Directory traversal bypass attempts
- Path traversal attacks (
- π Dual URL Formats: Supports both modern and legacy URL formats
- βοΈ Configuration Management: Easy project setup and management
- π‘οΈ Error Handling: Comprehensive error messages and validation
- π― Config URL Support: Access configuration via
fileopener://config - π§ ES Module Support: Built with modern JavaScript (ES modules)
- π§Ή Memory Leak Prevention: Automatic process cleanup after file operations
- π Log Management: Automatic log rotation and manual log cleanup
- π Web Integration: Compatible with fileopener-redirect-worker for HTTP-to-protocol redirection
# Install globally from npm
npm install -g @context-action/fopen-cli
# Register the protocol with your system
fopen install# Clone the repository
git clone <repository-url>
cd url-fileopener
# Install dependencies
pnpm install
# Build the CLI (converts ES modules to CommonJS)
pnpm build
# Register the protocol with your system
node dist/bin-simple.cjs install# 1. Add a project alias
fopen add myproject /path/to/your/project
# 2. Open files using URLs
fopen open "fileopener://myproject/src/index.js"
# 3. List configured projects
fopen list
# 4. Open configuration file
fopen config
# 5. Open config via URL (alternative)
fopen open "fileopener://config"# 1. Add a project alias
node dist/bin-simple.cjs add myproject /path/to/your/project
# 2. Open files using URLs
node dist/bin-simple.cjs open "fileopener://myproject/src/index.js"
# 3. List configured projects
node dist/bin-simple.cjs list
# 4. Open configuration file
node dist/bin-simple.cjs config
# 5. Open config via URL (alternative)
node dist/bin-simple.cjs open "fileopener://config"This CLI tool is fully compatible with the fileopener-redirect-worker, a Cloudflare Worker that automatically redirects HTTP URLs to the fileopener:// protocol.
- HTTP URL:
https://your-domain.com/fileopener/myProject/src/readme.md - Automatic Redirect: The worker redirects to
fileopener://myProject/src/readme.md - File Opening: Your local CLI tool opens the file in your default editor
# 1. Deploy the redirect worker to Cloudflare
git clone https://github.com/mineclover/fileopener-redirect-worker
cd fileopener-redirect-worker
npm install
npm run deploy
# 2. Configure your domain in wrangler.toml
[[routes]]
pattern = "your-domain.com/fileopener/*"
zone_name = "your-domain.com"
# 3. Use HTTP URLs in your documentation, issues, or web pages
# https://your-domain.com/fileopener/myProject/src/index.js- Shareable Links: Create HTTP links that work in browsers and automatically open files locally
- Documentation Integration: Use in README files, GitHub issues, or web documentation
- Cross-Platform: Works on any device with a browser, regardless of CLI installation
- Fallback Support: HTML fallback with manual link for unsupported browsers
<!-- In your README.md or documentation -->
Check out the main configuration file:
[src/config.js](https://your-domain.com/fileopener/myProject/src/config.js)
Or view the API documentation:
[docs/api.md](https://your-domain.com/fileopener/myProject/docs/api.md)This very README file can be opened using the fileopener protocol! Here's how to set it up:
# 1. Register the current project (path is optional - uses current directory)
fopen add url-fileopener
# 2. Open this README file directly
fopen open "fileopener://url-fileopener/README.md"
# 3. Or use the web redirect URL (if you have the worker deployed)
# https://your-domain.com/fileopener/url-fileopener/README.mdTry it yourself:
- Direct Protocol:
fileopener://url-fileopener/README.mdβ (Tested and working!) - Web Redirect:
https://your-domain.com/fileopener/url-fileopener/README.md - npm Package:
@context-action/fopen-cli@1.0.4β (Tested and working!)
More examples from this project:
- Source code - Main CLI implementation
- Package config - Project configuration
- Build script - Build automation
This demonstrates how you can create clickable links in documentation that automatically open the corresponding files in your local editor!
The npm package has been thoroughly tested and verified to work correctly:
# β
Tested: npm package installation and registration
npx @context-action/fopen-cli@1.0.4 install
# β Protocol registered with correct handler path
# β
Tested: project registration with path omission
npx @context-action/fopen-cli@1.0.4 add url-fileopener
# β Uses current directory automatically
# β
Tested: file opening with memory leak prevention
npx @context-action/fopen-cli@1.0.4 open "fileopener://url-fileopener/README.md"
# β File opens and process exits cleanlyKey improvements in v1.0.4:
- β Fixed bin path configuration for npm package
- β Added memory leak prevention with explicit process exit
- β Improved child process management with timeout
- β Enhanced error handling and validation
Registers the fileopener:// protocol with your operating system and creates the configuration directory.
# npm installation
fopen install
# source installation
node dist/bin-simple.cjs installOutput:
Installing file opener protocol...
Registering protocol: "fileopener"
With command: "node "/path/to/dist/bin/fopen-handler-simple.cjs" "$_URL_""
[SECURITY] Command executed: { ... }
Protocol registration successful!
Configuration directory: ~/.fopen-cli
Adds a new project alias mapping a name to a local directory path.
# npm installation
fopen add myproject /Users/username/projects/my-project
fopen add docs /Users/username/documents
fopen add current-project # Uses current directory
# source installation
node dist/bin-simple.cjs add myproject /Users/username/projects/my-project
node dist/bin-simple.cjs add docs /Users/username/documents
node dist/bin-simple.cjs add current-project # Uses current directoryValidation:
- Checks if the specified path exists
- Converts relative paths to absolute paths
- Updates existing project aliases
Lists all configured project aliases and their paths.
fopen listOutput:
Configured projects:
myproject -> /Users/username/projects/my-project
docs -> /Users/username/documents
Removes a project alias from the configuration.
fopen remove myprojectOutput:
Project 'myproject' removed successfully
Opens a file using the fileopener:// URL format.
# Modern format
fopen open "fileopener://myproject/src/index.js"
# Legacy format (query parameter)
fopen open "fileopener://myproject?path=src/index.js"
# Files with spaces (URL encoded)
fopen open "fileopener://myproject/file%20with%20spaces.txt"Opens the configuration file in your default editor.
fopen configCleans up log files to free disk space. Log files are automatically rotated when they exceed 1MB.
fopen clean-logsUnregisters the protocol from your system.
fopen uninstall
# With cleanup (removes configuration files)
fopen uninstall --cleanfileopener://project-name/path/to/file.ext
Examples:
fileopener://myproject/README.md
fileopener://myproject/src/components/Button.tsx
fileopener://docs/api/reference.md
fileopener://project-name?path=path/to/file.ext
Examples:
fileopener://myproject?path=README.md
fileopener://myproject?path=src/components/Button.tsx
Special characters in file paths should be URL encoded:
| Character | Encoded |
|---|---|
| Space | %20 |
| Hash | %23 |
| Percent | %25 |
Example:
fileopener://myproject/my%20file%20with%20spaces.txt
~/.fopen-cli/
βββ config.json # Project aliases configuration
βββ handler.log # Operation logs (when available)
{
"projects": {
"myproject": "/Users/username/projects/my-project",
"docs": "/Users/username/documents",
"website": "/Users/username/sites/website"
},
"version": "1.0.0",
"lastUpdated": "2025-09-15T03:50:44.475Z"
}The tool implements comprehensive security measures to prevent unauthorized file access:
# β These will be blocked:
fopen open "fileopener://myproject/../../../etc/passwd"
fopen open "fileopener://myproject?path=../sensitive-file.txt"
fopen open "fileopener://myproject?path=~/Documents/private.txt"# β These will be blocked:
fopen open "fileopener://myproject?path=/etc/passwd"
fopen open "fileopener://myproject?path=/Users/otheruser/private.txt"The tool resolves symbolic links and ensures they don't escape the project directory boundaries.
When security violations are detected, the tool provides clear error messages:
Security violation: Path traversal attempt detected
Access denied: Security policy violation
Attempted access to: ../etc/passwd
Allowed project path: /path/to/project
- Checks if the target file exists before attempting to open
- Validates project aliases exist in configuration
- Ensures resolved paths remain within project boundaries
The tool automatically manages log files to prevent disk space issues:
- Log files are automatically rotated when they exceed 1MB
- Old logs are backed up as
handler.log.old - Maximum total log size is limited to 2MB (current + backup)
# Clean all log files
fopen clean-logs- macOS/Linux:
~/.fopen-cli/handler.log - Windows:
%USERPROFILE%\.fopen-cli\handler.log
Logs include:
- URL processing attempts
- Security violations
- File opening results
- Error messages
This ensures the tool doesn't consume excessive disk space while maintaining useful debugging information.
Comprehensive error messages for various scenarios:
- Non-existent files or projects
- Invalid URL formats
- Path traversal attempts
- Missing configuration
Uses open command to open files with default applications.
Uses start command to open files with default applications.
Uses xdg-open command to open files with default applications.
The tool uses platform-specific commands to open files with their default applications:
- macOS:
open /path/to/file- Opens with the default application for that file type - Windows:
start "" "/path/to/file"- Opens with the default application for that file type - Linux:
xdg-open /path/to/file- Opens with the default application for that file type
Note: The actual behavior may vary depending on your system configuration and installed applications.
- Expected: Opens in your default text editor (VS Code, Sublime Text, etc.)
- Purpose: Code review, documentation reading, configuration editing
- Expected: Opens in a text editor or file manager (NOT executed)
- Security: Files are opened for viewing, not execution
- Purpose: Script review, configuration inspection
- Expected: Opens in the default media viewer/player
- Purpose: Content review, asset verification
- Expected: Opens in the default archive manager
- Purpose: Archive inspection, file extraction
The tool is designed with security in mind:
- No Execution: Executable files (
.exe,.sh,.bat) are opened for viewing, not execution - Path Validation: All paths are validated to prevent directory traversal attacks
- Project Boundaries: Files can only be accessed within configured project directories
- Safe Defaults: Uses system default applications rather than custom execution logic
If files don't open as expected:
- Check Default Applications: Verify your system's default applications for the file type
- Test with Different Files: Try opening various file types to isolate the issue
- System Configuration: Some systems may have different default behaviors
- Manual Testing: Test the platform commands directly:
# macOS open /path/to/your/file.js # Windows start "" "C:\path\to\your\file.js" # Linux xdg-open /path/to/your/file.js
Important: The exact behavior depends on your system configuration. The tool provides a safe, standard way to open files without executing potentially dangerous code.
src/
βββ bin-simple.js # Main CLI entry point
βββ bin/
βββ fopen-handler-simple.js # URL handler binary
tests/
βββ contract/ # Contract tests (TDD)
βββ integration/ # Integration tests
- Framework: Pure Node.js (no external frameworks)
- Protocol Registration: protocol-registry package
- Configuration: JSON files with atomic operations
- Testing: Vitest with comprehensive test coverage
- Build: tsup for JavaScript bundling
# Install dependencies
pnpm install
# Run tests
pnpm test
# Build the project
pnpm build
# Clean build artifacts
pnpm clean# Run all tests
pnpm test
# Run specific test suites
pnpm test tests/contract/
pnpm test tests/integration/Problem: URLs don't open or system doesn't recognize fileopener://
Solution:
# Re-register the protocol
fopen uninstall
fopen installProblem: File exists but doesn't open
Solutions:
-
Check project configuration:
fopen list fopen config # Verify paths in configuration -
Verify file path:
# Test with absolute path first fopen open "fileopener://myproject/README.md"
-
Check for special characters:
# Use URL encoding for special characters fopen open "fileopener://myproject/file%20with%20spaces.txt"
Problem: Access denied or permission errors
Solutions:
- Check directory permissions
- Ensure user has read access to project files
- Verify configuration directory permissions:
ls -la ~/.fopen-cli/
For detailed troubleshooting, check the configuration and logs:
# Open configuration file
fopen config
# Check project listings
fopen list
# Verify file exists
ls -la /path/to/your/project/file.extCreate clickable links in documentation that open source files:
Check the [main component](fileopener://myproject/src/components/Main.tsx)
or review the [API implementation](fileopener://myproject/src/api/users.ts).Share direct links to specific files during code reviews:
fileopener://project/src/features/authentication/login.ts
fileopener://project/tests/unit/auth.test.ts
Quick access to frequently used files:
# Open main configuration
fileopener://myproject/package.json
# Open documentation
fileopener://myproject/README.md
# Open entry point
fileopener://myproject/src/index.tsIntegrate with development tools, IDEs, or documentation systems to provide direct file access.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes following the TDD approach
- Add tests for new functionality
- Ensure all tests pass:
pnpm test - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow Test-Driven Development (TDD)
- Write tests before implementation
- Maintain high test coverage
- Use vanilla JavaScript for simplicity
- Keep code simple and readable
- Include comprehensive error handling
MIT License - see the LICENSE file for details.
Created with β€οΈ using pure Node.js