Skip to content

franckferman/bmctl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bmctl

Firefox bookmark toolkit - audit duplicates, compare exports, merge collections, and generate an interactive self-hosted dashboard from the command line.

Demo Python Version License


Table of Contents


Overview

bmctl is a single-file Python CLI for managing Firefox bookmark exports (.json). It parses the full folder hierarchy, preserves the original Firefox tree order, and provides five commands covering the full lifecycle of a bookmark collection.

No installation required beyond Python itself. No database, no daemon, no config file. One file, one command, one output.


Features

Command What it does
audit Duplicate detection, stats, folder tree visualization
compare Diff two exports - added, removed, net delta
merge Merge two collections into a Netscape HTML file with conflict resolution
export Flat export to CSV, Excel, or Markdown
dashboard Self-contained interactive HTML dashboard, no server required

URL normalization across all commands: scheme, www., trailing slash, and utm_* parameters are stripped before comparison. http://www.github.com/ and https://github.com are treated as the same URL.


Quick Start

# 1. Get the tool
git clone https://github.com/franckferman/bmctl.git
cd bmctl

# 2. Export your bookmarks from Firefox
#    Bookmarks > Show All Bookmarks > Import and Backup > Backup...
#    Save as bookmarks.json

# 3. Run your first audit
python3 bmctl.py audit -i bookmarks.json

# Generate an interactive dashboard
python3 bmctl.py dashboard -i bookmarks.json -o dashboard.html
# Open dashboard.html in your browser

Comparing two exports:

compare works on two separate Firefox exports taken at different points in time. Export once, wait (add/remove bookmarks), export again, then diff:

# First export saved as bookmarks-jan.json
# Second export saved as bookmarks-feb.json

python3 bmctl.py compare -o bookmarks-jan.json -n bookmarks-feb.json

Merging two collections:

Useful if you have bookmarks spread across two Firefox profiles or two machines. The merge takes the union of both collections. For each URL:

  • If it appears in only one collection, it is kept as-is.
  • If it appears in both collections in the same folder, the most recent version is kept and tags are merged.
  • If it appears in both collections in different folders (conflict), you are prompted to choose which folder to keep - or use --no-confirm to automatically keep the most recent.

No entries are silently deleted. Every URL from both files ends up in the output.

python3 bmctl.py merge -b profile-a.json -n profile-b.json -o merged.html
# merged.html is a Netscape HTML file - import it in any browser via:
# Bookmarks > Show All Bookmarks > Import and Backup > Restore... (or Import HTML)

No install step required. bmctl.py is a single file - you can also just download it directly without cloning the full repo.


Project Structure

bmctl.py
  BookmarkNode          Data model for a single bookmark
  UrlNormalizer         URL normalization / deduplication
  BookmarkDatabase      JSON parser + in-memory index
  BookmarkAuditor       Duplicate detection + reporting
  BookmarkComparator    Two-database diff
  BookmarkMerger        Merge + conflict resolution + HTML export
  BookmarkDashboardGen  Interactive HTML dashboard generator
  BookmarkExporter      CSV / Excel / Markdown export

BookmarkDatabase is the core - it walks the Firefox JSON tree recursively, assigns each bookmark its full folder path, and builds a URL index for deduplication. All five commands consume it.


Installation

Prerequisites: Python 3

No pip install required for core functionality. pandas and openpyxl are only needed for export --format xlsx:

pip install -r requirements.txt

No other dependencies.


Getting Started

Export your bookmarks from Firefox:

Bookmarks > Show All Bookmarks > Import and Backup > Backup...

Save as .json. This file is the input for all commands.


Commands

audit

Inspect a single export: duplicate detection, stats, and optional folder tree.

python bmctl.py audit -i bookmarks.json
======================================================================
                  GLOBAL AUDIT REPORT
======================================================================
 Total bookmarks found        : 3110
 Folders scanned              : 244
 Unique links                 : 3059
 Duplicates detected          : 51 (1.6%)
======================================================================

[!] Top 10 most duplicated links:
  - GitHub
    URL : https://github.com
    Found 3 times:
      * Folder: Dev
      * Folder: CTI, OSINT & SocMint > Code Search Engines

Use --show-tree to verify that your folder structure was parsed correctly before generating a dashboard:

python bmctl.py audit -i bookmarks.json --show-tree
  |   [   0]  Cybersecurity & CTI
    +-- [   5]  C2 Frameworks
    +-- [   7]  OSINT & Recon
    +-- [   5]  Exploitation
  |   [   0]  Development
    +-- [   4]  Python
    +-- [   4]  Go
  |   [   6]  Tools
  |   [   6]  Blogs & News

