Fix #3002. Auto-expanding for tilda.
diff --git a/mitmproxy/addons/cut.py b/mitmproxy/addons/cut.py
index 7d9a1f361b..6bb52e844a 100644
--- a/mitmproxy/addons/cut.py
+++ b/mitmproxy/addons/cut.py
@@ -1,6 +1,8 @@
 import io
 import csv
 import typing
+import os.path
+
 from mitmproxy import command
 from mitmproxy import exceptions
 from mitmproxy import flow
@@ -87,7 +89,8 @@ def save(
         append = False
         if path.startswith("+"):
             append = True
-            path = mitmproxy.types.Path(path[1:])
+            epath = os.path.expanduser(path[1:])
+            path = mitmproxy.types.Path(epath)
         try:
             if len(cuts) == 1 and len(flows) == 1:
                 with open(path, "ab" if append else "wb") as fp:
diff --git a/mitmproxy/addons/view.py b/mitmproxy/addons/view.py
index 6da17b5bdc..beaadcc6de 100644
--- a/mitmproxy/addons/view.py
+++ b/mitmproxy/addons/view.py
@@ -10,7 +10,6 @@
 """
 import collections
 import typing
-import os
 
 import blinker
 import sortedcontainers
@@ -359,9 +358,8 @@ def load_file(self, path: mitmproxy.types.Path) -> None:
         """
             Load flows into the view, without processing them with addons.
         """
-        spath = os.path.expanduser(path)
         try:
-            with open(spath, "rb") as f:
+            with open(path, "rb") as f:
                 for i in io.FlowReader(f).stream():
                     # Do this to get a new ID, so we can load the same file N times and
                     # get new flows each time. It would be more efficient to just have a
diff --git a/mitmproxy/types.py b/mitmproxy/types.py
index 2d66bb8ec1..23320c1213 100644
--- a/mitmproxy/types.py
+++ b/mitmproxy/types.py
@@ -178,7 +178,7 @@ def completion(self, manager: _CommandBase, t: type, start: str) -> typing.Seque
         return ret
 
     def parse(self, manager: _CommandBase, t: type, s: str) -> str:
-        return s
+        return os.path.expanduser(s)
 
     def is_valid(self, manager: _CommandBase, typ: typing.Any, val: typing.Any) -> bool:
         return isinstance(val, str)
diff --git a/test/mitmproxy/test_types.py b/test/mitmproxy/test_types.py
index 72492fa9a8..aafddef19b 100644
--- a/test/mitmproxy/test_types.py
+++ b/test/mitmproxy/test_types.py
@@ -2,6 +2,7 @@
 import os
 import typing
 import contextlib
+from unittest import mock
 
 from mitmproxy.test import tutils
 import mitmproxy.exceptions
@@ -69,7 +70,10 @@ def test_path():
         b = mitmproxy.types._PathType()
         assert b.parse(tctx.master.commands, mitmproxy.types.Path, "/foo") == "/foo"
         assert b.parse(tctx.master.commands, mitmproxy.types.Path, "/bar") == "/bar"
+        with mock.patch.dict("os.environ", {"HOME": "/home/test"}):
+            assert b.parse(tctx.master.commands, mitmproxy.types.Path, "~/mitm") == "/home/test/mitm"
         assert b.is_valid(tctx.master.commands, mitmproxy.types.Path, "foo") is True
+        assert b.is_valid(tctx.master.commands, mitmproxy.types.Path, "~/mitm") is True
         assert b.is_valid(tctx.master.commands, mitmproxy.types.Path, 3) is False
 
         def normPathOpts(prefix, match):

While I am sorting out in #3074 I decide to try to warm up :grinning: 
The list of all commands, which work with path https://github.com/mitmproxy/mitmproxy/issues/3002#issuecomment-374228453