Skip to content

File Import and Editing

sysid edited this page Nov 29, 2025 · 3 revisions

File Import and Smart Editing

Why File Import?

You have scripts, documents, and snippets scattered across your filesystem. You want to:

  • Keep them as files — for version control (git), your favorite editor, direct execution
  • But also have bkmr's powerful search, tagging, fuzzy finder, and organization

File Import gives you both. Your files stay exactly where they are. bkmr indexes their content and metadata, making them searchable and manageable alongside your other bookmarks. When you edit, bkmr automatically opens the source file — not a database copy.

Two Ways to Reference Files in bkmr

This is the critical distinction:

File-Imported Bookmark (bkmr import-files)

bkmr import-files ~/scripts/backup.sh --base-path SCRIPTS_HOME
Aspect Behavior
Content storage File content copied into database
file_path field Set to source file location
Smart editing bkmr edit opens the source file in $EDITOR
Sync Edits to source file can be synced back to database
Requirements Frontmatter with at least name: field
Visual indicator FZF shows file path + timestamp in magenta

Regular Bookmark with URL (bkmr add)

bkmr add "file:///Users/me/scripts/backup.sh" scripts --title "Backup Script"
Aspect Behavior
Content storage Only the URL/path is stored
file_path field NULL — not tracked as file-imported
Smart editing bkmr edit opens database template editor
Sync None — file and bookmark are independent
Requirements None — just a URL
Visual indicator No file path shown in FZF

Which Should You Use?

Use Case Recommendation
Scripts you actively develop and want searchable File Import
Documentation/notes you edit frequently File Import
Quick reference to a file location Regular bookmark with file:// URL
External URLs, code snippets, commands Regular bookmark

How Smart Editing Works

The smart edit mechanism is simple. When you run bkmr edit <id>:

Check: Is bookmark.file_path NOT NULL?
├─ YES (file-imported) → Open source file in $EDITOR, sync changes back
└─ NO (regular)        → Open database content in template editor

Database schema fields for file tracking:

file_path  TEXT NULL  -- Source file path (NULL = regular bookmark)
file_mtime INT  NULL  -- File modification timestamp
file_hash  TEXT NULL  -- SHA-256 hash for change detection

A bookmark is considered "file-imported" if and only if file_path IS NOT NULL.

Visual Identification in FZF

File-imported bookmarks are visually distinct in the fuzzy finder:

3164: api-reference [_md_,api,documentation]  /path/to/api-reference.md (2025-06-27 19:30:30)
3234: Explain Rust Modules [_md_,doc,rs]
  • Bookmark 3164: Shows file path and modification time in magenta — this is file-imported
  • Bookmark 3234: No file info — this is a regular bookmark (even though it has _md_ tag)

Requirements for File Import

Frontmatter is Required

For a file to be imported, it must have frontmatter with at least a name: field:

YAML frontmatter (works in any file):

---
name: "Database Backup Script"
tags: ["database", "backup"]
type: "_shell_"
---
#!/bin/bash
pg_dump mydb > backup.sql

Hash-style frontmatter (better for scripts — stays executable):

#!/bin/bash
# name: Database Backup Script
# tags: database, backup
# type: _shell_

pg_dump mydb > backup.sql

Frontmatter Fields

Field Required Description
name Yes Title for the bookmark
tags No Comma-separated or YAML list
type No System tag override (_shell_, _md_, _snip_)
description No Additional context

Without frontmatter: The file will be skipped during import with a warning.

Supported File Types

bkmr auto-detects file types and assigns appropriate system tags:

Extension Detected Type System Tag Default Action
.sh Shell script _shell_ Interactive execution
.py Python script _shell_ Interactive execution
.md Markdown _md_ Render in browser
Others Text _imported_ Copy to clipboard

You can override the auto-detected type using the type: frontmatter field.

Importing Files

Basic Import

# Single file
bkmr import-files ~/scripts/backup.sh

# Multiple files
bkmr import-files ~/scripts/backup.sh ~/scripts/deploy.sh

# Entire directory (recursive, respects .gitignore)
bkmr import-files ~/scripts/

Import with Base Paths (Recommended)

Base paths make your imports portable across machines:

# Import with base path variable
bkmr import-files ~/scripts/backup.sh --base-path SCRIPTS_HOME

# Stored as: $SCRIPTS_HOME/backup.sh (not absolute path)

Configure base paths in ~/.config/bkmr/config.toml:

