PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/README.md

https://gitlab.com/wincent/clipper
Markdown | 550 lines | 333 code | 217 blank | 0 comment | 0 complexity | 36fd4135cf91ac20cee0fa8a6e847ba6 MD5 | raw file
  1. ![Clipper](https://raw.github.com/wincent/clipper/master/logo.png)
  2. # Overview
  3. Clipper is a macOS "launch agent" — or Linux daemon — that runs in the background providing a service that exposes the local clipboard to tmux sessions and other processes running both locally and remotely.
  4. # At a glance
  5. # macOS installation (using Homebrew; for non-Homebrew installs see below)
  6. brew install clipper # run this outside of a tmux session
  7. # Configuration for ~/.tmux.conf:
  8. # tmux >= 2.4: bind "Enter" in copy mode to both copy and forward to Clipper
  9. bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "nc localhost 8377"
  10. # Or, if you are running Clipper on a UNIX domain socket:
  11. bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "nc -U ~/.clipper.sock"
  12. # Or, if your version of netcat doesn't have socket support and you want to use socat:
  13. bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "socat - UNIX-CLIENT:~/.clipper.sock"
  14. # tmux >= 1.8 and < 2.4: bind "Enter" in copy mode to both copy and forward to Clipper
  15. bind-key -t vi-copy Enter copy-pipe "nc localhost 8377"
  16. # Or, if you are running Clipper on a UNIX domain socket:
  17. bind-key -t vi-copy Enter copy-pipe "nc -U ~/.clipper.sock"
  18. # Or, if your version of netcat doesn't have socket support and you want to use socat:
  19. bind-key -t vi-copy Enter copy-pipe "socat - UNIX-CLIENT:~/.clipper.sock"
  20. # tmux < 1.8: bind <prefix>-y to forward to Clipper
  21. bind-key y run-shell "tmux save-buffer - | nc localhost 8377"
  22. # Or, if you are running Clipper on a UNIX domain socket:
  23. bind-key y run-shell "tmux save-buffer - | nc -U ~/.clipper.sock"
  24. # Or, if your version of netcat doesn't have socket support and you want to use socat:
  25. bind-key y run-shell "tmux save-buffer - | socat - UNIX-CLIENT:~/.clipper.sock"
  26. # Configuration for ~/.vimrc:
  27. # Bind <leader>y to forward last-yanked text to Clipper
  28. nnoremap <leader>y :call system('nc localhost 8377', @0)<CR>
  29. # Or, if you are running Clipper on a UNIX domain socket:
  30. nnoremap <leader>y :call system('nc -U ~/.clipper.sock', @0)<CR>
  31. # Or, if your version of netcat doesn't have socket support and you want to use socat:
  32. nnoremap <leader>y :call system('socat - UNIX-CLIENT:~/.clipper.sock', @0)<CR>
  33. # Configuration for ~/.bash_profile, ~/.zshrc etc:
  34. # Pipe anything into `clip` to forward it to Clipper
  35. alias clip="nc localhost 8377"
  36. # Or, if you are running Clipper on a UNIX domain socket:
  37. alias clip="nc -U ~/.clipper.sock"
  38. # Or, if your version of netcat doesn't have socket support and you want to use socat:
  39. alias clip="socat - UNIX-CLIENT:~/.clipper.sock"
  40. # Configuration for ~/.ssh/config:
  41. # Forward Clipper connection to remote host
  42. Host host.example.org
  43. RemoteForward 8377 localhost:8377
  44. # Or, if you are running Clipper on a UNIX domain socket:
  45. Host host.example.org
  46. RemoteForward /home/me/.clipper.sock /Users/me/.clipper.sock
  47. # Problem
  48. You're running tmux, possibly on a remote machine via ssh, and want to copy something using tmux copy mode into your local system clipboard.
  49. You can hold down Option and click to make a selection, bypassing tmux and allowing you to copy straight to the system clipboard, but that won't work if you're using vertical splits (because the selection will operate across the entire width of the terminal, crossing the splits) or if you want to grab more than what is currently visible.
  50. As a workaround for the vertical split problem, you can hold down Option + Command to make a rectangular (non-contiguous) selection, but that will grab trailing whitespace as well, requiring you to manually clean it up later. Again, it won't work if you want to grab more than what is currently visible.
  51. As a result, you often find yourself doing a tiresome sequence of:
  52. 1. Copy a selection using tmux copy mode on a remote machine
  53. 2. Still on the remote machine, open a new, empty buffer in Vim
  54. 3. Enter Vim paste mode (`:set paste`)
  55. 4. Paste the tmux copy buffer into the Vim buffer
  56. 5. Write the file to a temporary location (eg. `:w /tmp/buff`)
  57. 6. From the local machine, get the contents of the temporary file into the local system clipboard with `ssh user@host cat /tmp/buff | pbcopy` or similar
  58. # Solution
  59. macOS comes with a `pbcopy` tool that allows you to get stuff into the clipboard from the command-line. `xclip` is an alternative that works on Linux. We've already seen this at work above. Basically, we can do things like `echo foo | pbcopy` to place "foo" in the system clipboard.
  60. tmux has a few handy commands related to copy mode buffers, namely `save-buffer`, `copy-pipe` and `copy-pipe-and-cancel`, the availability of which depends on the version of tmux that you are running. With these, you can dump the contents of a buffer to standard out.
  61. In theory, combining these elements, we can add something like this to our `~/.tmux.conf`:
  62. bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel pbcopy
  63. or, in a version of tmux prior to 2.4 (which use `vi-copy` instead of `copy-mode-vi`, and `copy-pipe` instead of `copy-pipe-and-cancel`):
  64. bind-key -t vi-copy Enter copy-pipe pbcopy
  65. or, in an even older version of tmux prior to 1.8 (which don't have the `copy-pipe-and-cancel` or `copy-pipe` commands):
  66. bind-key y run-shell "tmux save-buffer - | pbcopy"
  67. In practice, this won't work on versions of macOS prior to 10.10 "Yosemite" or after 10.11 "El Capitan" &mdash; there was a brief lapse during those versions where it did work &mdash; because tmux uses the `daemon(3)` system call, which ends up putting it in a different execution context from which it cannot interact with the system clipboard. For (much) more detail, see:
  68. - http://developer.apple.com/library/mac/#technotes/tn2083/_index.html
  69. One workaround comes in the form of the `reattach-to-user-space` tool available here:
  70. - https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard
  71. This is a wrapper which allows you to launch a process and have it switch from the daemon execution context to the "user" context where access to the system clipboard is possible. The suggestion is that you can add a command like the following to your `~/.tmux.conf` to make this occur transparently whenever you open a new pane or window:
  72. set-option -g default-command "reattach-to-user-namespace -l zsh"
  73. Despite the fact that the wrapper tool relies on an undocumented, private API, it is written quite defensively and appears to work pretty well. While this is a workable solution when running on the local machine  so workable in fact that it is baked into tmux itself in version 2.6 we'll need something else if we want things to work transparently both locally and remotely, or on older versions of tmux. This is where Clipper comes in.
  74. Clipper is a server process that you can run on your local machine. It will listen on the network or on a UNIX domain socket for connections, and place any content that it receives into the system clipboard.
  75. It can be set to run automatically as a "launch agent" in the appropriate execution context, which means you don't have to worry about starting it, and it will still have access to the system clipboard despite being "daemon"-like.
  76. Through the magic of `ssh -R` it is relatively straightforward to have a shared tmux configuration that you can use both locally and remotely and which will provide you with transparent access to the local system clipboard from both places.
  77. # Setup
  78. ## Installing
  79. For Homebrew users, install by running (outside of all tmux sessions):
  80. brew install clipper # and follow the prompts...
  81. Alternatively, if you have a working Go environment on your system you can do:
  82. go get github.com/wincent/clipper
  83. Finally, if you want to do things manually, you can clone from the authoritative Git repo and build manually (which again requires a working Go environment):
  84. git clone git://git.wincent.com/clipper.git
  85. cd clipper
  86. go build
  87. ### Additional steps for non-Homebrew installs
  88. If you plan to use Clipper as a launch agent you'll need to put it somewhere the system can find it (ie. at a location in the standard PATH, such as under `/usr/local/bin/`) and update the included property list file to specify the full path to the location where you installed the Clipper executable.
  89. The following examples show how you would install the built Clipper executable to `/usr/local/bin/` after cloning the repo and performing a build. It also shows how you would set up Clipper as a launch agent (on macOS) or systemd service (on Linux) and start it running:
  90. #### macOS example setup
  91. sudo cp clipper /usr/local/bin
  92. cp contrib/darwin/tcp-port/com.wincent.clipper.plist ~/Library/LaunchAgents/
  93. launchctl load -w -S Aqua ~/Library/LaunchAgents/com.wincent.clipper.plist
  94. Note that these commands may fail to do the right thing inside of a tmux session under macOS. Run `launchctl` from outside of tmux, otherwise Clipper may find itself in the wrong execution context. Similarly, when running manually, either run Clipper outside of tmux or use the aforementioned `reattach-to-user-space` as a wrapper.
  95. #### Linux example setup
  96. sudo cp clipper /usr/local/bin
  97. cp contrib/linux/systemd-service/clipper.service ~/.config/systemd/user
  98. systemctl --user daemon-reload
  99. systemctl --user enable clipper.service
  100. systemctl --user start clipper.service
  101. #### Manual setup
  102. Alternatively, if you'd like to run Clipper manually, you can do so with:
  103. ./clipper [--address=IP_ADDR|UNIX_SOCKET] \
  104. [--port=PORT] \
  105. [--logfile=LOGFILE] \
  106. [--config=CONFIG_FILE]
  107. ## Uninstalling
  108. A Homebrew installation can be reversed with:
  109. brew uninstall clipper
  110. A manual launch agent installation can be reversed with the following (and as before, note that you should probably only run `launchctl` outside of a tmux session):
  111. launchctl unload ~/Library/LaunchAgents/com.wincent.clipper.plist
  112. rm ~/Library/LaunchAgents/com.wincent.clipper.plist
  113. sudo rm /usr/local/bin/clipper
  114. On Linux:
  115. systemctl --user stop clipper.service
  116. systemctl --user disable clipper.service
  117. sudo rm /usr/local/bin/clipper
  118. To kill a manually-launched instance of Clipper, just hit Control+C in the terminal where it is running.
  119. ## Configuring Clipper
  120. As previously noted, Clipper supports a number of command line options, which you can see by running `clipper -h`:
  121. ```
  122. Usage of clipper:
  123. -a string
  124. address to bind to (default loopback interface)
  125. -address string
  126. address to bind to (default loopback interface)
  127. -c string
  128. path to (JSON) config file (default "~/.clipper.json")
  129. -config string
  130. path to (JSON) config file (default "~/.clipper.json")
  131. -e string
  132. program called to write to clipboard (default "pbcopy")
  133. -executable string
  134. program called to write to clipboard (default "pbcopy")
  135. -f string
  136. arguments passed to clipboard executable
  137. -flags string
  138. arguments passed to clipboard executable
  139. -h show usage information
  140. -help
  141. show usage information
  142. -l string
  143. path to logfile (default "~/Library/Logs/com.wincent.clipper.log")
  144. -logfile string
  145. path to logfile (default "~/Library/Logs/com.wincent.clipper.log")
  146. -p int
  147. port to listen on (default 8377)
  148. -port int
  149. port to listen on (default 8377)
  150. -v show version information
  151. -version
  152. show version information
  153. ```
  154. The defaults shown above apply on macOS. Run `clipper -h` on Linux to see the defaults that apply there.
  155. You can explicitly set these on the command line, or in the plist file if you are using Clipper as a launch agent. Clipper will also look for a configuration file in JSON format at `~/.clipper.json` (this location can be overidden with the `--config`/`-c` options) and read options from that. The following options are supported:
  156. - `address`
  157. - `executable`
  158. - `flags`
  159. - `logfile`
  160. - `port`
  161. Here is a sample `~/.clipper.json` config file:
  162. ```
  163. {
  164. "address": "~/.run/clipper.sock",
  165. "logfile": "~/Library/Logs/clipper.log"
  166. }
  167. ```
  168. Note that explicit command line options including options supplied via a plist trump options read from a config file.
  169. ### `--address`
  170. Specifies the address on which the Clipper daemon will listen for connections. Defaults to "localhost", and listens on both IPv4 and IPv6 addresses, when available. This is a reasonable default, but you may wish to set it to a filesystem path instead in order to have Clipper create a UNIX domain socket at that location and listen on that instead (for better security: see "Security" below for more). Or perhaps you would like to _only_ listen on IPv4 _or_ IPv6, in which case you would use "127.0.0.1" or "[::1]" respectively (the square brackets around the IPv6 address are needed by the Go networking libraries in order to disambiguate the colons in the address from colons used to separate it from the port number). Note that if you see an error of the form "too many colons in address", it is likely that you have forgotten to wrap the IPv6 address in surrounding brackets.
  171. ### `--port`
  172. The port on which the Clipper daemon will accept TCP connections. Defaults to 8377. You may wish to set this to some other value, to avoid colliding with another service (or Clipper user) on your system using that port, or because you want some tiny extra dose of security through obscurity.
  173. Note that if you use the `--address` option to make Clipper use a UNIX domain socket, then setting the `--port` has no useful effect.
  174. See the "Security" section below for more.
  175. ### `--logfile`
  176. Unsurprisingly, controls where the Clipper daemon logs its output. Defaults to "~/Library/Logs/com.wincent.clipper.log".
  177. As an example, you could disable all logging by setting this to "/dev/null".
  178. ### `--executable`
  179. The executable used to place content on the clipboard (defaults to `pbcopy` on macOS and `xclip` on Linux).
  180. ### `--flags`
  181. The flags to pass to the `executable` (defaults to `-selection clipboard` on Linux and nothing on macOS).
  182. ## Configuring tmux
  183. Now we can use a slight modification of our command from earlier. Assuming we kept the standard listen address (127.0.0.1) and port (8377), we can use a command like this to send the last-copied text whenever we hit our tmux prefix key followed by `y`; here we're using netcat (`nc`) to send the contents of the buffer to the listening Clipper agent:
  184. bind-key y run-shell "tmux save-buffer - | nc localhost 8377"
  185. If we instead configured Clipper to listen on a UNIX domain socket at `~/.clipper.sock`, then we could do something like:
  186. bind-key y run-shell "tmux save-buffer - | nc -U ~/.clipper.sock"
  187. Or, alternatively, with `socat` (which may be useful if your version of `nc` doesn't support the `-U` switch):
  188. bind-key y run-shell "tmux save-buffer - | socat - UNIX-CLIENT:~/.clipper.sock"
  189. In tmux 1.8 to 2.3, we have access to the new `copy-pipe` command and can use a single key binding to copy text into the tmux copy buffer and send it to Clipper and therefore the system clipboard at the same time:
  190. bind-key -t vi-copy Enter copy-pipe "nc localhost 8377"
  191. Or, for a UNIX domain socket at `~/.clipper.sock`:
  192. bind-key -t vi-copy Enter copy-pipe "nc -U ~/.clipper.sock"
  193. Or, with `socat`:
  194. bind-key -t vi-copy Enter copy-pipe "socat - UNIX-CLIENT:~/.clipper.sock"
  195. In tmux 2.4 and above, we would use:
  196. bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "nc localhost 8377"
  197. Or, for a UNIX domain socket at `~/.clipper.sock`:
  198. bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "nc -U ~/.clipper.sock"
  199. Or, with `socat`:
  200. bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "socat - UNIX-CLIENT:~/.clipper.sock"
  201. ## Configuring Vim
  202. There is nothing inherent in Clipper that ties it to tmux. We can use it from any process, including Vim.
  203. For example, we can add a mapping to our `~/.vimrc` to send the last-yanked text to Clipper by hitting `<leader>y`:
  204. nnoremap <leader>y :call system('nc localhost 8377', @0)<CR>
  205. Equivalently, we could do the same for a Clipper daemon listening on a UNIX domain socket at `~/.clipper.sock` with:
  206. nnoremap <leader>y :call system('nc -U ~/.clipper.sock', @0)<CR>
  207. Or, with `socat`:
  208. nnoremap <leader>y :call system('socat - UNIX-CLIENT:~/.clipper.sock', @0)<CR>
  209. For the lazy, this functionality plus a `:Clip` command is made available as a [separate Vim plug-in](https://github.com/wincent/vim-clipper) called "vim-clipper", which additionally makes it possible to use the `TextYankPost` autocommand to forward all yanked text to Clipper automatically on versions of Vim that support it (currently, Neovim).
  210. ## Configuring Zsh (or Bash)
  211. By setting up an alias like:
  212. alias clip="nc localhost 8377"
  213. or (in the case of Clipper listening on a UNIX domain socket at `~/.clipper.sock`):
  214. alias clip="nc -U ~/.clipper.sock"
  215. or, with `socat`:
  216. alias clip="socat - UNIX-CLIENT:~/.clipper.sock"
  217. you can conveniently get files and other content into your clipboard:
  218. cat example.txt | clip
  219. ls /etc | clip
  220. ## Configuring SSH
  221. Again, assuming default address and port, we can use `-R` like this:
  222. ssh -R localhost:8377:localhost:8377 user@host.example.org
  223. Or, in the case of a UNIX domain socket at `~/.clipper.sock` and a sufficiently recent version of OpenSSH (version 6.7 or above):
  224. # Assuming a local socket on macOS in $HOME at /Users/me/.clipper.sock
  225. # and a remote Linux machine with $HOME is in /home rather than /Users:
  226. ssh -R/home/me/.clipper.sock:/Users/me/.clipper.sock host.example.org
  227. With this, a tmux process running on the remote host can use the same configuration file, and our `run-shell` from above will send the buffer contents to localhost:8377 (or the UNIX domain socket) on the remote machine, which will then be forwarded back over the SSH connection to localhost:8377 (or the UNIX domain socket) on the local machine, where Clipper is listening.
  228. See the "Security" section below for some considerations.
  229. To make this automated, entries can be set up in `.ssh/config`:
  230. # TCP forwarding:
  231. Host host.example.org
  232. RemoteForward 8377 localhost:8377
  233. # UNIX domain socket forwarding:
  234. Host host.example.org
  235. RemoteForward /home/me/.clipper.sock:/Users/me/.clipper.sock
  236. With this, forwarding is automatically set up any time you run:
  237. ssh user@host.example.org
  238. This works particularly well if you use the `ControlMaster`, `ControlPath` and `ControlPersist` settings described in the `ssh_config` man page. These allow you to set up a single forward, and re-use it each time you connect, even if you have multiple concurrent connnections to a given server. An example `~/.ssh/config` configuration that would give you this for all hosts would be something like:
  239. Host *
  240. ControlMaster auto
  241. ControlPath ~/.ssh/%r@%h:%p
  242. ControlPersist 240
  243. ## Configuring Mosh
  244. [Mosh](http://mosh.mit.edu/) is an alternative to SSH that aims to be a superior "mobile shell" than SSH. It is designed to handle intermittent connectivity, and provides relatively intelligent local echoing of line editing commands, but it [doesn't yet support any kind of port forwarding](https://github.com/mobile-shell/mosh/issues/499) (as of the current release, which is version 1.2.5 at the time of writing).
  245. One way to use Clipper with Mosh is to use Mosh for interactive editing but keep using SSH for port forwarding. For example, just say you want to connect to a remote machine with the alias "sandbox", you could have entries like this in your `~/.ssh/config`:
  246. Host sandbox
  247. ControlMaster no
  248. ControlPath none
  249. Hostname sandbox.example.com
  250. Host sandbox-clipper
  251. ControlMaster no
  252. ControlPath none
  253. ExitOnForwardFailure yes
  254. Hostname sandbox.example.com
  255. RemoteForward 8377 localhost:8377
  256. With this set-up, you can set up the tunnel with:
  257. ssh -N -f sandbox-clipper
  258. SSH will connect to the server, set up the port forwarding and then go into the background.
  259. Then connect using Mosh (it will respect the settings in your `~/.ssh/config` file because it uses SSH to bootstrap new connections):
  260. mosh sandbox
  261. You could also set up a shell alias to make setting up the Clipper tunnel more convenient; for example:
  262. alias clip-sandbox='ssh -N -f sandbox-clipper'
  263. You should only need to re-run this command if the connection is interrupted for some reason.
  264. # Troubleshooting
  265. ## Fixing `remote port forwarding failed for listen port 8377`
  266. This message can be emitted when the remote host you're connecting to already has something bound to the requested port. If there is a competing service that you can't move to another port, Clipper can be configured to use a different port with the `--port` switch, described above.
  267. Another reason you might see this warning is because an old or stale SSH daemon is lingering from a prior connection attempt. The following example commands show how you can detect the PID of such a process (in this example, 29517) and kill it off:
  268. $ sudo netstat -antpl | grep 8377 # look for offending PID (29517) in output
  269. $ ps auxww | grep 29517 # confirm it's your old sshd process
  270. $ kill 29517 # kill off old process
  271. $ ps auxww | grep 29517 # confirm that process is really gone
  272. For the bold and lazy, you can simply kill off all `sshd` process belonging to your user with:
  273. $ killall -u $USER sshd
  274. Do not do this as root, as you will lock yourself out of your server.
  275. Consult the netstat man page for more details (supported options may vary depending on the host operating system).
  276. ## Fixing `remote port forwarding failed` when using UNIX domain sockets
  277. Just as with TCP port forwarding, forwarding can fail when using UNIX domain sockets if a stale socket doesn't get automatically cleaned up (or overwritten, as should be the case when `StreamLocalBindUnlink yes` is present in the server's `sshd_config` file).
  278. In this case, the fix is to remove the stale socket on the remote host. For example, assuming a socket in `$HOME/.clipper.sock` on the remote host, `$HOST`:
  279. $ ssh $HOST rm .clipper.sock
  280. ## Fixing delays when sending data to Clipper via `nc`
  281. It's [been reported](https://github.com/wincent/clipper/issues/11) that on some systems sending data to Clipper via `nc` may be affected by an annoying delay. Reportedly, adding the `-N` switch to `nc` may address this issue.
  282. # "Reverse" Clipper
  283. Clipper helps you get content into your local clipboard from other, possibly remote, processes. To send content in the other direction, just paste normally. Note that to make this pleasant in an environment like Vim, you may want to set up bracketed paste mode; see [my dotfiles for an example](https://github.com/wincent/wincent/blob/3b0b2950cdcb09d23c87f0167c207d8c837cb1b2/.vim/plugin/term.vim#L93-114) of how this can be done.
  284. # Security
  285. At the moment, Clipper doesn't employ any authentication. It does, by default, listen only on the loopback interface, which means that random people on your network won't be able to connect to it. People with access to your local machine, however, will have access; they can push content into your clipboard even if they can't read from it.
  286. This may be fine on a single-user machine, but when you start using `ssh -R` to expose your Clipper instance on another machine you're evidently increasing your surface area. In order to mitigate this risk, you can configure Clipper to listen only on a UNIX domain socket, and place that socket in a location where the file-system permissions prevent others from accessing it.
  287. Most SSH systems are configured to use restrictive permissions on forwarded socket files (unless overridden; see the documentation for `StreamLocalBindMask` in `man ssh_config`), but you may wish to place the socket in a non-shared location like `~/.clipper.sock` rather than a shared one like `/tmp/clipper.sock` in any case.
  288. # Authors
  289. Clipper is written and maintained by Greg Hurrell <greg@hurrell.net>.
  290. Other contributors that have submitted patches include, in alphabetical order:
  291. - Jannis Hermanns
  292. - Nelson Fernandez
  293. - Paul Choi
  294. # Development
  295. The official Clipper source code repo is at:
  296. - http://git.wincent.com/clipper.git
  297. Mirrors exist at:
  298. - https://github.com/wincent/clipper
  299. - https://gitlab.com/wincent/clipper
  300. - https://bitbucket.org/ghurrell/clipper
  301. Patches are welcome via the usual mechanisms (pull requests, email, posting to the project issue tracker etc).
  302. # Website
  303. The official website for Clipper is:
  304. - https://github.com/wincent/clipper
  305. Bug reports should be submitted to the issue tracker at:
  306. - https://github.com/wincent/clipper/issues
  307. # License
  308. Copyright 2013-present Greg Hurrell. All rights reserved.
  309. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  310. 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  311. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  312. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  313. # History
  314. ## 2.0.0 (4 September 2018)
  315. - Accept an empty string for the `--flags` option, allowing flags to be suppressed ([#15](https://github.com/wincent/clipper/issues/15)).
  316. ## 1.0.0 (28 December 2017)
  317. - Automatically clean up stale socket files at startup.
  318. ## 0.4.2 (14 April 2017)
  319. - Fix binding to all interfaces instead of just the loopback interface when no address is provided ([#9](https://github.com/wincent/clipper/issues/9)).
  320. ## 0.4.1 (13 December 2016)
  321. - Create socket with user-only permissions, for better security.
  322. ## 0.4 (28 November 2016)
  323. - Linux support via `xclip` instead of `pbcopy` (patch from Nelson Fernandez).
  324. - Added `--executable` and `--flags` options.
  325. - On dual-stack systems, listen on both IPv4 and IPv6 loopback interfaces by default.
  326. ## 0.3 (3 June 2016)
  327. - Add support for listening over a UNIX domain socket.
  328. - Add support for reading options from a config file (`--config`/`-c` switch).
  329. ## 0.2 (2 November 2013)
  330. - Documentation updates.
  331. - Updated sample plist to use UTF-8 encoding by default.
  332. ## 0.1 (19 February 2013)
  333. - Initial release.