diff --git a/doc/05-repositories.md b/doc/05-repositories.md
index 2889a1924..703d26266 100644
--- a/doc/05-repositories.md
+++ b/doc/05-repositories.md
@@ -609,8 +609,8 @@ update to the latest version.
 ### Path
 
 In addition to the artifact repository, you can use the path one, which allows
-you to depend on a relative directory. This can be especially useful when dealing
-with monolith repositories.
+you to depend on a local directory, either absolute or relative. This can be
+especially useful when dealing with monolithic repositories.
 
 For instance, if you have the following directory structure in your repository:
 ```
@@ -649,8 +649,8 @@ the console will read `Symlinked from ../../packages/my-package`. If symlinking
 is _not_ possible the package will be copied. In that case, the console will
 output `Mirrored from ../../packages/my-package`.
 
-Instead of default fallback strategy you can force to use symlink with `"symlink": true` or
-mirroring with `"symlink": false` option.
+Instead of default fallback strategy you can force to use symlink with `"symlink": true`
+or mirroring with `"symlink": false` option.
 Forcing mirroring can be useful when deploying or generating package from a monolithic repository.
 
 ```json
@@ -667,9 +667,11 @@ Forcing mirroring can be useful when deploying or generating package from a mono
 }
 ```
 
-
-
-Instead of using a relative path, an absolute path can also be used.
+Leading tildes are expanded to the current user's home folder, and environment
+variables are parsed in both Windows and Linux/Mac notations. For example
+`~/git/mypackage` will automatically load the mypackage clone from
+`/home/<username>/git/mypackage`, equivalent to `$HOME/git/mypackage` or
+`%USERPROFILE%/git/mypackage`.
 
 > **Note:** Repository paths can also contain wildcards like ``*`` and ``?``.
 > For details, see the [PHP glob function](http://php.net/glob).
diff --git a/src/Composer/Config.php b/src/Composer/Config.php
index aaca4e4c9..59306f9d2 100644
--- a/src/Composer/Config.php
+++ b/src/Composer/Config.php
@@ -15,6 +15,7 @@ namespace Composer;
 use Composer\Config\ConfigSourceInterface;
 use Composer\Downloader\TransportException;
 use Composer\IO\IOInterface;
+use Composer\Util\Platform;
 
 /**
  * @author Jordi Boggiano <j.boggiano@seld.be>
@@ -210,7 +211,7 @@ class Config
                 $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
 
                 $val = rtrim($this->process($this->getComposerEnv($env) ?: $this->config[$key], $flags), '/\\');
-                $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $val);
+                $val = Platform::expandPath($val);
 
                 if (substr($key, -4) !== '-dir') {
                     return $val;
diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php
index cb93710e7..4acdb03c7 100644
--- a/src/Composer/Repository/PathRepository.php
+++ b/src/Composer/Repository/PathRepository.php
@@ -18,6 +18,7 @@ use Composer\Json\JsonFile;
 use Composer\Package\Loader\ArrayLoader;
 use Composer\Package\Version\VersionGuesser;
 use Composer\Package\Version\VersionParser;
+use Composer\Util\Platform;
 use Composer\Util\ProcessExecutor;
 
 /**
@@ -101,7 +102,7 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
         }
 
         $this->loader = new ArrayLoader(null, true);
-        $this->url = $repoConfig['url'];
+        $this->url = Platform::expandPath($repoConfig['url']);
         $this->process = new ProcessExecutor($io);
         $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
         $this->repoConfig = $repoConfig;
diff --git a/src/Composer/Util/Platform.php b/src/Composer/Util/Platform.php
index 252041d66..1b2b4031f 100644
--- a/src/Composer/Util/Platform.php
+++ b/src/Composer/Util/Platform.php
@@ -19,6 +19,43 @@ namespace Composer\Util;
  */
 class Platform
 {
+    /**
+     * Parses tildes and environment variables in paths.
+     *
+     * @param string $path
+     * @return string
+     */
+    public static function expandPath($path)
+    {
+        if (preg_match('#^~[/\\\\]#', $path)) {
+            return self::getUserDirectory() . substr($path, 1);
+        }
+        return preg_replace_callback('#^([\\$%])(\\w+)\\1?(([/\\\\].*)?)#', function($matches) {
+            // Treat HOME as an alias for USERPROFILE on Windows for legacy reasons
+            if (Platform::isWindows() && $matches[2] == 'HOME') {
+                return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches[3];
+            }
+            return getenv($matches[2]) . $matches[3];
+        }, $path);
+    }
+
+    /**
+     * @return string The formal user home as detected from environment parameters
+     * @throws \RuntimeException If the user home could not reliably be determined
+     */
+    public static function getUserDirectory()
+    {
+        if (false !== ($home = getenv('HOME'))) {
+            return $home;
+        } elseif (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
+            return $home;
+        } elseif (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
+            $info = posix_getpwuid(posix_getuid());
+            return $info['dir'];
+        }
+        throw new \RuntimeException('Could not determine user directory');
+    }
+
     /**
      * @return bool Whether the host machine is running a Windows OS
      */
diff --git a/tests/Composer/Test/ConfigTest.php b/tests/Composer/Test/ConfigTest.php
index 619e8d55f..0d35faf6a 100644
--- a/tests/Composer/Test/ConfigTest.php
+++ b/tests/Composer/Test/ConfigTest.php
@@ -150,7 +150,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
 
         $home = rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '\\/');
         $this->assertEquals('b', $config->get('c'));
-        $this->assertEquals($home.'/', $config->get('bin-dir'));
+        $this->assertEquals($home, $config->get('bin-dir'));
         $this->assertEquals($home.'/foo', $config->get('cache-dir'));
     }
 
diff --git a/tests/Composer/Test/Util/PlatformTest.php b/tests/Composer/Test/Util/PlatformTest.php
index 4cbe7ffe8..129410d95 100644
--- a/tests/Composer/Test/Util/PlatformTest.php
+++ b/tests/Composer/Test/Util/PlatformTest.php
@@ -21,7 +21,15 @@ use Composer\Util\Platform;
  */
 class PlatformTest extends \PHPUnit_Framework_TestCase
 {
-    public function testWindows()
+    public function testExpandPath()
+    {
+        putenv('TESTENV=/home/test');
+        $this->assertEquals('/home/test/myPath', Platform::expandPath('%TESTENV%/myPath'));
+        $this->assertEquals('/home/test/myPath', Platform::expandPath('$TESTENV/myPath'));
+        $this->assertEquals((getenv('HOME') ?: getenv('USERPROFILE')) . '/test', Platform::expandPath('~/test'));
+    }
+    
+    public function testIsWindows()
     {
         // Compare 2 common tests for Windows to the built-in Windows test
         $this->assertEquals(('\\' === DIRECTORY_SEPARATOR), Platform::isWindows());