Version 2.2.4

Nyxt manual

This manual first includes the tutorial, then covers the configuration of Nyxt.

Core concepts

Keybindings and commands

Commands are invoked by pressing specific keys or from the execute-command menu (C-space ).

Keybindings are represented like this: 'C-x'. In this example, 'C' is a shortcut for the modifier 'control', and 'x' represents the character 'x'. To input the 'C-x' keybinding you would keep 'control' pressed and then hit 'x'. Multiple key presses can be chained: in 'C-x C-s', you would have to press 'C-x', and then press 'C-s'.

Modifier keys legend:

Modifiers can be remapped, see the modifier-translator slot of the gtk-browser class.

Quickstart keys


Nyxt uses the concept of buffers instead of tabs. Unlike tabs, buffers are fully separated, each buffer having its own behavior and settings.


Each buffer has its own list of modes, ordered by priority. A mode is a set of functions, hooks, keybindings and other facilities that may modify the behavior of a buffer. For example, 'blocker-mode' can be used for domain-based adblocking while 'noscript-mode' disables JavaScript.

Each buffer has separate instances of modes, which means that altering the settings of a mode in a buffer does not impact other buffers. Mode specific functions/commands are only available when a mode is enabled for the current buffer.

Each mode has an associated mode toggler which is a command of the same name that toggles the mode for the current buffer.

Prompt buffer

The prompt buffer is a menu that will appear when a command requests user input. For example, when invoking the set-url command, you must supply the URL you would like to navigate to. The prompt buffer can provide suggestions. The list of suggestions will automatically narrow down to those matching your input as you type.

Some commands support multiple selections, for instance delete-buffer can delete all selected buffers at once. When the input is changed and the suggestions are re-filtered, the selection is not altered even if the marked elements don't show.

When at least one suggestion is marked, only the marked suggestions are processed upon return. The suggestion under the cursor is not processed if not marked.

Message area

The message area represents a space (typically at the bottom of a window) where Nyxt outputs messages back to you. To view the history of all messages, invoke the command list-messages .

Status area

The status area is where information about the state of that buffer is printed (typically at the bottom of a window). By default, this includes the active modes, the URL, and the title of the current buffer.

Basic controls

Moving within a buffer

To move within a buffer, several commands are provided:

Setting the URL

When ambiguous URLs are inputted, Nyxt will attempt the best guess it can. If you do not supply a protocol in a URL, HTTPS will be assumed. To visit a site supporting only the less secure HTTP, you must explicitly type the full URL including the 'http://' prefix.

Switching buffers

Copy and paste

Unlike other web browsers, Nyxt provides powerful ways of copying and pasting content via different commands. Starting from:

Passing through webpage's data:

Leveraging password managers:

And more:

Link navigation

Link-hinting allows you to visit URLs on a page without using the mouse. Invoke one of the commands below: several hints will appear on screen and all links on the page will be listed in the prompt buffer. You can select the hints by matching against the hint, the URL or the title.

Using the buffer history

History is represented as a tree that you can traverse: when you go back in history, then follow a new URL, it effectively creates a new branch without deleting the old path. The tree makes sure you never lose track of where you've been.

You can also view a full tree of the history for a given buffer by invoking the command 'buffer-history-tree'.


Nyxt can search a single buffer or multiple buffers at the same time.

You can view suggestions for search results in the prompt buffer in one place rather than having to jump around in a buffer (or multiple buffers).


The bookmark file /home/doe/.local/share/nyxt/bookmarks.lisp is made to be human readable and editable. Bookmarks can have the following settings:

Bookmark-related commands

Application mode

The command application-mode forwards all keys to the renderer. For instance, using the default binding of Nyxt (web-cua-map ) the key-binding C-i executes autofill . Suppose a user is using their email client which also uses C-i for the italic command. Thus, after executing application-mode the C-i binding is associated with the webpage's italic command instead of autofill . Finally, the user can return to their configuration just by executing application-mode again.

Enable, disable, and toggle multiple modes

The command enable-mode allows the user to apply multiple modes (such as nosound-mode and dark-mode ) to multiple buffers at once. Conversely, it is possible to revert this action by executing disable-mode while choosing exactly the same buffers and modes previously selected. Finally, toggle-mode also allows activation and deactivation of multiple modes, but only for the current buffer.

Light navigation

Reduce bandwidth usage via:

Visual mode

Select text without a mouse. Nyxt's visual-mode imitates Vim's visual mode (and comes with the CUA and Emacs-like keybindings out of the box, too). Activate it with the visual-mode (UNBOUND) command.

Visual mode provides the following commands:

Commands designed to ease the use for CUA users (but available to all users):