Flags:

Flag Default Description
-i / --input required Firefox JSON export
--top N 10 Show top N most duplicated URLs
--show-short off Stats only, skip duplicate list
--show-tree off Print full folder hierarchy with bookmark counts

compare

Diff two exports. Shows what was added and removed between two snapshots of the same collection.

python bmctl.py compare -o bookmarks-old.json -n bookmarks-new.json
======================================================================
                  COMPARISON REPORT
======================================================================
 Unique bookmarks V1 (old)    : 2980
 Unique bookmarks V2 (new)    : 3059
 Net delta                    : +79
======================================================================
 [+] New bookmarks added      : 102
 [-] Old bookmarks removed    : 23
======================================================================

[+] PREVIEW OF NEW ENTRIES (Max 15):
  + HackTricks                     (Folder: Cybersecurity > Documentation & Articles)
    https://book.hacktricks.xyz

Flags:

Flag Default Description
-o / --old required Old JSON export
-n / --new required New JSON export
--show-full off Show complete added/removed lists (no limit)
--show-short off Stats only, skip item lists

merge

Merge two bookmark collections into a single Netscape HTML file (importable by any browser). Detects URL conflicts (same URL in different folders) and resolves them.

python bmctl.py merge -b bookmarks-base.json -n bookmarks-new.json -o merged.html

Without --no-confirm, conflicts trigger an interactive prompt:

[?] FOLDER CONFLICT DETECTED FOR:
    - URL  : https://example.com
    - Title: Example Site
    In which folder(s) do you want to keep it?
      1) [Keep] -> Dev > Tools
      2) [Keep] -> Misc.
      3) Skip / Keep most recent version
    Your choice (1, 2...) :

Tags from all instances are merged onto the surviving node.

With automatic conflict resolution (keeps most recent):

python bmctl.py merge -b base.json -n new.json -o merged.html --no-confirm

Flags:

Flag Default Description
-b / --base required Base JSON export
-n / --new required JSON to merge in
-o / --output required Output HTML file
--no-confirm off Auto-resolve conflicts silently (keeps most recent)

export

Export to a flat format. All formats include: Title, URL, Folder path, Tags, Date added.

# CSV
python bmctl.py export -i bookmarks.json --format csv -o bookmarks.csv

# Excel
python bmctl.py export -i bookmarks.json --format xlsx -o bookmarks.xlsx

# Markdown (organized by folder)
python bmctl.py export -i bookmarks.json --format md -o bookmarks.md

Flags:

Flag Default Description
-i / --input required Firefox JSON export
--format required csv, xlsx, or md
-o / --output required Output file path

dashboard

Generate a fully self-contained single-file HTML dashboard. No server required - open directly in a browser.

python bmctl.py dashboard -i bookmarks.json -o dashboard.html

Dashboard features:

  • Sidebar with full collapsible folder tree (Firefox order preserved)
  • Three views: Dashboard (widget grid), Cards, Table
  • Global search across title, URL and tags
  • "Recent additions" quick view (last 50)
  • Folder-aware widget titles (relative path in folder view, full path in global view)
  • Pure black enterprise theme

Flags:

Flag Default Description
-i / --input required Firefox JSON export
-o / --output dashboard.html Output HTML file

WSL users: use Linux paths to avoid backslash stripping.

# Correct
python bmctl.py dashboard -i /mnt/c/Users/you/Desktop/bookmarks.json \
                          -o /mnt/c/Users/you/Desktop/dashboard.html
# Wrong - bash strips backslashes without quotes
python bmctl.py dashboard -i ... -o C:\Users\you\Desktop\dashboard.html

URL Deduplication

bmctl normalizes URLs before comparing them to find true duplicates:

Rule Example
Scheme normalization http:// = https://
Strip www. prefix www.github.com = github.com
Strip trailing slash github.com/ = github.com
Strip utm_* params ?utm_source=... removed
Query params preserved ?q=foo != ?q=bar

http://www.github.com/ and https://github.com resolve to the same canonical URL.


Firefox JSON Compatibility

bmctl handles both Firefox export formats:

Format Bookmark Folder
Legacy typeCode: 1 typeCode: 2
Modern type: "text/x-moz-place" type: "text/x-moz-place-container"
Fallback presence of uri field presence of children field

License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).

Any use, modification, or distribution - including over a network - requires the full source code to remain open under the same license.

About

bmctl Firefox bookmark toolkit - audit duplicates, compare exports, merge collections, and generate an interactive dashboard from the command line.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages