Fix link list items in README
[clipper.git] / README.md
1 # Overview
2
3 Clipper is an OS X "launch agent" that runs in the background providing a
4 service that exposes the local clipboard to tmux sessions and other processes
5 running both locally and remotely.
6
7 # Problem
8
9 You're running tmux, possibly on a remote machine via ssh, and want to copy
10 something using tmux copy mode into your local system clipboard.
11
12 You can hold down Option and click to make a selection, bypassing tmux and
13 allowing you to copy straight to the system clipboard, but that won't work if
14 you're using vertical splits (because the selection will operate across the
15 entire width of the terminal, crossing the splits) or if you want to grab more
16 than what is currently visible.
17
18 As a workaround for the vertical split problem, you can hold down Option +
19 Command to make a rectangular (non-contiguous) selection, but that will grab
20 trailing whitespace as well, requiring you to manually clean it up later.
21 Again, it won't work if you want to grab more than what is currently visible.
22
23 As a result, you often find yourself doing a tiresome sequence of:
24
25 1. Copy a selection using tmux copy mode on a remote machine
26 2. Still on the remote machine, open a new, empty buffer in Vim
27 3. Enter Vim paste mode (`:set paste`)
28 4. Paste the tmux copy buffer into the Vim buffer
29 5. Write the file to a temporary location (eg. `:w /tmp/buff`)
30 6. From the local machine, get the contents of the temporary file into the local
31    system clipboard with `ssh user@host cat /tmp/buff | pbcopy` or similar
32
33 # Solution
34
35 OS X comes with a `pbcopy` tool that allows you to get stuff into the clipboard
36 from the command-line. We've already seen this at work above. Basically, we can
37 do things like `echo foo | pbcopy` to place "foo" in the system clipboard.
38
39 tmux has a couple of handy commands related to copy mode buffers, namely
40 `save-buffer` and `show-buffer`. With these, you can dump the contents of a
41 buffer into a text file, or emit it over standard out.
42
43 In theory, combining these two elements, we can add something like this to our
44 `~/.tmux.conf`:
45
46     bind-key C-y run-shell "tmux save-buffer - | pbcopy"
47
48 In practice, this doesn't work because tmux uses the `daemon(3)` system call,
49 which ends up putting it in a different execution context from which it cannot
50 interact with the system clipboard. For (much) more detail, see:
51
52 - http://developer.apple.com/library/mac/#technotes/tn2083/_index.html
53
54 One workaround comes in the form of the `reattach-to-user-space` tool available
55 here:
56
57 - https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard
58
59 This is a wrapper which allows you to launch a process and have it switch from
60 the daemon execution context to the "user" context where access to the system
61 clipboard is possible. The suggestion is that you can add a command like the
62 following to your `~/.tmux.conf` to make this occur transparently whenever you
63 open a new pane or window:
64
65     set-option -g default-command "reattach-to-user-namespace -l zsh"
66
67 Despite the fact that the wrapper tool relies on an undocumented, private API,
68 it is written quite defensively and appears to work pretty well. While this is a
69 workable solution when running only the local machine, we'll need something else
70 if we want things to work transparently both locally and remotely. This is where
71 Clipper comes in.
72
73 Clipper is a server process that you can run on your local machine. It will
74 listen on the network for connections, and place any content that it receives
75 into the system clipboard.
76
77 It can be set to run automatically as a "launch agent" in the appropriate
78 execution context, which means you don't have to worry about starting it, and it
79 will still have access to the system clipboard despite being "daemon"-like.
80
81 Through the magic of `ssh -R` it is relatively straightforward to have a shared
82 tmux configuration that you can use both locally and remotely and which will
83 provide you with transparent access to the local system clipboard from both
84 places.
85
86 # Setup
87
88 ## Installing
89
90 I'm relatively new to Go so am not yet sure what the best way to distribute a
91 command-line applicaton is. So, for now, it boils down to:
92
93     git clone git://git.wincent.com/clipper.git
94     cd clipper
95     go build clipper.go
96     sudo cp clipper /usr/bin
97     cp com.wincent.clipper.plist ~/Library/LaunchAgents/
98     launchctl load -w -S Aqua ~/Library/LaunchAgents/com.wincent.clipper.plist
99
100 Alternatively, if you'd like to run Clipper manually, you can do so with:
101
102     ./clipper [--address=IP_ADDR] [--port=PORT] [--logfile=LOGFILE]
103
104 Note that both of these commands will fail to do the right thing inside of a
105 tmux session. Run `launchctl` from outside of tmux, otherwise Clipper will find
106 itself in the wrong execution context. Similarly, when running manually, either
107 run Clipper outside of tmux or use the aforementioned `reattach-to-user-space`
108 as a wrapper.
109
110 ## Uninstalling
111
112 The launch agent installation can be reversed with:
113
114     launchctl unload ~/Library/LaunchAgents/com.wincent.clipper.plist
115     rm ~/Library/LaunchAgents/com.wincent.clipper.plist
116     sudo rm /usr/bin/clipper
117
118 As before, note that you should only run `launchctl` outside of a tmux session.
119
120 To kill a manually-launched instance of Clipper, just hit Control+C in the
121 terminal where it is running.
122
123 ## Configuring tmux
124
125 Now we can use a slight modification of our command from earlier. Assuming we
126 kept the standard listen address (127.0.0.1) and port (8377), we can use a
127 command like this:
128
129     bind-key C-y run-shell "tmux save-buffer - | nc localhost 8377"
130
131 Here we're using netcat (`nc`)` to send the contents of the buffer to the
132 listening Clipper agent.
133
134 ## Configuring Vim
135
136 There is nothing inherent in Clipper that ties it to tmux. We can use it from
137 any process, including Vim.
138
139 For example, we can add a mapping to our `~/.vimrc` to send the last-yanked text
140 to Clipper:
141
142     nnoremap <leader>y :call system('nc localhost 8377', @0)<CR>
143
144 ## Configuring Zsh
145
146 By setting up an alias:
147
148     alias clip="nc localhost 8377"
149
150 you can conveniently get files and other content into your clipboard:
151
152     cat example.txt | clip
153
154 ## Configuring SSH
155
156 Again, assuming default address and port, we can use `-R` like this:
157
158     ssh -R localhost:8337:localhost:8377 user@host.example.org
159
160 With this, a tmux process running on the remote host can use the same
161 configuration file, and our `run-shell` from above will send the buffer
162 contents to localhost:8377 on the remote machine, which will then be forwarded
163 back over the SSH connection to localhost:8377 on the local machine, where
164 Clipper is listening.
165
166 See the "Security" section below for some considerations.
167
168 To make this automated, entries can be set up in `.ssh/config`:
169
170     Host host.example.org
171       RemoteForward 8377 localhost:8377
172
173 # Security
174
175 At the moment, Clipper doesn't employ any authentication. It does, by default,
176 listen only on the loopback interface, which means that random people on your
177 network won't be able to connect to it. People with access to your local
178 machine, however, will have access; they can push content into your clipboard
179 even if they can't read from it.
180
181 This may be fine on a single-user machine, but when you start using `ssh -R` to
182 expose your Clipper instance on another machine you're evidently increasing your
183 surface area. This may be ok, but my intention is to add an authentication
184 mechanism to the protocol in the near future in any case.
185
186 # Author
187
188 Clipper is written and maintained by Wincent Colaiuta <win@wincent.com>.
189
190 # Development
191
192 Development in progress can be inspected via the project's Git web-based
193 repository browser at:
194
195 - https://wincent.com/repos/clipper
196
197 the clone URL for which is:
198
199 - git://git.wincent.com/clipper.git
200
201 Mirrors exist on GitHub and Gitorious; these are automatically updated once
202 per hour from the authoritative repository:
203
204 - https://github.com/wincent/clipper
205 - https://gitorious.org/clipper/clipper
206
207 Patches are welcome via the usual mechanisms (pull requests, email, posting to
208 the project issue tracker etc).
209
210 # Website
211
212 The official website for Clipper is:
213
214 - https://wincent.com/products/clipper
215
216 Bug reports should be submitted to the issue tracker at:
217
218 - https://wincent.com/issues
219
220 # Donations
221
222 Clipper is free software released under the terms of the BSD license. If you
223 would like to support further development you can make a donation via PayPal to
224 win@wincent.com:
225
226 - https://www.paypal.com/xclick/business=win@wincent.com&item_name=clipper+donation&no_note=1&currency_code=EUR&lc=GB
227
228 # License
229
230 Copyright 2013 Wincent Colaiuta. All rights reserved.
231
232 Redistribution and use in source and binary forms, with or without
233 modification, are permitted provided that the following conditions are met:
234
235 1. Redistributions of source code must retain the above copyright notice,
236    this list of conditions and the following disclaimer.
237 2. Redistributions in binary form must reproduce the above copyright notice,
238    this list of conditions and the following disclaimer in the documentation
239    and/or other materials provided with the distribution.
240
241 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
242 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
243 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
244 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
245 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
247 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
248 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
249 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
250 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
251 POSSIBILITY OF SUCH DAMAGE.
252
253 # History
254
255 ## 0.1 (not yet released)
256
257 - Initial release