TabFS is a browser extension that
mounts your browser tabs as a filesystem on your computer.
Out of the box, it supports Chrome and (to a lesser extent1)
Firefox and Safari, on macOS and Linux.2
(update: You can now sponsor me to help support further
development of TabFS :-)
Each of your open tabs is mapped to a folder.
The files inside a tab’s folder directly reflect (and can control) the
state of that tab in your browser.
Going through the files inside a tab’s folder. For
example, the url.txt, text.txt, and title.txt files tell me those live
properties of this tab
(Read more up-to-date documentation for all of
TabFS’s files here.)
This gives you a ton of power, because now you can apply all the
existing tools
on your computer that already know how to deal with files — terminal
commands, scripting languages, point-and-click explorers, etc — and
use them to control and communicate with your browser.
Now you don’t need to code up a browser extension from
scratch every
time you want to do anything. You can write a script that talks to
your browser in, like, a melange of Python and bash, and you can save
it as a single ordinary
file that you
can run whenever, and it’s no different from scripting any other part
of your computer.
table of contents
Examples of stuff you can do!3
(assuming your current directory is the fs
subdirectory of the git
repo and you have the extension running)
List the titles of all the tabs you have open
$ cat mnt/tabs/by-id/*/title.txt
GitHub
Extensions
TabFS/install.sh at master · osnr/TabFS
Alternative Extension Distribution Options - Google Chrome
Web Store Hosting and Updating - Google Chrome
Home / Twitter
...
Cull tabs like any other files
Selecting and deleting a bunch of tabs in my file manager
I’m using Dired in Emacs here, but you could use whatever tools you
already feel comfortable managing your files with.
Close all Stack Overflow tabs
$ rm mnt/tabs/by-title/*Stack_Overflow*
or (older / more explicit)
$ echo remove | tee -a mnt/tabs/by-title/*Stack_Overflow*/control
btw
(this task, removing all tabs whose titles contain some string, is a
little contrived, but it’s not that unrealistic, right?)
(now… how would you do this without TabFS? I honestly have no
idea, off the top of my head. like, how do you even get the titles of
tabs? how do you tell the browser to close them?)
(I looked up the APIs, and, OK, if you’re already in a browser
extension, in a ‘background script’ inside the extension, and your
extension has the tabs
permission — this already requires you to
make 2 separate files and hop between your browser and your text
editor to set it all up! — you can do
this:
chrome.tabs.query({}, tabs => chrome.tabs.remove(tabs.filter(tab => tab.title.includes('Stack Overflow')).map(tab => tab.id)))
)
(not terrible, but look at all that upfront overhead to get it set
up. and it’s not all that discoverable. and what if you want to reuse
this later, or plug it into some larger pipeline of tools on your
computer, or give it a visual interface? the jump in complexity once
you need to communicate with anything — possibly setting up a
WebSocket, setting up handlers and a state machine — is pretty
horrifying)
(but to be honest, I wouldn’t even have conceived of this as a thing I
could do in the first place)
Save text of all tabs to a file
$ cat mnt/tabs/by-id/*/text.txt > text-of-all-tabs.txt
Evaluate JavaScript on a page / watch expressions: demo
(was evals
in linked demo, is now renamed to watches
)
$ touch mnt/tabs/last-focused/watches/'document.body.style.background = "green"'
$ touch mnt/tabs/last-focused/watches/'alert("hi!")'
$ touch mnt/tabs/last-focused/watches/'2 + 2'
$ cat mnt/tabs/last-focused/watches/'2 + 2'
4
$ touch mnt/tabs/last-focused/watches/window.scrollY
Now you can cat window.scrollY
and see where you are scrolled on the
page at any time.
Could make an ad-hoc
dashboard
around a Web page: a bunch of terminal windows floating around your
screen, each sitting in a loop and using cat
to monitor a different
variable.
Get images / scripts / other resource files from page
(TODO: document better, put in screenshots)
The debugger/
subdirectory
in each tab folder has synthetic files that let you access loaded
resources (in debugger/resources/
) and scripts (in
debugger/scripts/
).
Images will show up as actual PNG or JPEG files, scripts as actual JS
files, and so on. (this is experimental.)
(TODO: edit the images in place? you can already kinda edit the
scripts in place)
Retrieve what’s playing on YouTube Music: youtube-music-tabfs
Reload an extension when you edit its source code
Suppose you’re working on a Chrome extension (apart from this
one). It’s a pain to reload the extension (and possibly affected Web
pages) every time you change its code. There’s a Stack Overflow
post
with ways to automate this, but they’re all sort of hacky. You need
yet another extension, or you need to tack weird permissions onto your
work-in-progress extension, and you don’t just get a command you can
trigger from your editor or shell to refresh the extension.
TabFS lets you do all this in an ordinary shell
script.
You don’t have to write any browser-side code at all.
This script turns an extension (this one’s title is “Playgroundize
DevTools Protocol”) off, then turns it back on, then reloads any tabs
that have the relevant pages open (in this case, I decided it’s tabs
whose titles start with “Chrome Dev”):
#!/bin/bash -eux
echo false > mnt/extensions/Playg*/enabled
echo true > mnt/extensions/Playg*/enabled
echo reload | tee mnt/tabs/by-title/Chrome_Dev*/control
I mapped this script to Ctrl-. in my text editor, and now I just hit
that every time I want to reload my extension code.
TODO: Live edit a running Web page
edit page.html
in the tab folder. I guess it could just stomp
outerHTML at first, eventually could do something more sophisticated
then you can use your existing text editor! and you’ll always know
that if the file saved, then it’s up to date in the browser. no flaky
watcher that you’re not sure if it’s working
(it would be cool to have a persistent storage story here
also. I like the idea of being able to put arbitrary files anywhere in
the subtree, actually, because then you could use git and emacs
autosave and stuff for free… hmm)
TODO: Import data (JSON? XLS? JS?)
drag a JSON file foo.json
into the imports
subfolder of the tab
and it shows up as the object imports.foo
in JS. (modify
imports.foo
in JS and then read imports/foo.json
and you read the
changes back?)
import a plotting library or whatever the same way? dragging
plotlib.js
into imports/plotlib.js
and then calling
imports.plotlib()
to invoke that JS file
the browser has a lot of potential power as an interactive programming
environment, one where graphics come as
naturally as
console I/O do in most programming languages. i think something that
holds it back that is underexplored is lack of ability to just… drag
files in and manage them with decent tools. many Web-based ‘IDEs’ have
to reinvent file management, etc from scratch, and it’s like a
separate universe from the rest of your computer, and migrating
between one and the other is a real pain (if you want to use some
Python library to munge some data and then have a Web-based
visualization of it, for instance, or if you want to version files
inside it, or make snapshots so you feel
comfortable
trying stuff, etc).
(what would the persistent storage story here be? localStorage? it’s
interesting because I almost want each tab to be less of a
commodity,
less
disposable,
since now it’s the site I’m dragging