terminalmage / tridactyl

Implementing Vimperator/Pentadactyl as a WebExtension.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tridactyl logo

Tridactyl Build Status Matrix Chat Gitter Chat

Replace Firefox's default control mechanism with one modelled on the one true editor, Vim.


Get our "beta" builds! These are updated on AMO with each commit to master on this repo; your browser will automatically update from there once a day. If you want more frequent updates, you can change extensions.update.interval in about:config to whatever time you want, say, 15 minutes (900 seconds).

Type :help for online help once you're in :)

Remember that tridactyl cannot run on any page on addons.mozilla.org, about:*, data:*, view-source:* and file:*. We're sorry about that and we're working with Firefox to improve this situation by removing restrictions on existing APIs and developing a new API.

Highlighted features:

  • Press b to bring up a list of open tabs in the current window; you can type the tab ID or part of the title or URL to choose a tab (the buffer list doesn't show which one you've selected yet, but it does work)
  • Press I to enter ignore mode. Shift + Escape to return to normal mode.
  • Press f to start "hint mode", F to open in background
  • Press o to :open a different page
  • Press s if you want to search for something that looks like a domain name or URL
  • Bind new commands with e.g. :bind J tabprev. Type :help bind to see help on custom binds.
  • Type :help for online help
  • Use yy to copy the current page URL to your clipboard
  • ]] and [[ to navigate through the pages of comics, paginated articles, etc.
  • Pressing ZZ will close all tabs and windows, but it will only "save" them if your about:preferences are set to "show your tabs and windows from last time"

WebExtension-related issues

  • Do not try to navigate to any about:* pages using :open as it will fail silently.
  • Firefox will not load Tridactyl on addons.mozilla.org, about:*, some file:* URIs, view-source:*, or data:*. On these pages Ctrl-L (or F6), Ctrl-Tab and Ctrl-W are your escape hatches.
  • Tridactyl does not currently support changing/hiding the Firefox GUI, but you can do it yourself by changing your userChrome. We've developed quite a good one that makes windowed Firefox behave more like full-screen mode, but it's well commented, so you can make your own.


Building and installing


git clone https://github.com/cmcaine/tridactyl.git
cd tridactyl
npm install
npm run build

Each time package.json or package-lock.json change after you checkout or pull, you should run npm install again.

Addon is built in tridactyl/build. Load it as a temporary addon in firefox with about:debugging or see Development loop. The addon should work in Firefox 52+, but we're only deliberately supporting >=57.

If you want to install a local copy of the add-on into your developer or nightly build of firefox then you can enable installing unsigned add-ons and then build it like so:

# Build tridactyl if you haven't done that yet
npm run build
# Package for a browser
$(npm bin)/web-ext build -s build

If you want to build a signed copy (e.g. for the non-developer release), you can do that with web-ext sign. You'll need some keys for AMO and to edit the application id in src/manifest.json. There's a helper script in scripts/sign that's used by our build bot and for manual releases.

Development loop

npm run watch &
$(npm bin)/web-ext run -s build

This will compile and deploy your files each time you save them.


A pre-commit hook is added by npm install that simply runs npm test. If you know that your commit doesn't break the tests you can commit with git commit -n to ignore the hooks. If you're making a PR, travis will check your build anyway.


Ask in #tridactyl on matrix.org, freenode, or gitter. We're friendly!

Default keybindings are currently best discovered by reading the source for the normal mode parser.

Development notes are in the doc directory, but they're mostly out of date now. Code is quite short and not too badly commented, though.

Principles and objectives


  • Keyboard > mouse
  • default keybinds should be Vim-like
  • actions should be composable and repeatable
  • ex mode should expose all the browser functionality anyone might want
  • Arguable: most (all?) actions should have an ex mode version (departure from Vim?)
  • users can map and define their own actions and commands

Other objectives:

  • be fast - the whole point of a keyboard interface is to be more efficient, don't compromise that with slow code
  • don't crash - we're the new UI and we shouldn't crash
  • be maintainable - code should be well documented, reasoned about and tested.

Non-objectives for v1:

  • insert mode (embedded (n)vim would be good for future)
  • caret or visual mode - I'm not good enough at vim to find these easier than selecting with the mouse, and they require text motions, which I would prefer to delegate to vim.

Prior art:

  • pentadactyl/vimperator - dying with XUL
  • cVim/vimium/saka-key
  • vimfx - transitioning to WebExtensions, but no ex commands
  • qutebrowser/jumanji - see standalone.md.


What we learnt from these notes has been condensed in bug-message.md.

Evaluating prior art

cVim and vimium implement some kind of vim experience using webextensions. Neither allow you to modify the browser UI.

Common issues

  1. can't operate on some URLs (chrome store, chrome://, view-source://)
  2. can't escape location bar
  3. can't hide chrome UI
  4. can't suppress all chrome keybinds
  5. can't override some browser shortcuts
  6. bad js kills the UI (but the same bad js locks up the whole of firefox, so y'know...)

In conclusion, a privileged keyboard webextension will help with #1,2,4,5; #3,#1 (for visual changes) and maybe #2 need a ui API. #1 might not be applicable to ff content scripts.



Very lightweight, but what is there is actually really nice. Easily fixable issues: no command mode for the features they do have; some odd default maps; mappings are done by function name rather than key ('map b Vomnibar.activateTabSelection' rather than 'map b T'). Possibly fixable issues: plugin support (source), arbitrary js eval for mappings, marks are per tab, jumplist.


  • command mode
  • jumplist
  • :js
  • lots more.

Improvements over vimperator:

  • regex search
  • buffer switch between windows



Vim mode chromium plugin written at least partly in coffeescript. Source is not documented, but it's not so bad either (at least it's in coffeescript). Default maps are not to my liking, but that's hardly surprising. I don't see how to make new maps, tho. UI appearance is poor, appears to be influenced by context's css.


  • map!
  • sensible default maps
  • UI style
  • documentation for users or developers
  • plugin/eval support
  • jumplist, etc

May be worth taking code from, could consider forking it, but would need to review code more carefully for quality issues.



Written in uncommented javascript. But user experience is pretty good. Autocompletion in command mode is very good and it has a decent chunk of the vimperator features implemented.


  • decent documentation
  • can't map some characters that vimium can
  • jumplist

Improvements over vimperator:

  • autocompletion is much faster
  • allegedly lets you edit with vim


This is an early draft and may be entirely replaced.

ex-commands as functions (typed and with helper functions in some other scope):

  • open(url)
  • scroll(x=+10)
  • mark()
  • map(actions, keys)
  • ...

helper functions for actions:

  • scroll-x, scroll-y
  • jumplist.get/getrelative/store
  • undo-tab-deletion

Count and range:

  • given as arguments?
  • just repeat the call 'count' times?

for default actions, a mapping from key to helper function.

Generated parsers (command and normal mode):

  • command mode pretty conventional. Include type checking.

  • For auto-complete to work, need to be able to parse partial results sensibly.

  • actions will be a slightly weirder grammar:

  • More permissive

  • Time sensitive

  • In vim, actions compose as you write them (d takes a motion as an argument, for example), I can't think of any examples of this in vimperator: actions sometimes take a count or argument, but that argument is never an action.

  • If actions did compose, we would have to give them types, as vim does for motions, and the parsing would be less trivial.

Autocomplete functions for commands:

  • Split from implementation of command.
  • Could perhaps be automatic from command's parameter types?

Some actions have their own interactive mini-mode:

  • hints
  • searching

Logo acknowledgement

The logo was designed by Jake Beazley using free vector art by www.Vecteezy.com

ezoic increase your site revenue


Implementing Vimperator/Pentadactyl as a WebExtension.



Language:TypeScript 76.6%Language:JavaScript 12.4%Language:CSS 4.6%Language:Python 3.8%Language:Shell 1.2%Language:CoffeeScript 0.9%Language:HTML 0.5%