A note for emacs-mode users: unlike in Emacs, in Nyxt the command toggle-mark (UNBOUND) is bound to Shift-space, as C-space is bound to 'execute-command, overriding any mode keybinding. If you want to toggle mark with C-space, you'll need to set your own override-map such that C-space is not bound. An example:

(define-configuration buffer
  ((override-map (let ((map (make-keymap "override-map")))
                   (define-key map
                     "M-x" 'execute-command)))))


Nyxt has many facilities for automation. For instance, it is possible to automate the reading experience:

Symmetrically, it is possible to automate the filling of forms:

In addition, it is possible to automate actions over time:

Or even automate actions based on conditions:

Nyxt also offers a no-code interface to build automation via Common Lisp macros:

Lastly, the command PROCESS-MODE must be highlighted:

PROCESS-MODE is actually a building block for other modes previously mentioned, such as REPEAT-MODE . The extension relationship goes further, since CRUISE-CONTROL-MODE is in its turn an extension and a composition of REPEAT-MODE and SCROLL-DOWN . Further extensions and compositions can be creatively tailor-made by users to automate their own use of Nyxt.


The Nyxt help system

Nyxt provides introspective and help capabilities. All commands, classes, slots, variables, functions and bindings can be inspected for definition and documentation.

A good starting point is to study the documentation of the classes browser , window , buffer and prompt-buffer .


Nyxt is written in the Common Lisp programming language which offers a great perk: everything in the browser can be customized by the user, even while it's running!

To get started with Common Lisp, we recommend checking out our web page: Learn Lisp . It contains numerous pointers to other resources, including free books both for beginners and seasoned programmers.

Nyxt provides a mechanism for new users unfamiliar with Lisp to customize Nyxt. Start by invoking the commands describe-class or describe-slot . You can press the button marked 'Configure' to change the value of a setting. The settings will be applied immediately and saved for future sessions. Please note that these settings will not alter existing object instances.

Settings created by Nyxt are stored in /home/doe/.config/nyxt/auto-config.lisp .

Any settings can be overridden manually by /home/doe/.config/nyxt/init.lisp .

The following section assumes knowledge of basic Common Lisp or a similar programming language.

Nyxt configuration can be persisted in the user file /home/doe/.config/nyxt/init.lisp (create the parent folders if necessary).


(define-configuration buffer
  ((default-modes (append '(noscript-mode) %slot-default%))))

The above turns on the 'noscript-mode' (disables JavaScript) by default for every buffer.

The define-configuration macro can be used to customize the slots of classes like the browser, buffers, windows, etc. Refer to the class and slot documentation for the individual details.

To find out about all modes known to Nyxt, run describe-command and type 'mode'.

Slot configuration

Slots store values that can be either accessed (get) or changed (set). Setting new values for slots allows many possibilities of customization. For instance, keyboard layouts vary across the world. The slot hints-alphabet has the default value of ABCDEFGHIJKLMNOPQRSTUVWXYZ . If the user has an American keyboard, they can do:

  1. Execute command describe-slot (f1 s) ;
  3. Select hints-alphabet (user-web-mode class option);
  4. Press the button Configure , and;
  5. Insert the string "asfdghjkl" .

This will make link-hinting more comfortable for this user. In addition, other similar approaches of customization can be applied to slots such as spell-check-language , which can be expanded to do the spelling-check of other languages besides English.

Web buffers and internal buffers

A `internal-buffer' is used for Nyxt-specific, internal pages such as the tutorial and the description pages. A `web-buffer' is used for web pages. Both the `web-buffer' and the `internal-buffer' classes inherit from the `buffer' class.

You can configure a `buffer' slot and it will cascade down as a new default for both the `internal-buffer' and `web-buffer' classes- unless this slot is specialized by these child classes.

Keybinding configuration

Nyxt supports multiple bindings schemes such as CUA (the default), Emacs or vi. Changing scheme is as simple as running the corresponding mode, e.g. emacs-mode . To make the change persistent across sessions, add the following to your configuration:

You can create new scheme names with keymap:make-scheme-name . Also see the scheme-name class and the define-scheme macro.

To extend the bindings of a specific mode, you can extend the mode with define-configuration and extend its binding scheme with define-scheme . For example:

(define-configuration base-mode
    (define-scheme (:name-prefix "my-base" :import %slot-default%)
      (list "g b" (make-command switch-buffer* ()
                    (switch-buffer :current-is-last-p t)))))))

The override-map is a keymap that has priority over all other keymaps. By default, it has few bindings like the one for execute-command . You can use it to set keys globally:

(define-configuration buffer
  ((override-map (let ((map (make-keymap "override-map")))
                   (define-key map
                     "M-x" 'execute-command
                     "C-space" 'nothing)))))

The nothing command is useful to override bindings to do nothing. Note that it's possible to bind any command, including those of disabled modes that are not listed in execute-command .

In addition, a more flexible approach is to create your own mode with your custom keybindings. When this mode is added first to the buffer mode list, its keybindings have priorities over the other modes. Note that this kind of global keymaps also have priority over regular character insertion, so you should probably not bind anything without modifiers in such a keymap.

(defvar *my-keymap* (make-keymap "my-map"))
(define-key *my-keymap*
  "C-f" 'nyxt/web-mode:history-forwards
  "C-b" 'nyxt/web-mode:history-backwards)

(define-mode my-mode ()
  "Dummy mode for the custom key bindings in `*my-keymap*'."
  ((keymap-scheme (keymap:make-scheme
                   scheme:cua *my-keymap*
                   scheme:emacs *my-keymap*
                   scheme:vi-normal *my-keymap*))))

(define-configuration (buffer web-buffer)
  ((default-modes (append '(my-mode) %slot-default%))))

Bindings are subject to various translations as per keymap:*translator* . By default if it fails to find a binding it tries again with inverted shifts. For instance if C-x C-F fails to match anything C-x C-f is tried. See the default value of keymap:*translator* to learn how to custsomize it or set it to nil to disable all forms of translation.

Search engines

See the search-engines buffer slot documentation. Bookmarks can also be used as search engines, see the corresponding section.

Nyxt comes with some default search engines for, . The following example shows one way to add new search engines.

(defvar *my-search-engines*
   '("python3" "" "")
   '("doi" "" ""))
  "List of search engines.")

(define-configuration buffer
  ((search-engines (append (mapcar (lambda (engine) (apply 'make-search-engine engine))

Note that the last search engine is the default one. For example, in order to make python3 the default, the above code can be slightly modified as follows.

(defvar *my-search-engines*
   '("doi" "" "")
   '("python3" "" "")))

(define-configuration buffer
  ((search-engines (append %slot-default%
                           (mapcar (lambda (engine) (apply 'make-search-engine engine))


You can configure which actions to take depending on the URL to be loaded. For instance, you can configure which Torrent program to start to load magnet links. See theurl-dispatching-handler function documentation.


See the list-downloads command and the download-path buffer slot documentation.

Proxy and Tor

See the proxy-mode documentation.

Custom commands

Creating your own invokable commands is similar to creating a Common Lisp function, except the form is define-command instead of defun . If you want this command to be invokable outside of the context of a mode, use define-command-global .


(define-command-global bookmark-url ()
  "Query the user which URL to bookmark."
  (let ((url (prompt
              :prompt "Bookmark URL"
              :sources (make-instance 'prompter:raw-source))))
    (bookmark-add url)))

See the prompt-buffer class documentation for how to write write custom prompt-buffers.


Hooks provide a powerful mechanism to tweak the behaviour of various events that occur in the context of windows, buffers, modes, etc.

A hook holds a list of handlers . Handlers are named and typed functions. Each hook has a dedicated handler constructor.

Hooks can be 'run', that is, their handlers are run according to the combination slot of the hook. This combination is a function of the handlers. Depending on the combination, a hook can run the handlers either in parallel, or in order until one fails, or even compose them (pass the result of one as the input of the next). The handler types specify which input and output values are expected.

Many hooks are executed at different points in Nyxt, among others:

For instance, if you want to force '' over '', you can set a hook like the following in your configuration file:

(defun old-reddit-handler (request-data)
  (let ((url (url request-data)))
    (setf (url request-data)
          (if (search "" (quri:uri-host url))
                (setf (quri:uri-host url) "")
                (log:info "Switching to old Reddit: ~s" (render-url url))

(define-configuration web-buffer
    (hooks:add-hook %slot-default% (make-handler-resource #'old-reddit-handler)))))

(See url-dispatching-handler for a simpler way to achieve the same result.)

Or, if you want to set multiple handlers at once,

(define-configuration web-buffer
    (reduce #'hooks:add-hook
            (mapcar #'make-handler-resource (list #'old-reddit-handler
            :initial-value %slot-default%))))

Some hooks like the above example expect a return value, so it's important to make sure we return request-data here. See the documentation of the respective hooks for more details.

Data paths and data profiles

Nyxt provides a uniform configuration interface for all data files persisted to disk (bookmarks, cookies, etc.). To each file corresponds a data-path object. A data-profile is a unique but customizable object that helps define general rules for data storage. Both data-paths and data-profiles compose, so it's possible to define general rules for all data-paths (even for those not known in advance) while it's also possible to specialize some data-paths given a data-profile.

The data-profile can be set from command line and from the configuration file. You can list all known data profiles (including the user-defined profiles) with the --list-data-profiles command-line option.

The data-paths can be passed a hint from the --with-path command line option, but each data-path and data-profile rules are free to ignore it. The expand-default-path helper function uses the --with-path value first, then fallback to a default. See its documentation for more details.

When the data path ends with the .gpg extension, your GnuPG key is used to decrypt and encrypt the file transparently. Refer to the GnuPG documentation for how to set it up.

Note that the socket and the initialization data-paths cannot be set in your configuration (the socket is used before the initialization file is loaded). Instead you can specify these paths from their respective command-line option. You can instantiate a unique, separate Nyxt instance when you provide a new socket path. This is particularly useful in combination with data profiles, e.g. to develop Nyxt or extensions.

Example to create a development data-profile that stores all data in /tmp/nyxt and stores bookmark in an encrypted file:

(define-class dev-data-profile (data-profile)
   ((name :initform "dev"))
   (:documentation "Development profile."))

(defmethod nyxt:expand-data-path ((profile dev-data-profile) (path data-path))
  "Persist data to /tmp/nyxt/."
  (expand-default-path (make-instance (class-name (class-of path))
                                      :basename (basename path)
                                      :dirname "/tmp/nyxt/")))

(defmethod nyxt:expand-data-path ((profile dev-data-profile) (path history-data-path))
  "Persist history to default location."
  (expand-data-path *global-data-profile* path))

;; Make new profile the default:
(define-configuration buffer
  ((data-profile (make-instance (or (find-data-profile (getf *options* :data-profile))
   (bookmarks-path (make-instance 'bookmarks-data-path
                                  :basename "~/personal/bookmarks/bookmarks.lisp.gpg"))))

Then you can start a separate instance of Nyxt using this profile with nyxt --data-profile dev --socket /tmp/nyxt.socket .

Password management

Nyxt provides a uniform interface to some password managers including KeepassXC and Password Store . The supported installed password manager is automatically detected. See the password-interface buffer slot for customization.

You may use the define-configuration macro with any of the password interfaces to configure them. Please make sure to use the package prefixed class name/slot designators within the define-configuration macro.


Much of the visual style can be configured by the user. Search the class slots for 'style'. To customize the status area, see the status-formatter window slot.


You can evaluate code from the command line with --eval and --load . From a shell:

$ nyxt --no-init --eval '+version+' 
  --load my-lib.lisp --eval '(format t "Hello ~a!~&" (my-lib:my-world))'

You can evaluate multiple --eval and --load in a row, they are executed in the order they appear.

You can also evaluate a Lisp file from the Nyxt interface with the load-file command. For convenience, load-init-file (re)loads your initialization file.

You can even make scripts. Here is an example foo.lisp:

#!nyxt --script
(format t "~a~&" +version+)

--eval and --load can be commanded to operate over an existing instance instead of a separate instance that exits immediately.

The `remote-execution-p' slot of the `browser' class of the remote instance must be non-nil.

To let know a private instance of Nyxt to load a foo.lisp script and run its `foo' function:

nyxt --data-profile nosave --remote --load foo.lisp --eval '(foo)'


To install an extension, copy inside the *extensions-path* (default to ~/.local/share/nyxt/extensions ).

Extensions are regular Common Lisp systems.

A catalogue of extensions is available in the document/ file in the source repository.


Playing videos

Nyxt delegates video support to third-party plugins.

When using the WebKitGTK backends, GStreamer and its plugins are leveraged. Depending on the video, you will need to install some of the following packages:

On Debian-based systems, you might be looking for (adapt the version numbers):

For systems from the Fedora family:

After the desired plugins have been installed, clear the GStreamer cache at ~/.cache/gstreamer-1.0 and restart Nyxt.

Website crashes

If some websites systematically crash, try to install all the required Gstreamer plugins as mentioned in the 'Playing videos' section.

Input method support (CJK, etc.)

Depending on your setup, you might have to set some environment variables or run some commands before starting Nyxt, for instance

ibus --daemonize --replace --xim

You can persist this change by saving the commands in your .xprofile or similar.

Font size on HiDPI displays

On HiDPI displays, the font size used for displaying web and Nyxt's prompt-buffer content might be too tiny.

To fix this issue when using the WebKitGTK render, export the following environment variable before starting Nyxt:

export GDK_SCALE=2
export GDK_DPI_SCALE=0.5

StumpWM mouse scroll

If the mouse scroll does not work for you, see the StumpWM FAQ for a fix.

Blank WebKit web-views

If you are experiencing problems with blank web-views on some sites you can try to disable compositing. To disable compositing from your initialization file, you can do the following: (setf (uiop:getenv "WEBKIT_DISABLE_COMPOSITING_MODE") "1")