[base_paths]
SCRIPTS_HOME = "$HOME/scripts"
DOCS_HOME = "$HOME/documents"

Update Changed Files

# Detect and update changed files
bkmr import-files ~/scripts/ --base-path SCRIPTS_HOME --update

# Detects:
# - Content changes (SHA-256 hash comparison)
# - Metadata changes (frontmatter name, tags, type)
# - Path changes (file moved to different directory)

Preview with Dry Run

# See what would happen without making changes
bkmr import-files ~/scripts/ --base-path SCRIPTS_HOME --dry-run --update

Remove Deleted Files

# Delete bookmarks whose source files no longer exist
bkmr import-files ~/scripts/ --delete-missing

Smart Editing in Practice

Editing File-Imported Bookmarks

bkmr edit 3164
# Output:
#   Editing source file: /Users/me/scripts/backup.sh
#   [Opens in $EDITOR]
#   File edited successfully, syncing changes to database...
#   Successfully synced changes to database

What happens:

  1. Resolves file_path (expands base path variables like $SCRIPTS_HOME)
  2. Opens the source file in $EDITOR
  3. Waits for you to save and close
  4. Re-parses frontmatter and content
  5. Updates database with any changes

Editing Regular Bookmarks

bkmr edit 3234
# Opens template editor with database content:
# === ID ===
# 3234
# === URL ===
# [content here]
# === TITLE ===
# Explain Rust Modules
# ...

Force Database Editing

Even for file-imported bookmarks, you can force database editing:

bkmr edit 3164 --force-db
# Opens database template editor instead of source file

Use cases:

  • Source file is on unmounted drive
  • Want temporary changes without affecting source
  • Source file was deleted but you want to keep/edit the bookmark

Integration with bkmr Features

Search

File-imported bookmarks are fully searchable:

# Full-text search includes file content
bkmr search "database backup"

# Tag filtering includes frontmatter tags
bkmr search -t backup,production

# Find all imported shell scripts
bkmr search -t _shell_

Fuzzy Finder

bkmr search --fzf
# CTRL-E → Smart edit (opens source file for imported bookmarks)
# CTRL-D → Delete

Content-Aware Actions

# Shell scripts: interactive execution
bkmr open <shell-script-id>

# With arguments
bkmr open <shell-script-id> --no-edit -- arg1 arg2

# Markdown: render in browser
bkmr open <markdown-id>

Complete Workflow Example

1. Configure Base Paths

bkmr --generate-config > ~/.config/bkmr/config.toml
# Edit to add:
# [base_paths]
# SCRIPTS_HOME = "$HOME/scripts"

2. Create Script with Frontmatter

cat > ~/scripts/backup-db.sh << 'EOF'
#!/bin/bash
# name: Database Backup
# tags: database,backup,production
# type: _shell_

pg_dump mydb | gzip > backup_$(date +%Y%m%d).sql.gz
EOF
chmod +x ~/scripts/backup-db.sh

3. Import

bkmr import-files ~/scripts/ --base-path SCRIPTS_HOME
# Output: Imported: backup-db.sh

4. Search, Edit, Execute

# Find it
bkmr search backup --fzf

# Edit (opens ~/scripts/backup-db.sh)
bkmr edit <id>

# Execute
bkmr open <id>

5. Keep in Sync

# After editing files directly
bkmr import-files ~/scripts/ --base-path SCRIPTS_HOME --update

Troubleshooting

"Source file does not exist"

$ bkmr edit 123
Source file does not exist: $SCRIPTS_HOME/old-script.sh
Falling back to database content editing...

Solutions: Check if file moved/deleted, update base path config, use --force-db

"No frontmatter found"

$ bkmr import-files script.sh
Warning: Invalid frontmatter in script.sh - skipping

Solution: Add frontmatter with at least name: field

"Base path not configured"

$ bkmr import-files scripts/ --base-path SCRIPTS_HOME
Error: Base path 'SCRIPTS_HOME' not found in configuration

Solution: Add to ~/.config/bkmr/config.toml under [base_paths]

Best Practices

  1. Use base paths for portability across machines
  2. Minimal frontmatter — just name: and relevant tags:
  3. Regular sync — run bkmr import-files --update periodically or create an alias
  4. Descriptive names — "Backup Production Database" not "backup.sh"
  5. Consistent tagging — use hierarchical tags like production,database,backup

Related Pages

bkmr Documentation

Getting Started
User Guide
Advanced Features
Reference
Support

Clone this wiki locally