Lots of stuff to go over here, bear with me :)

> there is no right order for them

Correct, but in most cases I expect users to use keyword arguments for nontrivial APIs like this -- relying on argument order is and always will be fragile/hard to remember/etc, and one of the main benefits for using Python (IMO) over e.g. shell / whatever, is that we *can* use keyword arguments when invoking subroutines.

Moving to fewer arguments that have multiple meanings is certainly one way of combating the 'remembering order' problem, but IMO it's not the best one. Kwargs are :)

Another argument one can make in favor of your 'overloaded/compacted args' tactic is that it's less typing when used frequently -- except in this case I do not see setting up remote tunnels as a frequently-written code snippet. I'd expect maybe a handful of calls to this function in any given fabfile. Given that assumption, a clearer/more explicit API feels like the right tradeoff.

> and people just need to remember to choose between host:port and port.

That's one of the reasons I argue against this, actually -- I've dealt with a large userbase for a while now and users frequently get tripped up with this sort of thing :( Again, in some situations where the function is invoked frequently (or e.g. as a secondary/optional API on top of a more explicit one) I would accept that tradeoff. Here, I don't think the potential for confusion is worth the savings.

> The default for lhost is localhost

Was that a typo or a misread? :) I was talking about the default of the remote host value, `rhost`, not `lhost`: [link](https://github.com/rasky/fabric/blob/42c91442b094536f1dcde334d8416713fae3643f/fabric/context_managers.py#L485). A default *local* host value of `localhost` seems quite reasonable and I wouldn't change that.

> Can you please explain better the env.host_string suggestion? I don't think I understand what you are aiming to.

What I meant was that when users do not give an explicit remote host argument, it should default to what Fabric is currently targeting. Fabric's current target host is always stored in `env.host_string` (it is *the* state value determining current target).

This way, one can invoke the function like so:

``` python
with remote_tunnel(port=8000):
    # stuff
```

and it defaults to forwarding port 8000 from the current target host to port 8000 on localhost. But one can still override it to choose a *different* remote target, e.g.:

``` python
with remote_tunnel(port=8000, remote_host='dbserver'):
    # stuff
```