#+title: Hyperdrive.el User Manual
#+subtitle: Release {{{version}}}
#+author: Joseph Turner and Adam Porter
#+language: en
#+setupfile: doc-setup.org

#+texinfo_dir_category: Emacs
#+texinfo_dir_title: Hyperdrive: (hyperdrive)
#+texinfo_dir_desc: P2P filesystem in Emacs

[[https://docs.holepunch.to/building-blocks/hyperdrive][Hyperdrive]] is a P2P, real-time, local-first, versioned filesystem
designed for easy peer-to-peer file sharing.  ~hyperdrive.el~ is an
independent project built by [[https://ushin.org][USHIN]] which provides an Emacs interface
for managing hyperdrives.

~hyperdrive.el~ is in early development. If something breaks, please see
[[*Troubleshooting]].

- Homepage: https://ushin.org/hyperdrive/hyperdrive-manual.html
- Repository: https://git.sr.ht/~ushin/hyperdrive.el

This manual is for ~hyperdrive.el~ version {{{version}}}.

* Freedom to copy

Copyright \copy 2023, 2024, 2025 USHIN, Inc.

#+begin_quote
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with the Front-Cover Texts being "A GNU Manual,"
and with the Back-Cover Texts as in (a) below.  A copy of the license
is included in the section entitled "GNU Free Documentation License."

(a) The FSF's Back-Cover Text is: "You have the freedom to copy and
modify this GNU manual."
#+end_quote

* Installation

** Install Emacs

~hyperdrive.el~ requires [[https://www.gnu.org/software/emacs/][GNU Emacs]] version 28.1 or later.

** Install curl

~hyperdrive.el~ requires a reasonably up-to-date version of [[https://curl.se/download.html][curl]].

Feel free to skip this step.  ~curl~ may already installed on your
machine, and ~hyperdrive.el~ will warn you otherwise.

** Install hyperdrive.el

~hyperdrive.el~ can be installed from [[https://elpa.nongnu.org/nongnu/hyperdrive.html][NonGNU ELPA]] with ~M-x
package-refresh-contents~ then ~M-x package-install RET hyperdrive~.

After installing with NonGNU ELPA, you can later upgrade to a newer
version of ~hyperdrive.el~ by running ~M-x package-refresh-contents~ then
~M-x package-upgrade RET hyperdrive~.  On Emacs 28, If ~package-upgrade~
is not available as a command, display the list of packages with ~M-x
list-packages~, select ~hyperdrive~, and click the ~Install~ button.

** Install hyper-gateway-ushin

~hyperdrive.el~ relies on [[https://git.sr.ht/~ushin/hyper-gateway-ushin/][hyper-gateway-ushin]] for talking to the
hypercore network.

After installing ~hyperdrive.el~ (see [[*Install hyperdrive.el][Install hyperdrive.el]]), run ~M-x
hyperdrive-install~ to download and install the gateway.

Alternatively, follow the [[https://git.sr.ht/~ushin/hyper-gateway-ushin#installation][manual installation instructions]].

* Example configuration

After following the [[*Installation][installation instructions]], you can add this
snippet to your ~~/.emacs.d/init.el~ file.  This code will make the
keyboard shortcut ~C-c h~ (hold the ~Control~ key and tap ~c~, then release
both and tap ~h~) open [[*Hyperdrive menu command][the hyperdrive menu command]].  It will also enable
the [[*Menu bar support]["Hyperdrive" menu bar]]:

#+begin_src emacs-lisp
  (when (package-installed-p 'hyperdrive)
    (global-set-key (kbd "C-c h") #'hyperdrive-menu)
    (menu-bar-mode +1)
    (hyperdrive-menu-bar-mode +1)
    (with-eval-after-load 'hyperdrive
      (context-menu-mode +1)
      (hyperdrive-context-menu-mode +1)))
#+end_src

With [[info:use-package][use-package]]:

#+begin_src emacs-lisp
  (use-package hyperdrive
    :bind ("C-c h" . hyperdrive-menu)
    :init
    (menu-bar-mode +1)
    (hyperdrive-menu-bar-mode +1)
    :config
    (context-menu-mode +1)
    (hyperdrive-context-menu-mode +1))
#+end_src

* Usage

#+begin_verse
Be careful about what you share!
When you upload a file, beware:
  You may delete your own copy,
  But gone it may not be.
On the network it still may be there.
#+end_verse

** Install the gateway

Run ~M-x hyperdrive-install~ to download and install the gateway program
(see [[*hyper-gateway-ushin]]):

- Command: hyperdrive-install ::

  Download and install the gateway.  Prompts for confirmation before
  downloading.

- Command: hyperdrive-cancel-install ::

  Cancel installation in progress.

** Menu bar support
#+findex: menu-bar-mode

If you enable ~hyperdrive-menu-bar-mode~, either in your configuration
(see [[*Example configuration]]) or with ~M-x hyperdrive-menu-bar-mode~,
the "Hyperdrive" menu should appear after the "Tools" menu at the top
of the screen.  If you don't see the menu bar, please double check
that ~menu-bar-mode~ is enabled (it is enabled by default).

- Command: hyperdrive-menu-bar-mode ::

  Enable the "Hyperdrive" menu bar.

If you have disabled ~menu-bar-mode~, you can still use the hyperdrive
menu bar by pressing ~C-mouse-3~ in a hyperdrive file or directory.

** Context menu support
#+findex: context-menu-mode

If you enable ~hyperdrive-context-menu-mode~, either in your
configuration (see [[*Example configuration]]) or with ~M-x
hyperdrive-context-menu-mode~, "Hyperdrive"-related menu items should
appear when you right-click on hyperdrive names, like ~petname:foo~.
If you don't see hyperdrive context menu items when you right-click on
hyperdrive names, please check that ~context-menu-mode~ is enabled (it
is enabled automatically by ~hyperdrive-context-menu-mode~).

- Command: hyperdrive-context-menu-mode ::

  Enable the "Hyperdrive" right-click context menu.

If you have disabled ~context-menu-mode~, you can still use the
context menu bar by putting point on a hyperdrive name and pressing
~S-<f10>~.

** Hyperdrive menu command

~M-x hyperdrive-menu~ is a keyboard-driven interface to many
~hyperdrive.el~ commands.  With the menu open, press one of highlit keys
or key combinations to invoke the command displayed next to it.
Different commands are available in ~hyperdrive-menu~ when you're inside
a hyperdrive file, directory, or neither.

While inside the ~hyperdrive-menu~, press ~?~ twice to open this
~hyperdrive.el~ info manual.  You can also press ~?~ followed by a
command's key sequence to get help for that command. ([[*Quick documentation access][more tips on
getting help]])

If you press ~C-u~ (universal prefix argument) before a key sequence,
the command may behave differently, e.g., by prompting for more
information.  You can jump between ~hyperdrive-menu~ commands with the
~up~ and ~down~ arrow keys.  Press ~C-g~ to close the menu.

- Command: hyperdrive-menu ::

  Show the hyperdrive menu interface.

For more on this type of user interface, please refer to the [[info:transient#Introduction][Transient
documentation]].  To learn about the commands available in
~hyperdrive-menu~, read on!

** Start/stop the gateway

To connect with peers, you'll need to start the gateway (see
[[*hyper-gateway-ushin]]).  The current running status of the gateway
can be seen in ~hyperdrive-menu~ (see [[*Hyperdrive menu command]])
and in the "Hyperdrive" menu bar (see [[*Menu bar support]]).

- Command: hyperdrive-start ::

  Start the gateway.

- User Option: hyperdrive-gateway-ready-hook ::

  Hook run when the gateway becomes responsive after ~hyperdrive-start~.
  One of the default hooks, ~hyperdrive-check-gateway-version~, will
  warn you if you're running an outdated version of the gateway.

- Command: hyperdrive-stop ::

  Stop the gateway.

- User Option: hyperdrive-gateway-dead-hook ::

  Hook run when the gateway is no longer live after ~hyperdrive-stop~.

- Command: hyperdrive-restart ::

  Restart the gateway.

- Command: hyperdrive-gateway-version ::

  Say the version of the gateway which is running.

*** Advanced gateway customization

- User Option: hyperdrive-gateway-start-function ::

  Function run to start the gateway.  By default, ~hyperdrive.el~ will
  start the gateway as an Emacs subprocess.

- User Option: hyperdrive-gateway-stop-function ::

  Function run to stop the gateway.

- User Option: hyperdrive-gateway-live-predicate ::

  Function run to check that the gateway process is live.

** Open a hyperdrive

You can open a hyperdrive folder or file by pasting in a ~hyper://~ URL
after ~M-x hyperdrive-open-url~.  Try loading USHIN's hyperdrive:

#+begin_example
hyper://aaj45d88g4eenu76rpmwzjiabsof1w8u6fufq6oogyhjk1ubygxy/
#+end_example

- Command: hyperdrive-open-url ::

  Open a hyperdrive file or directory by its ~hyper://~ URL.

The following commands let you select and visit one of the
hyperdrives you've already created or visited:

- Command: hyperdrive-find-file ::

  Open a hyperdrive file or directory by choosing one of your known
  hyperdrives and a path inside it.  Like ~find-file~, this command can
  be used to create a new file inside your own hyperdrives.

- Command: hyperdrive-view-file ::

  Like ~hyperdrive-find-file~, but open the file in [[info:emacs#View Mode][view-mode]].

*** Directory view

~hyperdrive.el~ offers a Dired-like (see [[info:emacs#Dired]]) interface
for exploring hyperdrive directories.  In the directory view, the file
size color indicates how much of a file you have already downloaded:

- green :: fully downloaded (~hyperdrive-size-fully-downloaded~)
- yellow :: partially downloaded (~hyperdrive-size-partially-downloaded~)
- red :: not downloaded (~hyperdrive-size-not-downloaded~)

Mouse over the file size to see exactly how many blocks make up the
file and how many of them you have downloaded.

The following bindings are available in the directory view by default:

#+attr_texinfo: :compact t
- Key: n (hyperdrive-ewoc-next) ::
- Key: p (hyperdrive-ewoc-previous) ::

  Move between entries.

- Key: RET (hyperdrive-dir-find-file) ::

  Open the file or directory at point.

- Key: o (hyperdrive-dir-find-file-other-window) ::
- Key: <mouse-1> ::
- Key: <mouse-2> ::

  Open the file or directory at point in a new window.

- Key: v (hyperdrive-dir-view-file) ::

  Open the file or directory at point in [[info:emacs#View Mode][view-mode]].

- Key: ^ (hyperdrive-up) ::

  Go up to the parent directory.

- Key: g (revert-buffer) ::

  Refresh the directory to display potential updates.

- Key: s (hyperdrive-dir-sort) ::

  Sort directory contents by the current column.  To sort by a
  different column, click on the column header or use the universal
  prefix argument (~C-u s~).

- Key: d (hyperdrive-dir-download-file) ::

  Download the file at point to disk.

- Key: D (hyperdrive-delete) ::

  Delete the file or directory (recursively) at point.

- Key: F (hyperdrive-forget-file) ::

  Delete your local copy of the file at point.

- Key: H (hyperdrive-dir-history) ::

  Open the version history (see [[*View the hyperdrive version history]])
  of file at point.

- Key: w (hyperdrive-dir-copy-url) ::

  Copy the URL of the file or directory at point.

- Key: j (imenu) ::

  Open ~imenu~ to quickly jump to a file in the current directory.

- Key: ? (hyperdrive-menu) ::

  Open ~hyperdrive-menu~ (see [[*Hyperdrive menu command][Hyperdrive menu command]]).

- Key: + (hyperdrive-create-directory-no-op) ::

  This command signals an error, because you cannot create empty
  directories (see [[*No empty directories]]).

You can customize the directory view with the following options:

- User Option: hyperdrive-directory-display-buffer-action ::

  Display buffer action for hyperdrive directories.  Passed to
  ~display-buffer~, which see.

- User Option: hyperdrive-directory-sort ::

  Column by which directory entries are sorted by default.
  Internally, a cons cell of (COLUMN .  DIRECTION), the COLUMN being
  one of the directory listing columns (~name~, ~size~, or ~mtime~) and
  DIRECTION being one of ~:ascending~ or ~:descending~.

*** File view
#+findex: dired-jump

The following keybindings are available inside the file view by
default:

- Key: C-x x g (hyperdrive-revert-buffer-quick) ::

  Refresh the file to display potential updates.  This command remaps
  the global ~revert-buffer-quick~ keybinding.

- Key: C-x C-j (hyperdrive-up) ::

  Jump to the parent hyperdrive directory from a hyperdrive file or
  directory buffer.  This command remaps the global ~dired-jump~ keybinding.

For security reasons, ~hyperdrive.el~ does not enable major modes based
on file extension unless the hyperdrive has been marked as "safe" with
~M-x hyperdrive-mark-as-safe~ (see [[*Mark a hyperdrive as safe]]).

The following customization options affect how files are displayed:

- User Option: hyperdrive-render-html ::

  Control how HTML hyperdrive files are displayed.  By default, HTML
  pages are rendered in Emacs with [[info:eww#Top][EWW]].  If ~nil~, raw HTML will be
  displayed.

*** Unknown paths

When you attempt to load a file or folder that doesn't appear to
exist, ~hyperdrive.el~ will prompt you to take action:

- ~h~ (history) to open the [[*View the hyperdrive version history][version history]] for that file.
- ~u~ (up) to open the parent directory containing that file or folder
- ~r~ (recurse) to go up the directory tree until a directory is found
  or until you get to the root directory.
- ~e~ (explain) to open this section of the hyperdrive Info manual.
- ~q~ (exit) to exit,
- ~?~ (help) to show a help message.

If you attempt to load the root directory (~hyper://PUBLIC-KEY/~) of a
hyperdrive with a valid-looking public key which you've never loaded
before and for which no peers are currently found, ~hyperdrive.el~
should warn you that no peers were found for that drive.  This might
mean that the drive doesn't exist or just that you're not connected to
anyone who knows about it.

If you attempt to load a file or directory for a hyperdrive with a
malformed public key, ~hyperdrive.el~ should ask you to double-check the
URL.

** Create a hyperdrive

You can have multiple hyperdrives, each one containing its own set of
files. Run ~M-x hyperdrive-new~ then type in a ~seed~ (see [[*Seeds]]) to
create a new hyperdrive. That seed will be combined with your secret
master key (see [[*Master key]]) to produce a public key (see [[*Public
keys]]) that uniquely identifies that hyperdrive.

- Command: hyperdrive-new ::

  Create a new hyperdrive from a seed string.

When you create a new drive, your chosen seed is used as its petname
(see [[*Petnames]]) by default.

** Write to a hyperdrive
#+vindex: save-some-buffers-default-predicate

After modifying a file in one of your hyperdrives, ~save-buffer~ will
silently update the current hyperdrive file with the new content.

- Key: C-x C-s (save-buffer) ::

  Save the current hyperdrive file buffer to its location.

- Key: C-x s (save-some-buffers) ::

  Save all modified hyperdrive file buffers to their locations.  This
  command's primary purpose is to save normal file buffers, and
  ~hyperdrive.el~ has integrated with it.

  ~hyperdrive.el~ will prompt to save modified hyperdrive files before
  exiting Emacs.  If you want the command ~save-some-buffers~ to always
  prompt to save hyperdrive files in addition to regular files, set
  ~save-some-buffers-default-predicate~ to ~t~.

- Command: hyperdrive-write-buffer ::

  Write the current buffer to a hyperdrive by choosing one of
  hyperdrives you have created as well as the path in that hyperdrive
  where you want to store the file.

** Link to a hyperdrive

You can share a hyperdrive file with someone by copying and sending
its link.  Anyone who has the link to a hyperdrive file or directory
can load it and view its contents.

- Command: hyperdrive-copy-url ::

  Copy the URL of the current hyperdrive file or directory.

In the directory view, you can copy the URL of the file or directory
at point by pressing ~w~ (see [[*Directory view]]).

*** Org mode links
#+findex: org-store-link
#+findex: org-insert-link
#+vindex: org-link-file-path-type

If the current file is an org-mode file, ~org-store-link~ will store a
link to the hyperdrive file.  If point is inside a heading, a
URL-encoded search option containing its ~CUSTOM_ID~, ~ID~, or heading
text will be appended as the stored URL's link fragment.

Linking by path alone to other files within the same hyperdrive is
supported; within ~hyper://PUBLIC-KEY/foo.org~, links to ~bar.org~,
~./bar.org~, and ~/bar.org~ will all point to ~hyper://PUBLIC-KEY/bar.org~.
Links within a hyperdrive may also begin with the explicit ~file:~
prefix.  A version number can also be specified; ~/$/version/42/bar.org~
will point to ~hyper://PUBLIC-KEY/$/version/42/bar.org~.

Org-mode hyperdrive link completion allows you to interactively link
to a hyperdrive file/folder by running ~M-x org-insert-link~ (or ~C-c C-l~
in org-mode), then typing ~hyper:~ and ~RET~.  To change how
~org-insert-link~ inserts links to files within the same hyperdrive,
adjust ~hyperdrive-org-link-full-url~ and ~org-link-file-path-type~.

- User Option: hyperdrive-org-link-full-url ::

  This option controls whether relative links to hyperdrives are ever
  inserted with ~org-insert-link~.  Set it to ~t~ if you always want to
  insert full ~hyper://~ links.

*** Markdown links

Relative links are supported; within ~hyper://PUBLIC-KEY/foo.md~, the
links ~[bar](<bar.md>)~, ~[bar](<./bar.md>)~, and ~[bar](</bar.md>)~ all
point to ~hyper://PUBLIC-KEY/bar.md~.

** Delete a hyperdrive file

*Please note that deleted files can be accessed by loading a prior
version of the hyperdrive (see [[*View the hyperdrive version history]]).*

- Command: hyperdrive-delete ::

  Delete the hyperdrive file in the current buffer.

This command also has a keybinding in the directory view (see
[[*Directory view]]).

** Forget a hyperdrive file

*Please note that forgetting a file may result in data loss if it
cannot be loaded from another peer on the network.*

It is possible to "forget" your local copy of a hyperdrive file in
order to save disk space.  "Forgetting" a file does not delete the
file from the hyperdrive and does not increment the hyperdrive's
version number.

- Command: hyperdrive-forget-file ::

  Delete your local copy of the file for the current buffer.

This command also has a keybinding in the directory view (see
[[*Directory view]]).  When you forget a file, the file size of its
directory listing will turn red, indicating that you no longer have a
copy of the file.

** View the hyperdrive version history

Hyperdrives are versioned, meaning that you can explore the history of
changes made to hyperdrive files (see [[*Versioning]]).

- Command: hyperdrive-open-previous-version ::

  Open the previous version of the current hyperdrive file or directory.

- Command: hyperdrive-open-previous-version ::

  Open the next version of the current hyperdrive file or directory.

- Command: hyperdrive-open-at-version ::

  Open the current hyperdrive file or directory at a specific version
  number.  To open the file or directory at its hyperdrive's latest
  version, leave the version blank.

The following keybindings are available when visiting an old version
of a hyperdrive file (~hyperdrive-blob-mode~):

#+attr_texinfo: :compact t
- Key: n (hyperdrive-open-next-version) ::
- Key: p (hyperdrive-open-previous-version) ::

  Traverse version history for the current file.

- Key: q (kill-current-buffer) ::

*** History buffer

The history buffer displays the entire known history of a hyperdrive
file.  For an explanation of how it works, see [[*Partial version data]].

Like in the [[*Directory view][directory view]], the file size color in the history view
indicates how much of a file you have already downloaded.

- Command: hyperdrive-history ::

  Open the history buffer for the current hyperdrive file.  To open
  the history for a different file, use the universal prefix argument
  like this: ~C-u M-x hyperdrive-history~.

The following keybindings are available inside the history view by
default:

#+attr_texinfo: :compact t
- Key: n (hyperdrive-ewoc-next) ::
- Key: p (hyperdrive-ewoc-previous) ::

  Move between entries.

- Key: + (hyperdrive-history-load) ::

  Load all drive metadata, including version metadata, then reload the
  history buffer.

- Key: RET (hyperdrive-history-find-file) ::

  Open the file at the start of the version range at point.  When the
  version range at point is ~unknown~, run ~hyperdrive-history-load~.

- Key: o (hyperdrive-history-find-file-other-window) ::
- Key: <mouse-1> ::
- Key: <mouse-2> ::

  Open the file at the start of the version range at point in a new
  window.

- Key: v (hyperdrive-history-view-file) ::

  Open the file at the start of the version range at point in [[info:emacs#View
   Mode][view-mode]].  When the version range at point is ~unknown~, run
  ~hyperdrive-history-load~.

- Key: w (hyperdrive-history-copy-url) ::

  Copy the URL of the file at the start of the version range at point.

- Key: d (hyperdrive-history-download-file) ::

  Download the file at the start of the version range at point.

- Key: = (hyperdrive-history-diff) ::

  Display the differences between the version at point and the prior
  version.

- Key: F (hyperdrive-history-forget-file) ::

  Delete your local copy of the file for the version range at point.

To act on the latest known version of the file, use these keybindings
on the header line displaying the file description.

You can customize the history view:

- User Option: hyperdrive-history-display-buffer-action ::

  Display buffer action for hyperdrive history buffers.  Passed to
  ~display-buffer~, which see.

** Describe a hyperdrive

To see information about a hyperdrive, such as its public key, seed,
petname, nickname, domains, writability, local disk usage, or other
metadata, run ~hyperdrive-describe-hyperdrive~.  For more on what this
information means, see [[*Naming]].

- Command: hyperdrive-describe-hyperdrive ::

  Display the description of the hyperdrive containing the current
  file or directory.  To describe a different hyperdrive, use the
  universal prefix argument: ~C-u M-x hyperdrive-describe-hyperdrive~.

** Name a hyperdrive

~hyperdrive.el~ supports different ways to identify hyperdrives (see
[[*Naming]]).  The following commands can be used to name hyperdrives:

- Command: hyperdrive-set-petname ::

  Set the petname (see [[*Petnames]]) of the hyperdrive for the current
  hyperdrive file or directory.  You can't use the same petname for
  multiple hyperdrives.  To set the petname of a different hyperdrive,
  use the universal prefix argument: ~C-u M-x hyperdrive-set-petname~.

- Command: hyperdrive-set-nickname ::

  Set the nickname (see [[*Nicknames]]) of the hyperdrive for the current
  hyperdrive file or directory.  You can only set the nickname for a
  hyperdrive which you previously created.  To set the nickname of a
  different hyperdrive, use the universal prefix argument like this:
  ~C-u M-x hyperdrive-set-nickname~.

** Explore the peer graph

~hyperdrive.el~ includes a tool for building and exploring a network
of sources of information.  This peer graph feature is based on three
ways relating to other peers:

- Sources :: Sources are peers whose content you want to see.  Sources
  are also used to discover other sources.

- Blockers :: Blockers are peers whose blocked peers will be hidden
  from your view.  Blockers are also used to discover other blockers.

- Blocked :: Blocked are peers whose content you do not want to see.

For a video demonstration and explanation of the peer graph, see
[[https://ushin.org/presentations.html#emacsconf2024][EmacsConf 2024: New in hyperdrive.el: quick install, peer graph, transclusion!]]

*** Customization

- User Option: hyperdrive-peer-graph-sources-max-hops-default ::

  Default maximum number of hops to go out when gathering source.
  Defaults to ~3~.

- User Option: hyperdrive-peer-graph-blockers-max-hops-default ::

  Default maximum number of hops to go out when gathering blockers.
  Defaults to ~3~.

- User Option: hyperdrive-peer-graph-show-sources-p-default ::

  Whether to show sources in peer graph and list views by default.
  Defaults to ~t~.

- User Option: hyperdrive-peer-graph-show-blockers-p-default ::

  Whether to show blockers in peer graph and list views by default.
  Defaults to ~t~.

- User Option: hyperdrive-peer-graph-show-blocked-p-default ::

  Whether to show blocked in peer graph and list views by default:

  + ~all~ :: Show blocked sources and non-sources.
  + ~sources~ :: Show only blocked sources. (default)
  + ~non-sources~ :: Show only blocked non-sources.
  + ~nil~ :: Hide blocked peers.

- User Option: hyperdrive-peer-graph-shortest-paths-p-default ::

  Whether to show only the shortest paths between peers by default.
  Defaults to ~t~.

- User Option: hyperdrive-peer-graph-buffer-name ::

  Buffer name to use for peer graph buffers.  Defaults to
  ~"*hyperdrive-peer-graph*"~.

- User Option: hyperdrive-peer-graph-list-buffer-name ::

  Buffer name to use for peer list buffers.  Defaults to
  ~"*hyperdrive-peer-graph-list*"~.

- User Option: hyperdrive-peer-graph-list-apply-filters ::

  Whether the filters applied to the peer graph should affect the peer
  list as well. Defaults to ~t~.

  For example, if non-nil and ~hyperdrive-peer-graph-show-sources-p~
  is ~nil~, then sources will not appear in the peer list.  Regardless
  of this options value, you can fold the sections of the peer list
  with ~magit-section-toggle~, bound to ~TAB~.

- User Option: hyperdrive-peer-graph-display-buffer-action ::

  Display buffer action for peer graph buffers.  Passed to
  ~display-buffer~, which see.

- User Option: hyperdrive-peer-graph-list-display-buffer-action ::

  Display buffer action for peer list buffers.  Passed to
  ~display-buffer~, which see.

- User Option: hyperdrive-peer-graph-auto-resize-on-window-resize ::

  Whether to redraw the graph when the window displaying its buffer
  resizes.  Value has the same meaning as
  ~image-auto-resize-on-window-resize~, defined in ~image-mode.el~.

- User Option: hyperdrive-peer-graph-menu-display-action ::

  Display buffer action for transient peer graph menu.  See
  [[info:transient][transient.el info manual]] for more information.

- User Option: hyperdrive-sbb-view-layout ::

  Name of the Graphviz layout engine to use.  See [[https://graphviz.org/docs/attrs/layout/][Graphviz
  documentation on layout]] for more information.  Defaults to ~"dot"~.

- User Option: hyperdrive-sbb-view-overlap ::

  How to handle overlapping nodes.  See [[https://graphviz.org/docs/attrs/overlap/][GraphViz documentation on
  overlap]] for more information. Defaults to ~"voronoi"~.

  Only affects ~fdp~, ~neato~, ~sfdp~, ~circo~, ~twopi~ layouts.

- User Option: hyperdrive-sbb-view-sources-color ::

  Color used for sources in peer graph.  Defaults to foreground of
  ~hyperdrive-sbb-source~ face.

- User Option: hyperdrive-sbb-view-blockers-color ::

  Color used for blockers in peer graph.  Defaults to foreground of
  ~hyperdrive-sbb-blocker~ face.

- User Option: hyperdrive-sbb-view-blocked-color ::

  Color used for blocked in peer graph.  Defaults to foreground of
  ~hyperdrive-sbb-blocked~ face.

** Bookmark a hyperdrive
#+findex: bookmark-set
#+findex: bookmark-jump
#+findex: bookmark-list

You can use the built-in ~bookmark-set~, ~bookmark-jump~, and
~bookmark-list~ functions to store and jump to a hyperdrive file or
directory.

- Command: hyperdrive-bookmark-jump ::

  Select a hyperdrive bookmark and jump to it.

- Command: hyperdrive-bookmark-list ::

  View a list of hyperdrive bookmarks.

** Stream audio and video

When you use ~hyperdrive-find-file~ or some other command to open a
streamable audio/video file, Emacs will use an external program to
stream that video from the network.  After the stream finishes, the
audio/video file is stored locally.

- User Option: hyperdrive-stream-player-command ::

  Command used to play streamable URLs externally.  Default uses
  [[https://mpv.io/][mpv]].  There also exists a preconfigured option for [[https://www.videolan.org/vlc/][VLC media player]].

** Download hyperdrive files

You can "download" a hyperdrive file to your local filesystem, meaning
that ~hyperdrive.el~ will (1) download the file from the network if it
hasn't done so already and then (2) copy the file contents to a
file-path on your machine of your choosing.  The following commands
may be run while offline.

- Command: hyperdrive-download ::

  Download a hyperdrive file by selecting a hyperdrive and a path.

- Command: hyperdrive-download-url ::

  Download a hyperdrive file by pasting in a ~hyper://~ URL.

- User Option: hyperdrive-download-directory ::

  Location where ~hyperdrive-download-url~ will download files.  Defaults
  to ~eww-download-directory~ or, if not bound, the home directory.

** Upload files from your filesystem
#+findex: yank-media

If you already have a file on your local filesystem that you'd like to
put on a hyperdrive, you can "upload" it.  Note that the following
commands add files to a hyperdrive, but those files are not
automatically "uploaded" to anyone else's machine in the traditional
sense.  Files are only shared on the network when other peers request
them from your node.  The following commands may be run while offline.

- Command: hyperdrive-upload-file ::

  Upload a single file from your filesystem.  By default, the selected
  file will be placed in your hyperdrive's root directory, but you can
  edit the filepath before uploading.

- Command: hyperdrive-upload-files ::

  Upload multiple files from your filesystem.  The selected files will
  be uploaded into the same target directory in your hyperdrive.

On Emacs 29+, you can upload an image which you previously copied to
your clipboard from an external program with ~M-x yank-media~.

*** Mirror a whole directory

For uploading more than a few files, you can use ~hyperdrive-mirror~.

- Command: hyperdrive-mirror ::

  Upload a directory, mirroring its subdirectory structure in your
  hyperdrive.  This command prompts for a source directory on your
  local filesystem from which to upload files as well as a hyperdrive
  and target directory inside of it where the files will end up.

  The source and target directories will be compared, and only the
  files which are "new locally" (they don't already exist on the
  drive) or "newer locally" (they have been locally modified since a
  previous upload) will be uploaded.  Files which are the "same" (they
  have the same timestamp as in the drive) or are "older locally"
  (they have been modified on the drive more recently than on the
  filesystem) will not be uploaded.

  With a universal prefix argument (~C-u M-x hyperdrive-mirror~), it
  additionally prompts for a filter argument to programmatically
  determine which files will be considered for upload.  With two
  universal prefix arguments (~C-u C-u M-x hyperdrive-mirror~), matching
  files will be uploaded without the confirmation step.

As a confirmation step, ~hyperdrive-mirror~ displays each file to be
uploaded alongside the URL in the hyperdrive where it will end up.
The following keybindings are available in ~hyperdrive-mirror-mode~:

- Key: C-c C-c (hyperdrive-mirror-do-upload) ::

  Upload all of the files in the "To Upload" section.

- Key: TAB (magit-section-toggle) ::

  Fold or unfold the section at point.

** Mark a hyperdrive as safe

For security reasons, ~hyperdrive.el~ does not enable major modes
based on file extension unless the hyperdrive has been marked as
"safe."  When opening a file in a hyperdrive marked as "unknown" (the
default), ~hyperdrive.el~ will prompt you to mark the drive as "safe",
"unsafe", or "unknown".  Files in hyperdrives which are marked as
"safe" are always opened in the appropriate major mode with
~set-auto-mode~.  Files in hyperdrives which are marked as "unsafe"
are opened in ~fundamental-mode~ (no major mode).

- Command: hyperdrive-mark-as-safe ::

  Mark a hyperdrive as "safe", "unsafe", or "unknown".  This command
  can also be invoked from ~hyperdrive-menu-hyperdrive~ and the menu bar.

** Purge a hyperdrive

*Data which has been purged from your local machine may still be
available on the network.*

*Data which has been purged from your local machine may not be
recoverable.*

- Command: hyperdrive-purge ::

  Remove all data related to a hyperdrive.  This command will prompt
  for confirmation before deleting anything.  In addition to the
  hyperdrive's file content and metadata, ~hyperdrive-purge~ also
  deletes relevant metadata persisted in the ~hyperdrive-hyperdrives~
  variable.

** Non-interactive use

In writing your own functions to extend ~hyperdrive.el~, you can use
~hyperdrive-by-slot~ to access a hyperdrive by its metadata:

- Function: hyperdrive-by-slot ::

  This function accepts a hyperdrive seed, petname, or public key, and
  returns the hyperdrive ~struct~.

*** Non-interactive use example: ~hyperdrive-mirror~

You can use the following snippet to recursively upload all of the
files from your local filesystem's ~~/blog/~ directory into the ~/blog/~
directory of a hyperdrive you previously created with petname ~"foo"~:

#+begin_src emacs-lisp
  (hyperdrive-mirror
   "~/blog/"
   (hyperdrive-by-slot 'petname "foo")
   "/blog/")
#+end_src

To upload the same files without confirmation, add ~:no-confirm t~.

Now let's say that you want to upload only those files tagged as
"public" using Protesilaos Stavrou's [[https://protesilaos.com/emacs/denote][Denote]] file-naming scheme.  The
following snippet includes a ~FILTER~ key whose value is a regular
expression against which every expanded filename will be tested.

#+begin_src emacs-lisp
  (hyperdrive-mirror
   "~/blog/"
   (hyperdrive-by-slot 'petname "foo")
   "/blog/"
   :filter "_public")
#+end_src

Alternatively, you could select files by tag with Karl Voit's
[[https://github.com/novoid/filetags/][filetags]]. Either way allows for a "non-splitting" approach where
public and private files exist in the same directory.

~FILTER~ may also be a function, which receives the expanded filename
as its only argument. For example, the following snippet will mirror
only those files in ~~/blog/~ which are smaller than 5MB:

#+begin_src emacs-lisp
  (hyperdrive-mirror
   "~/blog/"
   (hyperdrive-by-slot 'petname "foo")
   "/blog/"
   :filter (lambda (file) (> (* 5 1024 1024)
                        (file-attribute-size
                         (file-attributes file)))))
#+end_src

** Org-transclusion integration

The [[https://git.sr.ht/~ushin/hyperdrive-org-transclusion][hyperdrive-org-transclusion]] package adds support for transcluding
hyperdrive files and parts of hyperdrive files with [[https://nobiot.github.io/org-transclusion/][org-transclusion]].

To use this feature, please install ~hyperdrive-org-transclusion~ with
~M-x package-install RET hyperdrive-org-transclusion~ and then add the
following snippet to your configuration:

#+begin_src emacs-lisp
  (with-eval-after-load 'org-transclusion
    (hyperdrive-org-transclusion-mode +1))
#+end_src

You can then run ~M-x org-transclusion-add~ on the following link to
transclude the Org heading with the property ~CUSTOM_ID: emacs~ inside
the ~/software.org~ file inside the USHIN hyperdrive:

#+begin_example
#+transclude: [[hyper://aaj45d88g4eenu76rpmwzjiabsof1w8u6fufq6oogyhjk1ubygxy/software.org#%3A%3A%23emacs]]
#+end_example

** Miscellaneous features

*** Find file at point integration
#+findex: find-file-at-point

If you have enabled ~find-file-at-point~ (~ffap~) bindings with ~M-x
ffap-bindings~, you can open a hyperdrive link by putting the point on
it and pressing ~C-x C-f~.

*** Embark integration
#+findex: embark-act

Embark users can run ~embark-act~ in the ~completing-read~ interface
for selecting a hyperdrive in order to select an alternative action
for the selected hyperdrive.

*** Webjump integration
#+findex: webjump
#+vindex: webjump-sites

You can jump to a ~hyper://~ link with ~M-x webjump~ after adding it to
~webjump-sites~:

#+begin_src emacs-lisp
  (add-to-list
   'webjump-sites
   '("USHIN Hyperdrive" . "hyper://aaj45d88g4eenu76rpmwzjiabsof1w8u6fufq6oogyhjk1ubygxy/"))
#+end_src

* Concepts

** Hyperdrive

[[https://docs.holepunch.to/building-blocks/hyperdrive][Hyperdrive]] is a virtual filesystem which you can use to share files on
the peer-to-peer (P2P) ~hyper~ network.  It's a folder with a globally
unique link starting with ~hyper://~ that you can put files into and
other peers can pull files out of (if they have the link).

Anyone with the link to your hyperdrive can download its contents
directly from your computer.  There's no need to make an account or
rely on a third party to pass the data along.  Anyone who has a copy
of the content in your hyperdrive can serve it to others.  This means
that your hyperdrive can circulate on the ~hyper~ network even when
you're offline.

Hyperdrive is single-writer, meaning that you are the only one who
change a hyperdrive that you've created.  Files in a hyperdrive are
cryptographically signed to ensure that the files you share aren't
tampered with.

You can make as many hyperdrives as you like; the only limitation is
your own disk space.

Hyperdrive is offline-first since you can view files which were
previously downloaded even when your machine is disconnected from the
rest of the network.  It's also local-first, since you can connect
with peers on a local network even without an internet connection.

Unlike BitTorrent, another P2P protocol for sharing files, hyperdrives
are mutable.  If you share a link to your hyperdrive and then later
add, update, or delete files inside it, peers will be able to access
your latest changes at the same link.  When you make revisions to a
hyperdrive, the old versions of your files can still be accessed by
peers on the network.  See [[*Versioning]] for more information.

*** Sparse replication
#+cindex: Sparse replication

Hyperdrives are sparsely replicated, meaning that peers can download
particular files from a hyperdrive without having to download the
whole drive.  This reduces both load times and disk usage.

*** Versioning
#+cindex: Versioning

Hyperdrives are versioned, meaning that it is possible to explore a
hyperdrive as it was in the past.  Version numbers indicate the
hyperdrive's version.  For example, ~hyper://PUBLIC-KEY/$/version/50/~
refers to the fiftieth version of the hyperdrive identified by
~PUBLIC-KEY~.  If you want to load the latest version, leave out the
~/$/version/N~ part.  For example, if you run...

#+begin_example
M-x hyperdrive-open-url RET hyper://PUBLIC-KEY/foo.org RET
#+end_example

...then ~hyperdrive.el~ will attempt to find ~/foo.org~ inside the latest
version of that hyperdrive.

Whenever you add a file, remove a file, or change a file, the
hyperdrive's version number gets incremented by 1.  The version number
tells you how many times the hyperdrive has been modified, not how
many times a particular file has been modified.  For example, let's say
that the current version of your hyperdrive at ~hyper://PUBLIC-KEY/~
is 50.  If you add a new file at ~hyper://PUBLIC-KEY/bar.org~, the latest
version of your hyperdrive will become 51.

Since ~/bar.org~ did not exist before version 51, if you attempt to load
~hyper://PUBLIC-KEY/$/version/50/bar.org~, ~hyperdrive.el~ should warn you
that nothing exists at that URL.  If you add another file at
~hyper://PUBLIC-KEY/quux.org~, your hyperdrive's latest version will
become 52.  For the moment, ~hyper://PUBLIC-KEY/bar.org~,
~hyper://PUBLIC-KEY/$/version/51/bar.org~, and
~hyper://PUBLIC-KEY/$/version/52/bar.org~, all point to the same version
of ~/bar.org~.  If you then make a change to ~/bar.org~, your hyperdrive's
latest version will become 53.  Now ~hyper://PUBLIC-KEY/bar.org~ and
~hyper://PUBLIC-KEY/$/version/53/bar.org~ will point to the latest
version of ~/bar.org~, while the original version will be available at
version 51 or 52.

Here's the mockup of the history view for ~/bar.org~ so far, the
hyperdrive's latest version being 53:

| Version range | exists |
|---------------+--------|
|            53 | yes    |
|         51-52 | yes    |
|          1-50 | no     |

The table shows that ~/bar.org~ was created at version 51 and modified
at version 53.  The final version range number in the table is 53,
indicating that the hyperdrive's latest version is 53.

If you delete ~/bar.org~ then try to load ~hyper://PUBLIC-KEY/bar.org~,
~hyperdrive.el~ will open an empty buffer for you to author a new file.
If another peer attempts to load that URL, ~hyperdrive.el~ will warn
~"URL not found"~, since you are the only one who can modify your drive.
All peers can view the old file contents at the versioned URLs.

Since only the current version of a hyperdrive file can be updated,
~hyperdrive.el~ sets the buffer to read-only whenever a version number
is specified in a hyper URL.

**** Partial version data

Because hyperdrives are sparsely replicated (see [[*Sparse replication]]),
~hyperdrive.el~ might not know the full version history of a file.
In the history view (see [[*History buffer]]), ranges of the history which
have not yet been downloaded from the network are displayed as
"unknown".  You can run the ~hyperdrive-history-load~ command to
download the full history and reload the history buffer.

*** Master key
# TODO: Link to this node once we've added backup/restore.

The secret master key is combined with a seed (see [[*Seeds]]) to generate
a new public key for a hyperdrive when you run ~hyperdrive-new~.  Your
master key is generated automatically by the gateway.

** hyper-gateway-ushin
#+cindex: hyper-gateway-ushin

[[https://git.sr.ht/~ushin/hyper-gateway-ushin][Hyper-gateway-ushin]] handles interactions with hyperdrive under the hood, and
it runs a local HTTP server which offers a Fetch API to access the
Hyperdrive network. In ~hyperdrive.el~, P2P interactions consist
mostly of, e.g., ~GET~ requests to download files and ~PUT~ requests
to write files to a hyperdrive.

** Naming
#+cindex: Naming

Inspired by Marc Stiegler's [[http://www.skyhunter.com/marcs/petnames/IntroPetNames.html][An Introduction to Petname Systems]],
~hyperdrive.el~ names drives in a three different ways:

- Public key :: public, globally unique, not human-memorable
- Nickname   :: public, not necessarily unique, human-memorable
- Petname    :: private, locally unique, human-memorable

If ~hyperdrive.el~ is like a phonebook, then public keys are phone
numbers, nicknames are how your contacts introduce themselves, and
petnames are the names you actually write down.

Each drive may also have one or both of the following attributes:

- Seed       :: string used to generate public key
- DNS domain :: public, globally unique, human-memorable

*** Public keys
#+cindex: Public keys

Public keys are globally unique identifiers for hyperdrives.  They
make up the first part of a ~hyper://~ URL.  Public keys are
52-character-long [[https://en.wikipedia.org/wiki/Base32#z-base-32][z-base-32]] encoded keys generated from your master
key (see [[*Master key]]) and a [[*Seeds][seed]] string.  When you run ~hyperdrive-new~
and type a new seed, the gateway automatically generates a new public
key.

*** Nicknames
#+cindex: Nicknames

Nicknames are public, memorable names which you can give to your own
hyperdrives to make them easier for others to recognize.  Other users
can see your nicknames but cannot change them.

Nicknames are stored in each hyperdrive inside
~/.well-known/host-meta.json~ under the ~name~ key, as specified in
[[https://www.rfc-editor.org/rfc/rfc6415#section-6.1][RFC6415]].

*** Petnames
#+cindex: Petnames

Petnames are locally unique hyperdrive identifiers. You can give a
petname to any hyperdrive you load, whether you created it or not.

*** Seeds
#+cindex: Seeds

Seeds are used in tandem with your secret master key (see [[*Master key]])
to generate public keys (see [[*Public keys]]).  The same seed and master
key will always produce the same public key, so a hyperdrive's seed
cannot be changed.  Seeds are local but not secret.  To share a drive,
you must use a public key or DNS domain (see [[*DNS domains]]).

*** DNS domains
#+cindex: DNS domains

It is possible to use [[https://dnslink.io/][DNSLink]] to link to a hyperdrive with a domain
name instead of a public key (see [[*Public keys]]), like
~hyper://example.org/path/to/file~. Create a TXT record at
~_dnslink.example.org~ with the contents ~/hyper/PUBLIC-KEY~ (no trailing
slash). Note: relying on DNS adds another point of centralization,
reducing the durability of your link. ~hyperdrive.el~ somewhat mitigates
this issue by remembering which public key the DNS record resolved to,
so that peers can use the stored public key itself for subsequent
connections.

DNS domains are checked for suspicious characters (see
[[info:elisp#Suspicious Text]]).

* Customization

You can adjust the following options in the customization interface by
running ~M-x customize-group RET hyperdrive RET~:

- User Option: hyperdrive-gateway-program ::

  Name of executable to run when starting the gateway with
  ~hyperdrive-gateway-start-function~.  ~hyperdrive-install~ will install
  the gateway to this file in ~hyperdrive-gateway-directory~.

- User Option: hyperdrive-gateway-directory ::

  Filesystem directory in which the gateway is expected to be found.
  ~hyperdrive-install~ will install the gateway to this location.  When
  starting the gateway, if ~hyperdrive-gateway-program~ is not found in
  this directory, Emacs searches ~PATH~ for ~hyperdrive-gateway-program~.

- User Option: hyperdrive-gateway-command-args ::

  Command line arguments passed to the gateway when starting the
  gateway with the default ~hyperdrive-gateway-start-function~.

- User Option: hyperdrive-gateway-port ::

  ~hyperdrive.el~ will send HTTP requests to the gateway on this port.
  Defaults to ~4973~.  The default ~hyperdrive-gateway-start-function~
  will start the gateway on this port.

- User Option: hyperdrive-persist-location ::

  Location where ~persist~ will store ~hyperdrive-hyperdrives~ and
  ~hyperdrive-existent-versions~.  Defaults to ~nil~, meaning that the
  default ~persist~ location will be used.

- User Option: hyperdrive-timestamp-format ::

  Format string used for timestamps.  Passed to ~format-time-string~,
  which see.

- User Option: hyperdrive-queue-limit ::

  Default number of request sent to the gateway at a time in a queue.
  Defaults to ~20~.

- User Option: hyperdrive-preferred-formats ::

  List of metadata types used to display hyperdrives.  Hyperdrives are
  displayed using the first available metadata type.  See [[*Naming][Naming]]
  section for what this means.

- User Option: hyperdrive-default-entry-format ::

  Format string for displaying hyperdrive entries (files/directories).
  By default, entries are displayed with the preferred hyperdrive
  format in brackets (see ~hyperdrive-preferred-formats~), followed by
  the full entry path, followed by "version: " and version in
  parentheses.

- User Option: hyperdrive-buffer-name-format ::

  Format string for buffer names of buffers visiting hyperdrive
  files/directories.  By default, this format is like
  ~hyperdrive-default-entry-format~ with the entry name sans directory
  instead of the full path.

- User Option: hyperdrive-formats ::

  Alist mapping hyperdrive and hyperdrive entry metadata to a format
  string, used in ~hyperdrive-default-entry-format~ and
  ~hyperdrive-buffer-name-format~ as well as other places hyperdrives or
  entries are displayed.  By default, each metadatum is prefixed by
  its type, e.g., the petname ~foo~ is displayed by default as
  ~petname:foo~.

  Feel free to adjust the following example configuration for
  abbreviated labels:

  #+begin_src emacs-lisp
    (setq hyperdrive-formats
          '((name . "%s")
            (version . " (%s)")
            (path . "%s")
            (petname . "p:%s")
            (nickname . "n:%s")
            (public-key . "k:%s")
            (short-key . "k:%.8s…")
            (seed . "s:%s")
            (domains . "d:%s")))
  #+end_src

  With this snippet, the petname ~foo~ now displays as ~p:foo~.  For further
  customization, run ~M-x customize-group RET hyperdrive-entry-format~.

** Additional customization

This section mentions ways to change the behavior of ~hyperdrive.el~
besides its own customization options.

*** Completion styles and cycling
#+vindex: completion-category-overrides
#+findex: completing-read

~hyperdrive.el~ offers a ~completing-read~ interface for selecting a
hyperdrive from a list of known hyperdrive.  You can customize the
completion styles and cycling behavior by customizing the ~hyperdrive~
category in ~completion-category-overrides~.

* Known limitations

** No empty directories

Instead of files and folders, Hyperdrive technically has entries and
entry prefixes.  In other words, folders don't exist unless they
contain files.  This results in potentially unexpected behavior:

- it is not possible to create empty directories
- deleting the last file in a folder deletes the folder as well

When a hyperdrive file or folder is not found, ~hyperdrive.el~ prompts
you for an action (see [[*Unknown paths]]).

** Files and folders can have the same name

In the current implementation of Hyperdrive, it's possible for an
entry (folder) and an entry prefix (folder) to have the same name,
e.g., ~hyper://PUBLIC-KEY/foo/bar/~ and ~hyper://PUBLIC-KEY/foo/bar~. In
this case, the folder listing for ~hyper://PUBLIC-KEY/foo/~ would
display the ~bar~ entry but not the ~bar/~ entry prefix.

** Non-UTF-8 encoded text

We have primarily tested reading and writing files which are UTF-8
encoded.  If you use other encodings and you notice issues, please let
us know (see [[*Contributing/Getting help]]).

* Tips

** Quick documentation access

There are many ways to read this info manual within Emacs:

- Command: hyperdrive-info-manual ::

  Open the hyperdrive.el info manual.

You can also open the ~hyperdrive.el~ info manual from ~hyperdrive-menu~
by pressing ~?~ twice.

To view documentation for particular ~hyperdrive.el~ commands,
functions, and variables, press ~C-h o~ (~describe-symbol~).  Inside the
~*Help*~ buffer that pops open, you can press ~i~ (~help-goto-info~) to jump
to the relevant section in the ~hyperdrive.el~ manual.

* Troubleshooting

** Reinstall/upgrade the gateway

Please ensure that you have the expected version of the gateway by
running ~M-x hyperdrive-install~.

* Contributing/Getting help

You're welcome to join our public XMPP chat room!

- ~xmpp:discuss@conference.ushin.org~ ([[https://anonymous.cheogram.com/discuss@conference.ushin.org][Join anonymously from your browser]])
- ~#_bifrost_discuss_conference.ushin.org:aria-net.org~ (Matrix bridge)

Bugs can be submitted to the [[https://todo.sr.ht/~ushin/ushin][ushin issue tracker]]. Patches, comments or
questions can be submitted to the [[https://lists.sr.ht/~ushin/ushin][ushin public inbox]].

* Uninstallation

If you have installed the gateway with ~hyperdrive-install~, you can
delete the gateway which Emacs downloaded according to the values of
~hyperdrive-gateway-directory~ and ~hyperdrive-gateway-program~, which is
~~/.local/lib/hyperdrive.el/hyper-gateway-ushin~ by default.

You can delete the user data which ~hyper-gateway-ushin~ stores by
default in ~~/.local/share/hyper-gateway-nodejs~.

You can remove ~hyperdrive.el~ with ~M-x package-delete hyperdrive~.

* Acknowledgments

Paula Maas and Martin Turner for inspiration, feedback and undying
support.

[[https://github.com/alphapapa/][Adam Porter]] for rewriting ~hyperdrive.el~ and for his work on ~plz.el~.

[[https://mauve.moe/][Mauve Signweaver]] for their guidance into the
world of p2p as well as the development of ~hyper-gateway~.

[[https://emacsair.me/][Jonas Bernoulli]] for improving ~hyperdrive-mirror~ and for his work on
~transient.el~.

[[https://protesilaos.com][Protesilaos Stavrou]] for design input and user-testing ~hyperdrive.el~.

[[https://savannah.gnu.org/users/eliz][Eli Zaretskii]] for guidance about text encoding systems.

[[https://emacs.ch/@yantar92][Ihor Radchenko]] for guidance about security and Org mode integration.

[[https://karl-voit.at/][Karl Voit]] for his feedback which inspired the design of ~hyperdrive-mirror~.

[[https://www.sanityinc.com/][Steve Purcell]] and [[https://github.com/akirak][Akira Komamura]] for suggestions to improve our CI
build manifests.

[[https://eshelyaron.com/][Eshel Yaron]] for the suggestion to add ~hyperdrive-menu-bar-mode~.

[[https://riscy.io/][Chris Rayner]] for the suggestion to add ~hyperdrive-org-transclusion-mode~.

* Indices

** Keystroke index
:PROPERTIES:
:INDEX: ky
:END:

** Function index
:PROPERTIES:
:INDEX: fn
:END:

** Variable index
:PROPERTIES:
:INDEX: vr
:END:

** Concept index
:PROPERTIES:
:INDEX: cp
:END:

* GNU Free Documentation License

#+include: fdl.org

# Local Variables:
# sentence-end-double-space: t
# End:
