Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sureshamal/markview/llms.txt

Use this file to discover all available pages before exploring further.

MarkView provides full command-line integration, allowing you to open files and directories directly from your terminal. This is perfect for power users who prefer CLI workflows.

Overview

Once built, MarkView can be invoked from the command line with file or directory paths as arguments. The application will automatically load and display the specified content.
The CLI functionality is powered by Rust commands that parse command-line arguments and load files during application startup.

Basic Usage

Single File

Open a single Markdown file:
./markview README.md
The file will open in MarkView and be displayed immediately.

Multiple Files

Load multiple files at once by passing multiple arguments:
./markview file1.md file2.md documentation.md
All specified files will appear in the sidebar, and the first file will be selected by default.

Directory

Load all Markdown files from a directory:
./markview ./docs
MarkView will recursively find all .md and .markdown files in the specified directory.

Current Directory

Load all Markdown files in the current directory:
./markview .

Path Resolution

MarkView intelligently handles both relative and absolute paths.

Relative Paths

Relative paths are resolved against the current working directory:
cd ~/projects/my-docs
./markview ./guides/getting-started.md

Absolute Paths

Absolute paths are used as-is:
./markview /home/user/documents/README.md

Path Resolution Implementation

The Rust backend handles path resolution:
// From src-tauri/src/lib.rs:11-25
#[tauri::command]
fn get_cli_args() -> Vec<String> {
    let mut args: Vec<String> = Vec::new();
    if let Ok(current_dir) = env::current_dir() {
        for arg in env::args().skip(1) {
            let path = std::path::Path::new(&arg);
            if path.is_absolute() {
                args.push(arg.clone());
            } else {
                args.push(current_dir.join(path).to_string_lossy().into_owned());
            }
        }
    }
    args
}
  1. CLI arguments are collected (skipping the first argument, which is the executable name)
  2. Each argument is checked to determine if it’s an absolute or relative path
  3. Absolute paths are passed through unchanged
  4. Relative paths are joined with the current working directory
  5. The resolved paths are returned to the frontend

Platform-Specific Examples

./markview README.md
Add MarkView to your PATH for easier access:
export PATH="$PATH:/path/to/markview"
markview README.md

Backend Implementation

The command-line functionality is implemented through three Rust commands:

1. get_cli_args

Retrieves and resolves command-line arguments:
// From src-tauri/src/lib.rs:11-25
#[tauri::command]
fn get_cli_args() -> Vec<String> {
    let mut args: Vec<String> = Vec::new();
    if let Ok(current_dir) = env::current_dir() {
        for arg in env::args().skip(1) {
            let path = std::path::Path::new(&arg);
            if path.is_absolute() {
                args.push(arg.clone());
            } else {
                args.push(current_dir.join(path).to_string_lossy().into_owned());
            }
        }
    }
    args
}
Returns: Vec<String> - Array of resolved file/directory paths

2. read_markdown_file

Reads a single Markdown file from disk:
// From src-tauri/src/lib.rs:27-41
#[tauri::command]
fn read_markdown_file(path: String) -> Result<FileData, String> {
    let path = Path::new(&path);
    if path.is_file() {
        if let Ok(content) = fs::read_to_string(path) {
            let name = path
                .file_name()
                .unwrap_or_default()
                .to_string_lossy()
                .into_owned();
            return Ok(FileData { name, content });
        }
    }
    Err("Could not read file".to_string())
}
Parameters:
  • path: String - Absolute path to the Markdown file
Returns: Result<FileData, String>
  • FileData { name: String, content: String } on success
  • Error message string on failure

3. read_markdown_dir

Reads all Markdown files from a directory:
// From src-tauri/src/lib.rs:43-69
#[tauri::command]
fn read_markdown_dir(path: String) -> Result<Vec<FileData>, String> {
    let mut files = Vec::new();
    let path = Path::new(&path);
    if path.is_dir() {
        if let Ok(entries) = fs::read_dir(path) {
            for entry in entries.flatten() {
                let entry_path = entry.path();
                if entry_path.is_file() {
                    if let Some(ext) = entry_path.extension() {
                        if ext == "md" || ext == "markdown" {
                            if let Ok(content) = fs::read_to_string(&entry_path) {
                                let name = entry_path
                                    .file_name()
                                    .unwrap_or_default()
                                    .to_string_lossy()
                                    .into_owned();
                                files.push(FileData { name, content });
                            }
                        }
                    }
                }
            }
        }
    }
    Ok(files)
}
Parameters:
  • path: String - Absolute path to the directory
Returns: Result<Vec<FileData>, String>
  • Array of FileData objects for all Markdown files found
  • Empty array if directory contains no Markdown files
read_markdown_dir only scans the top level of the specified directory. It does not recursively scan subdirectories.

