diff --git a/CHANGELOG.md b/CHANGELOG.md
index df36685681efec06e9f6cc6a51dc4e7bf2a0eb05..25e15965c8eee3ca529baf4c9c7b57586f4aa4fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,4 @@
 # v2.16
 
 * changed semantics of `wrap_future`
+* added `Directory` to schema configuration
diff --git a/docs/configuration/schema.rst b/docs/configuration/schema.rst
index ae14194c98a71ddec85bc4c5c69037c851c2406b..ef83f2989da4df24c4a22e99c1bd35d60393f401 100644
--- a/docs/configuration/schema.rst
+++ b/docs/configuration/schema.rst
@@ -17,6 +17,14 @@ you should instantiate a Descriptor. Descriptor reflects how your config is nest
 
 .. autoclass:: satella.configuration.schema.File
 
+.. autoclass:: satella.configuration.schema.FileObject
+    :members:
+
+.. autoclass:: satella.configuration.schema.Directory
+
+.. autoclass:: satella.configuration.schema.DirectoryObject
+    :members:
+
 .. autoclass:: satella.configuration.schema.basic.FileObject
 
 .. autoclass:: satella.configuration.schema.IPv4
@@ -71,15 +79,17 @@ Note that providing a short-hand, string type is impossible for descriptors that
 
 Available string types are:
 
-* **int** - Integer
-* **str** - String
-* **list** - List
-* **dict** - Dict
-* **ipv4** - IPv4
-* **any** - Descriptor
-* **bool** - Boolean
-* **union** - Union
-* **caster** - Caster
+* **int** - :class:`~satella.configuration.schema.Integer`
+* **str** - :class:`~satella.configuration.schema.String`
+* **list** - :class:`~satella.configuration.schema.List`
+* **dict** - :class:`~satella.configuration.schema.Dict`
+* **ipv4** - :class:`~satella.configuration.schema.IPv4`
+* **any** - :class:`~satella.configuration.schema.Descriptor`
+* **bool** - :class:`~satella.configuration.schema.Boolean`
+* **union** - :class:`~satella.configuration.schema.Union`
+* **caster** - :class:`~satella.configuration.schema.Caster`
+* **file** - :class:`~satella.configuration.schema.File`
+* **dir** - :class:`~satella.configuration.schema.Directory`
 
 Lists you define as following
 
diff --git a/satella/__init__.py b/satella/__init__.py
index e74eabb222b8ba857449b73eeabc233d9b58c3ae..50a1c84bbf85ed4f580fa779ee011d811959e361 100644
--- a/satella/__init__.py
+++ b/satella/__init__.py
@@ -1 +1 @@
-__version__ = '2.16a1'
+__version__ = '2.16'
diff --git a/satella/configuration/schema/__init__.py b/satella/configuration/schema/__init__.py
index a1f61b57ae317b532db63507b3d6eb36870c368f..e13557041874bcf75d8f42937edb54ca63873e93 100644
--- a/satella/configuration/schema/__init__.py
+++ b/satella/configuration/schema/__init__.py
@@ -1,9 +1,10 @@
 from .base import CheckerCondition, Descriptor
-from .basic import IPv4, Integer, String, Float, Boolean
+from .basic import IPv4, Integer, String, Float, Boolean, File, Directory, FileObject, DirectoryObject
 from .from_json import descriptor_from_dict
 from .registry import register_custom_descriptor
 from .structs import Union, List, Dict, Caster, create_key
 
 __all__ = ['CheckerCondition', 'Descriptor', 'descriptor_from_dict', 'IPv4', 'Integer',
            'String', 'Float', 'Boolean', 'Union', 'List', 'Dict', 'Caster',
+           'File', 'FileObject', 'DirectoryObject', 'Directory',
            'register_custom_descriptor', 'create_key']
diff --git a/satella/configuration/schema/basic.py b/satella/configuration/schema/basic.py
index 5c16bd26fd230805440b74050c054c06743c0760..4eff8c35204699adcd7e312be760819e580b579d 100644
--- a/satella/configuration/schema/basic.py
+++ b/satella/configuration/schema/basic.py
@@ -71,7 +71,7 @@ class FileObject:
         return self.path
 
     def __eq__(self, other) -> bool:
-        return self.path == str(other)
+        return self.path == str(other) and isinstance(other, FileObject)
 
     def __hash__(self) -> int:
         return hash(self.path)
@@ -95,6 +95,37 @@ class FileObject:
         return open(self.path, mode)
 
 
+class DirectoryObject:
+    """
+    What you get for values in schema of :class:`~satella.configuration.schema.Directory`.
+
+    This object is comparable and hashable, and is equal to the string of it's path
+    """
+    __slots__ = 'path',
+
+    def __init__(self, path: str):
+        self.path = path
+
+    def __repr__(self):
+        return '<Directory object %s>' % (self.path, )
+
+    def __str__(self):
+        return self.path
+
+    def __eq__(self, other) -> bool:
+        return self.path == str(other) and isinstance(other, DirectoryObject)
+
+    def __hash__(self) -> int:
+        return hash(self.path)
+
+    def get_files(self) -> tp.Iterable[str]:
+        """
+        Return a list of files inside this directory
+        :return:
+        """
+        return os.listdir(self.path)
+
+
 @staticmethod
 def _make_file(v: str) -> bool:
 
@@ -114,6 +145,25 @@ class File(Descriptor):
     BASIC_MAKER = _make_file
 
 
+@staticmethod
+def _make_directory(v: str) -> bool:
+
+    if not os.path.isdir(v):
+        raise ConfigurationValidationError('Expected to find a directory under %s'
+                                           % (v,))
+    return DirectoryObject(v)
+
+
+@register_custom_descriptor('dir')
+class Directory(Descriptor):
+    """
+    This value must be a valid path to a file. The value in your schema will be
+    an instance of :class:`~satella.configuration.schema.basic.FileObject`
+    """
+
+    BASIC_MAKER = _make_directory
+
+
 class Regexp(String):
     """
     Base class for declaring regexp-based descriptors. Overload it's attribute REGEXP. Use as