{"id":27621779,"url":"https://github.com/dhth/bmm","last_synced_at":"2025-06-13T08:10:12.557Z","repository":{"id":278292847,"uuid":"931826132","full_name":"dhth/bmm","owner":"dhth","description":"get to your bookmarks in a flash","archived":false,"fork":false,"pushed_at":"2025-05-25T15:48:13.000Z","size":190,"stargazers_count":130,"open_issues_count":8,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-25T16:39:28.616Z","etag":null,"topics":["bookmarks","bookmarks-manager","ratatui","tui"],"latest_commit_sha":null,"homepage":"https://tools.dhruvs.space/bmm","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dhth.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-12T23:13:34.000Z","updated_at":"2025-05-25T15:46:30.000Z","dependencies_parsed_at":"2025-05-25T16:29:15.680Z","dependency_job_id":"d2a2f966-07c0-4b36-b575-2b0ec39a3dc4","html_url":"https://github.com/dhth/bmm","commit_stats":null,"previous_names":["dhth/bmm"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/dhth/bmm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhth%2Fbmm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhth%2Fbmm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhth%2Fbmm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhth%2Fbmm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dhth","download_url":"https://codeload.github.com/dhth/bmm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhth%2Fbmm/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259606992,"owners_count":22883565,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bookmarks","bookmarks-manager","ratatui","tui"],"created_at":"2025-04-23T08:03:58.031Z","updated_at":"2025-06-13T08:10:12.532Z","avatar_url":"https://github.com/dhth.png","language":"Rust","readme":"\u003cp align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003ebmm\u003c/h1\u003e\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/dhth/bmm/actions/workflows/build.yml\"\u003e\u003cimg alt=\"GitHub release\" src=\"https://img.shields.io/github/actions/workflow/status/dhth/bmm/build.yml?style=flat-square\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://crates.io/crates/bmm\"\u003e\u003cimg alt=\"GitHub release\" src=\"https://img.shields.io/crates/v/bmm?style=flat-square\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/dhth/bmm/releases/latest\"\u003e\u003cimg alt=\"Latest release\" src=\"https://img.shields.io/github/release/dhth/bmm.svg?style=flat-square\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/dhth/bmm/releases\"\u003e\u003cimg alt=\"Commits since latest release\" src=\"https://img.shields.io/github/commits-since/dhth/bmm/latest?style=flat-square\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n`bmm` (stands for \"bookmarks manager\") lets you get to your bookmarks in a\nflash.\n\n![tui-2](https://github.com/user-attachments/assets/a3dc5fb7-d258-461e-86b5-f2498dfbd4dc)\n\nIt does so by storing your bookmarks locally, allowing you to quickly access,\nmanage, and search through them using various commands. `bmm` has a traditional\ncommand line interface that can be used standalone and/or integrated with other\ntools, and a textual user interface for easy browsing.\n\n🤔 Motivation\n---\n\nI'd been using [buku](https://github.com/jarun/buku) for managing my bookmarks\nvia the command line. It's a fantastic tool, but I was noticing some slowdown\nafter years of collecting bookmarks in it. I was curious if I could replicate\nthe subset of its functionality that I used while improving search performance.\nAdditionally, I missed having a TUI to browse bookmarks in. `bmm` started out as\na way to fulfill both goals. Turns out, it runs quite a lot faster than `buku`\n(check out benchmarks\n[here](https://github.com/dhth/bmm/actions/workflows/bench.yml)). I've now moved\nmy bookmark management completely to `bmm`, but `buku` remains an excellent\ntool, and those looking for a broader feature set should definitely check it\nout.\n\n💾 Installation\n---\n\n**homebrew**:\n\n```sh\nbrew install dhth/tap/bmm\n```\n\n**cargo**:\n\n```sh\ncargo install bmm\n```\n\nOr get the binaries directly from a Github [release][1]. Read more about\nverifying the authenticity of released artifacts\n[here](#-verifying-release-artifacts).\n\n⚡️ Usage\n---\n\n```text\nUsage: bmm [OPTIONS] \u003cCOMMAND\u003e\n\nCommands:\n  import    Import bookmarks from various sources\n  delete    Delete bookmarks\n  list      List bookmarks based on several kinds of queries\n  save      Save/update a bookmark\n  save-all  Save/update multiple bookmarks\n  search    Search bookmarks by matching over terms\n  show      Show bookmark details\n  tags      Interact with tags\n  tui       Open bmm's TUI\n  help      Print this message or the help of the given subcommand(s)\n\nOptions:\n      --db-path \u003cSTRING\u003e  Override bmm's database location (default: \u003cDATA_DIR\u003e/bmm/bmm.db)\n      --debug             Output debug information without doing anything\n  -h, --help              Print help (see more with '--help')\n```\n\n⌨ CLI mode\n---\n\n`bmm` allows every action it supports to be performed via its CLI. As such, it\ncan be easily integrated with other search tools (eg.\n[Alfred](https://www.alfredapp.com/), [fzf](https://github.com/junegunn/fzf),\netc.)\n\n![cli](https://github.com/user-attachments/assets/f8493e7c-8286-4fa4-8d49-6f34b5c5044b)\n\n### Importing existing bookmarks\n\n`bmm` allows importing bookmarks from various sources. It supports the following\ninput formats:\n\n- HTML (These are bookmark files exported by browsers like Firefox, Chrome, etc,\n  in the NETSCAPE-Bookmark-file-1 format.)\n- JSON\n- TXT\n\n```bash\nbmm import firefox.html\nbmm import bookmarks.json --dry-run\n\n# overwrite already saved attributes (title and tags) while importing\nbmm import bookmarks.txt --reset-missing-details\n\n# ignore errors related to bookmark title and tags\n# if title is too long, it'll be trimmed, some invalid tags will be corrected\nbmm import bookmarks.txt --ignore-attribute-errors\n```\n\n\u003cdetails\u003e\u003csummary\u003e An example HTML file\u003c/summary\u003e\n\n```html\n\u003c!DOCTYPE NETSCAPE-Bookmark-file-1\u003e\n\u003c!-- This is an automatically generated file.\n     It will be read and overwritten.\n     DO NOT EDIT! --\u003e\n\u003cMETA HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\"\u003e\n\u003cmeta http-equiv=\"Content-Security-Policy\"\n      content=\"default-src 'self'; script-src 'none'; img-src data: *; object-src 'none'\"\u003e\u003c/meta\u003e\n\u003cTITLE\u003eBookmarks\u003c/TITLE\u003e\n\u003cH1\u003eBookmarks Menu\u003c/H1\u003e\n\n\u003cDL\u003e\u003cp\u003e\n    \u003cDT\u003e\u003cH3 ADD_DATE=\"1736450822\" LAST_MODIFIED=\"1739920697\" PERSONAL_TOOLBAR_FOLDER=\"true\"\u003eBookmarks Toolbar\u003c/H3\u003e\n    \u003cDL\u003e\u003cp\u003e\n        \u003cDT\u003e\u003cH3 ADD_DATE=\"1739896938\" LAST_MODIFIED=\"1739920670\"\u003eproductivity\u003c/H3\u003e\n        \u003cDL\u003e\u003cp\u003e\n            \u003cDT\u003e\u003cH3 ADD_DATE=\"1739896992\" LAST_MODIFIED=\"1739920767\"\u003ecrates\u003c/H3\u003e\n            \u003cDL\u003e\u003cp\u003e\n                \u003cDT\u003e\u003cA HREF=\"https://crates.io/crates/sqlx\" ADD_DATE=\"1739897020\" LAST_MODIFIED=\"1739897041\" ICON_URI=\"https://crates.io/favicon.ico\" TAGS=\"crates,rust\"\u003esqlx - crates.io: Rust Package Registry\u003c/A\u003e\n            \u003c/DL\u003e\u003cp\u003e\n            \u003cDT\u003e\u003cA HREF=\"https://github.com/dhth/omm\" ADD_DATE=\"1739920615\" LAST_MODIFIED=\"1739920646\" ICON_URI=\"https://github.com/fluidicon.png\" TAGS=\"productivity,tools\"\u003eGitHub - dhth/omm: on-my-mind: a keyboard-driven task manager for the command line\u003c/A\u003e\n            \u003cDT\u003e\u003cA HREF=\"https://github.com/dhth/hours\" ADD_DATE=\"1739920661\" LAST_MODIFIED=\"1739920670\" ICON_URI=\"https://github.com/fluidicon.png\" TAGS=\"productivity,tools\"\u003eGitHub - dhth/hours: A no-frills time tracking toolkit for command line nerds\u003c/A\u003e\n        \u003c/DL\u003e\u003cp\u003e\n        \u003cDT\u003e\u003cA HREF=\"https://github.com/dhth/bmm\" ADD_DATE=\"1739920697\" LAST_MODIFIED=\"1739920739\" ICON_URI=\"https://github.com/fluidicon.png\" TAGS=\"tools\"\u003eGitHub - dhth/bmm: get to your bookmarks in a flash\u003c/A\u003e\n    \u003c/DL\u003e\u003cp\u003e\n\u003c/DL\u003e\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003e An example JSON file\u003c/summary\u003e\n\n```json\n[\n  {\n    \"uri\": \"https://github.com/dhth/bmm\",\n    \"title\": null,\n    \"tags\": \"tools,bookmarks\"\n  },\n  {\n    \"uri\": \"https://github.com/dhth/omm\",\n    \"title\": \"on-my-mind: a keyboard-driven task manager for the command line\",\n    \"tags\": null\n  }\n]\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003e An example TXT file\u003c/summary\u003e\n\n```text\nhttps://github.com/dhth/bmm\nhttps://github.com/dhth/omm\nhttps://github.com/dhth/hours\n```\n\u003c/details\u003e\n\n### Saving/updating a bookmark\n\n```bash\n# save a new URI\nbmm save https://github.com/dhth/bmm\n\n# save a new URI with title and tags\nbmm save https://github.com/dhth/omm \\\n    --title 'a keyboard-driven task manager for the command line' \\\n    --tags 'tools,productivity'\n\n# update the title of a previously saved bookmark\nbmm save https://github.com/dhth/bmm \\\n    --title 'yet another bookmarking tool'\n\n# append to the tags of a previously saved bookmark\nbmm save https://github.com/dhth/omm \\\n    --tags 'task-manager'\n\n# use your editor to provide details\nbmm save https://github.com/dhth/bmm -e\n```\n\n### Saving/updating several bookmarks at a time\n\n```bash\n# save/update multiple bookmarks via arguments\nbmm save \\\n    'https://github.com/dhth/bmm' \\\n    'https://github.com/dhth/omm' \\\n    --tags 'cli,bookmarks'\n\n# save/update multiple bookmarks via stdin\ncat \u003c\u003c EOF | bmm save --tags tools --reset-missing-details -s\nhttps://github.com/dhth/bmm\nhttps://github.com/dhth/omm\nhttps://github.com/dhth/hours\nEOF\n```\n\n### Listing bookmarks based on several queries\n\n`bmm` allows listing bookmarks based on queries on bookmark uri/title/tags. The\nfirst two are pattern matched, while the last is matched exactly.\n\n```bash\nbmm list --uri 'github.com' \\\n    --title 'command line' \\\n    --tags 'tools,productivity' \\\n    --format json\n```\n\n### Searching bookmarks by terms\n\nSometimes you want to search for bookmarks without being very granular. The\n`search` command allows you to do so. It accepts a list of terms, and will\nreturn bookmarks where all of the terms are matched over any attribute or tag\nbelonging to a bookmark. You can also open the results in `bmm`'s TUI.\n\n```bash\n# search bookmarks based on search terms\nbmm search cli rust tool bookmarks --format delimited\n\n# open search results in bmm's TUI\nbmm search cli rust tool bookmarks --tui\n```\n\n### Show bookmark details\n\n```bash\nbmm show 'https://github.com/dhth/bmm'\n```\n\n### Interaction with tags\n\n```bash\n# Show saved tags\nbmm tags list \\\n    --format json \\\n    --show-stats\n\n# open saved tags in bmm's TUI\nbmm tags list --tui\n\n# rename tag\nbmm tags rename old-tag new-tag\n\n# delete tags \nbmm tags delete tag1 tag2 tag3\n```\n\n### Delete bookmarks\n\n```bash\nbmm delete 'https://github.com/dhth/bmm' 'https://github.com/dhth/omm'\n\n# skip confirmation\nbmm delete --yes 'https://github.com/dhth/bmm'\n```\n\n📟 TUI mode\n---\n\nTo allow for easy browsing, `bmm` ships with its own TUI. It can be launched\neither in a generic mode (via `bmm tui`) or in the context of a specific command\n(e.g., `bmm search tools --tui`).\n\nThe TUI lets you do the following:\n\n- Search bookmarks based on terms\n- List all tags\n- View bookmarks that hold a tag\n\nFeature requests for the TUI can be submitted via `bmm`'s [issues\npage](https://github.com/dhth/bmm/issues).\n\n![tui](https://github.com/user-attachments/assets/6ca63039-8872-4520-93da-1576cc0cf8ec)\n\n### TUI Reference Manual\n\n```text\nbmm has three views.\n\n- Bookmarks List View\n- Tags List View\n- Help View\n\nKeymaps\n---\n\nGeneral\n    ?                    show/hide help view\n    Esc / q              go back/reset input/exit\n    j / Down             go down in a list\n    k / Up               go up in a list\n\nBookmarks List View\n    s                    show search input\n    Enter                submit search query\n    t                    show Tags List View (when search is not active)\n    o                    open URI in browser\n    y                    copy URI under cursor to system clipboard\n    Y                    copy all URIs to system clipboard\n\nTags List View\n    Enter                show bookmarks that are tagged with the one under cursor\n```\n\n🔐 Verifying release artifacts\n---\n\nIn case you get the `bmm` binary directly from a [release][1], you may want to\nverify its authenticity. Checksums are applied to all released artifacts, and\nthe resulting checksum file is attested using [Github Attestations][2].\n\nSteps to verify (replace `A.B.C` in the commands below with the version you\nwant):\n\n1. Download the sha256 checksum file for your platform from the release:\n\n   ```shell\n   curl -sSLO https://github.com/dhth/bmm/releases/download/vA.B.C/bmm-x86_64-unknown-linux-gnu.tar.xz.sha256\n   ```\n\n2. Verify the integrity of the checksum file using [gh][3].\n\n   ```shell\n   gh attestation verify bmm-x86_64-unknown-linux-gnu.tar.xz.sha256 --repo dhth/bmm\n   ```\n\n3. Download the compressed archive you want, and validate its checksum:\n\n   ```shell\n   curl -sSLO https://github.com/dhth/bmm/releases/download/vA.B.C/bmm-x86_64-unknown-linux-gnu.tar.xz\n   sha256sum --ignore-missing -c bmm-x86_64-unknown-linux-gnu.tar.xz.sha256\n   ```\n\n3. If checksum validation goes through, uncompress the archive:\n\n   ```shell\n   tar -xzf bmm-x86_64-unknown-linux-gnu.tar.xz\n   cd bmm-x86_64-unknown-linux-gnu\n   ./bmm\n   # profit!\n   ```\n\n🙏 Acknowledgements\n---\n\n`bmm` sits on the shoulders of the following crates:\n\n- [clap](https://crates.io/crates/clap)\n- [csv](https://crates.io/crates/csv)\n- [dirs](https://crates.io/crates/dirs)\n- [lazy_static](https://crates.io/crates/lazy_static)\n- [once_cell](https://crates.io/crates/once_cell)\n- [open](https://crates.io/crates/open)\n- [ratatui](https://crates.io/crates/ratatui)\n- [regex](https://crates.io/crates/regex)\n- [select](https://crates.io/crates/select)\n- [serde](https://crates.io/crates/serde)\n- [serde_json](https://crates.io/crates/serde_json)\n- [sqlx](https://crates.io/crates/sqlx)\n- [tempfile](https://crates.io/crates/tempfile)\n- [thiserror](https://crates.io/crates/thiserror)\n- [tokio](https://crates.io/crates/tokio)\n- [input](https://crates.io/crates/tui-input)\n- [url](https://crates.io/crates/url)\n- [which](https://crates.io/crates/which)\n\n[1]: https://github.com/dhth/bmm/releases\n[2]: https://github.blog/news-insights/product-news/introducing-artifact-attestations-now-in-public-beta/\n[3]: https://github.com/cli/cli\n","funding_links":[],"categories":["Rust","\u003ca name=\"Rust\"\u003e\u003c/a\u003eRust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhth%2Fbmm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdhth%2Fbmm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhth%2Fbmm/lists"}