Frontend Integration

The frontend automatically processes CLI arguments on application startup:
// From app/page.tsx:483-500
useEffect(() => {
  const loadInitialArgs = async () => {
    try {
      const { invoke } = await import('@tauri-apps/api/core');
      const paths = await invoke<string[]>('get_cli_args');
      for (const path of paths) {
        if (path.endsWith('.md') || path.endsWith('.markdown')) {
          await loadFileFromPath(path);
        } else {
          await loadFolderFromPath(path);
        }
      }
    } catch (err) {
      console.log('Not running in Tauri, skipping initial args');
    }
  };
  loadInitialArgs();
}, [loadFileFromPath, loadFolderFromPath]);
1

Invoke Rust Command

The frontend calls get_cli_args() to retrieve command-line arguments.
2

Determine Path Type

Each path is checked to determine if it’s a file (.md or .markdown extension) or a directory.
3

Load Content

  • Files are loaded with read_markdown_file()
  • Directories are loaded with read_markdown_dir()
4

Display in UI

Loaded files appear in the sidebar, and the first file is automatically selected.

FileData Structure

Both file reading commands return data in this format:
// From src-tauri/src/lib.rs:5-9
#[derive(serde::Serialize)]
struct FileData {
    name: String,
    content: String,
}
name
String
The filename (not the full path) extracted using file_name()
content
String
The complete file content as a UTF-8 string

Error Handling

The CLI implementation includes graceful error handling:

File Reading Errors

// From app/page.tsx:436-455
const loadFileFromPath = useCallback(async (filePath: string) => {
  try {
    const { invoke } = await import('@tauri-apps/api/core');
    const fileData = await invoke<{ name: string; content: string }>('read_markdown_file', { path: filePath });
    
    const newFile: MarkdownFile = {
      id: `${fileData.name}-${Date.now()}-${Math.random()}`,
      name: fileData.name,
      content: fileData.content,
    };
    setFiles(prev => {
      const existingNames = new Set(prev.map(f => f.name));
      if (existingNames.has(fileData.name)) return prev;
      return [...prev, newFile];
    });
    setSelectedFile(fileData.name);
  } catch (err) {
    console.error('Failed to read file:', err);
  }
}, []);
  • File not found: Silently logged to console
  • Permission denied: Logged to console, file skipped
  • Invalid UTF-8: File is skipped
  • Not a Markdown file: Ignored by extension check
  • Not running in Tauri: CLI arguments are skipped (for web development)

Building for CLI Usage

To use MarkView from the command line, you need to build the production binary:
1

Install Dependencies

bun install
2

Build Production Binary

bun run tauri build
3

Locate Binary

The compiled executable will be at:
src-tauri/target/release/markview
4

Add to PATH (Optional)

For convenient access, add the binary location to your system PATH or copy it to a directory already in your PATH (e.g., /usr/local/bin on Linux/macOS).

Advanced Usage

Shell Aliases

Create convenient aliases for common operations:
# In ~/.bashrc or ~/.zshrc
alias mdview="/path/to/markview"
alias mdhere="markview ."
alias mdread="markview README.md"

Integration with Other Tools

Combine MarkView with other CLI tools:
find . -name "*.md" -exec markview {} +

Scripting

Use MarkView in scripts for documentation viewing:
#!/bin/bash
# Open project documentation

PROJECT_DOCS="$HOME/projects/myproject/docs"

if [ -d "$PROJECT_DOCS" ]; then
    markview "$PROJECT_DOCS"
else
    echo "Documentation not found!"
    exit 1
fi

Comparison with GUI Methods

CLI Advantages

  • Fast for power users
  • Scriptable and automatable
  • Integrates with other tools
  • Quick access from anywhere

GUI Advantages

  • Visual file selection
  • Drag and drop support
  • Easier for beginners
  • No path typing required

Troubleshooting

Problem: Shell can’t find the markview command.Solution:
  • Use the full path: ./markview or /path/to/markview
  • Add MarkView to your PATH environment variable
  • Check that the binary has execute permissions: chmod +x markview
Problem: CLI arguments are passed, but files don’t open.Solution:
  • Verify file paths are correct and files exist
  • Check file extensions are .md or .markdown
  • Ensure you have read permissions for the files
  • Check console logs for error messages
Problem: Relative paths don’t resolve correctly.Solution:
  • Use absolute paths instead
  • Ensure you’re in the correct directory when using relative paths
  • Check that the current working directory is accessible
Problem: Not all Markdown files from a directory are loaded.Solution:
  • Remember that only the top-level directory is scanned (no recursion)
  • Check file extensions are exactly .md or .markdown
  • Verify files are readable and contain valid UTF-8 text

Next Steps

Opening Files

Explore all methods to load files into MarkView

Navigation

Master the UI navigation features