Text search for Firefox history
Project description
Foxhole - Local Fulltext Search For Firefox History
Local-first tool to store and search your Firefox browsing history in full text.
Motivation: browsers only store URL and title in the history. But what if you don't remember those, only the content of the website? This tools enables full text search for your browser history.
It works like this: Every time a tab is loaded, the content of that website is
sent using a local host connection, which stores the content in an SQLITE
database. You can then search using either the built-in SQLITE search, grep
(see grepping below), or whatever other method you want.
-
Will this save my bank-statements? Not if you blacklist the bank's webpage (see the notes regarding ignoring webpages under Installation. I mean, who am I to judge? Maybe you want that. If you accidentally save information you can prune it using the built-in
foxhole-prunecommand (see here for more details). -
I don't trust you. Me neither. However, the codebase is minimal, and I recommend looking through what happens when
foxholesaves the information. The webextension is here and the native host connector is here. -
Why SQLITE instead of local storage? Extensions like Falcon utilize local storage, and provides a nice frontend for search directly from Firefox. However, local storage can be a hassle. What if you want to transfer data without transferring the Firefox profile? What if you want to do something external with the browser history? Good luck getting it out from local storage. Here, you only have a standard run-of-the-mill SQLITE file.
-
Why not embedding search? Initially the extension was created with embeddings in mind, however, during evaluation the performance was not worth the cost in inference time and storage increase. With this implementation you can simply do multiple searches, trying different keywords instead.
-
Why can't I just install an extension? Why do I have to install a python script as well? Since browsers are sandboxed, host native messaging is the only way to get the data from the browser outside the local machine. This is good, seeing as it's harder to write malicious extensions. It does mean extension like this are a bit cumbersome to install.
Installation
pipx install foxhole
foxhole-install
Then install the Firefox extension by downloading the .xpi from latest release
You can of course install using just pip if you have global pip (like on
Mac/Windows) or venv instead of using pipx.
Ignoring webpages
In your data directory a file called IGNORE will be created during
installation. Put urls you don't want saved in here, or (imo) those pages you
keep returning to often like your search engine which will not provide highly
relevant search results for this type of browser history search (ideally we
only want "content" sites in our index).
Usage
Search
Here's an example search:
foxhole android phone with buttons
Which in my case returns:
1628 https://www.reddit.com/r/dumbphones/comments/1dmnm2v/my_ideal_qin_f21_pro_setup/ My ideal Qin F21 Pro setup : r/dumbphones
1626 https://github.com/AlikornSause/Notes-on-QIN-F21-PRO#keypad-and-buttons AlikornSause/Notes-on-QIN-F21-PRO: My notes on the Duoqin F21 pro dumb/feature phone
1646 https://github.com/AlikornSause/Notes-on-QIN-F21-PRO?tab=readme-ov-file#hardware-versions AlikornSause/Notes-on-QIN-F21-PRO: My notes on the Duoqin F21 pro dumb/feature phone
867 https://xdaforums.com/t/app-4-2-t9-launcher.3002969/ [APP][4.2+] T9 Launcher | XDA Forums
1625 https://xdaforums.com/t/guide-information-guide-for-qin-f21-pro.4726912/ [GUIDE][INFORMATION] Guide for Qin F21 Pro | XDA Forums
752 https://www.reddit.com/r/dumbphones/comments/11zqtl6/my_thoughts_about_the_qin_f21_pro/ My thoughts about the Qin F21 Pro : r/dumbphones
1970 https://old.reddit.com/r/ereader/comments/1018vlb/am_i_missing_something_or_is_an_android_ereader/ Am I missing something or is an Android eReader generally a "bad" idea? : ereader
2859 https://old.reddit.com/r/eink/comments/xuvlwc/budget_eink_smart_devices/ Budget E-Ink Smart Devices : eink
763 https://github.com/bkerler/mtkclient bkerler/mtkclient: MTK reverse engineering and flash tool
4507 https://shkspr.mobi/blog/2025/05/whatever-happened-to-cheap-ereaders/ Whatever happened to cheap eReaders? – Terence Eden’s Blog
FTS5 supports additional search syntax to refine queries. For the complete set of options, see the FTS5 Documentation. Key operators include:
-
AND: Matches documents containing both terms.
Example:foxhole perry AND whitereturns documents that include both "perry" and "white". -
OR: Matches documents containing either term.
Example:foxhole perry OR whitereturns documents that include either "perry" or "white". -
NOT: Excludes documents containing the specified term.
Example:foxhole perry NOT whitereturns documents that include "perry" but exclude "white". -
"<phrase>": Matches exact phrases.
Example:foxhole "perry white"returns documents containing the exact phrase "perry white", not just the individual terms.
Viewing
The included foxhole-view command lets you view one entry from the database, given an ID (which you get by searching, see above). For example, to print out the content of the web page with ID 1111:
foxhole-view 1111
Pruning
By default the extension just keeps storing documents in the database. You
might want to prune this eventually though, for storage reasons, or if you
forgot to add a domain to IGNORE. The foxhole-prune command deals with this.
You can either prune by keeping only the documents x days back, only the most
recent x documents, or by pruning using the ignore_list. For example,
here's how you would prune using the ignore list:
foxhole-prune --ignore_list
See foxhole-prune -h for full usage description.
Grepping
You can also use grep/awk in a UNIX fashion. The included foxhole-ls
command lists all documents as tab-separated rows like (id, url, title, text).
The text column is stripped for new lines to enable grepping.
For example, if you'd like to print the ids, url and title of all documents containing "perry white" without regards for case:
foxhole-ls | grep -i "perry white" | cut -f 1,2,3
Which for my current document database returns:
9 https://smallville.fandom.com/wiki/Clark_Kent Clark Kent | Smallville Wiki | Fandom
336 https://smallville.fandom.com/wiki/Jonathan_Kent Jonathan Kent | Smallville Wiki | Fandom
337 https://smallville.fandom.com/wiki/Martha_Kent Martha Kent | Smallville Wiki | Fandom
898 https://en.wikipedia.org/wiki/Lana_Lang Lana Lang - Wikipedia
2103 https://smallville.fandom.com/wiki/Martha_Kent#Smallville_TV_Series Martha Kent | Smallville Wiki | Fandom
4166 https://en.wikipedia.org/wiki/Perry_White Perry White - Wikipedia
4167 https://en.wikipedia.org/wiki/Lane_Smith Lane Smith - Wikipedia
4168 https://en.wikipedia.org/wiki/Jonathan_and_Martha_Kent Jonathan and Martha Kent - Wikipedia
This does take about ~1s per query since the SQLITE API for Python isn't super fast for reads. If you have SQLITE installed you can do blazingly fast grepping using for example (if you're on Linux/Mac):
sqlite3 ~/.local/share/foxhole/doc.sqlite "SELECT id,url,title,text FROM pages;" | \
grep -i "perry white" | \
cut -f 1,2,3 -d "|"
Which would be easy to add as a function to your bashrc.
If you're on Windows/Mac/Linux and the command above isn't working you might
have another location for your data directory. Print that out by running
foxhole -h
Development Installation
pip3 install -e .
For Windows, make sure that python3 is installed from the Python website and
is added to PATH. You can't do WSL here AFAICT.
Install the host connection using:
foxhole-install
Finally, install the web-extension by going to
about:debugging#/runtime/this-firefox
in Firefox, and adding manifest.json using "Load temporary Add-on".
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file foxhole-0.0.0.tar.gz.
File metadata
- Download URL: foxhole-0.0.0.tar.gz
- Upload date:
- Size: 30.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ba06c4246725acdd6579801183b65dc342b47bd6da8060c80f21703d7d23f0b
|
|
| MD5 |
b18641f1daabbf1c1a368b333b0c9868
|
|
| BLAKE2b-256 |
8cbc0161ec33b28257c09d370eb5548e7e84e4dbcd152e0fd28dbfbe6a792c6d
|
Provenance
The following attestation bundles were made for foxhole-0.0.0.tar.gz:
Publisher:
release.yaml on skogsgren/foxhole
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
foxhole-0.0.0.tar.gz -
Subject digest:
4ba06c4246725acdd6579801183b65dc342b47bd6da8060c80f21703d7d23f0b - Sigstore transparency entry: 1365623316
- Sigstore integration time:
-
Permalink:
skogsgren/foxhole@0487cfd3be0944ce16789dedb534eba646a88bc9 -
Branch / Tag:
refs/tags/0.1.5 - Owner: https://github.com/skogsgren
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@0487cfd3be0944ce16789dedb534eba646a88bc9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file foxhole-0.0.0-py3-none-any.whl.
File metadata
- Download URL: foxhole-0.0.0-py3-none-any.whl
- Upload date:
- Size: 23.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f688f58fca95f73e3f77ebb861fcde5bf3cabc5db50758816733f111084a7e66
|
|
| MD5 |
3592823d435a605cb2cde79cd187c5e1
|
|
| BLAKE2b-256 |
f87b1c5bc60c5f53ab5f731d182e93d6034471d627c5759bd4e759a7c68a92c5
|
Provenance
The following attestation bundles were made for foxhole-0.0.0-py3-none-any.whl:
Publisher:
release.yaml on skogsgren/foxhole
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
foxhole-0.0.0-py3-none-any.whl -
Subject digest:
f688f58fca95f73e3f77ebb861fcde5bf3cabc5db50758816733f111084a7e66 - Sigstore transparency entry: 1365623414
- Sigstore integration time:
-
Permalink:
skogsgren/foxhole@0487cfd3be0944ce16789dedb534eba646a88bc9 -
Branch / Tag:
refs/tags/0.1.5 - Owner: https://github.com/skogsgren
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@0487cfd3be0944ce16789dedb534eba646a88bc9 -
Trigger Event:
release
-
Statement type: