diff --git a/conservancy_beancount/config.py b/conservancy_beancount/config.py
new file mode 100644
index 0000000..29cd9d7
--- /dev/null
+++ b/conservancy_beancount/config.py
@@ -0,0 +1,29 @@
+"""User configuration for Conservancy bookkeeping tools"""
+# Copyright © 2020 Brett Smith
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import os
+
+from pathlib import Path
+from typing import (
+ Optional,
+)
+
+class Config:
+ def repository_path(self) -> Optional[Path]:
+ try:
+ return Path(os.environ['CONSERVANCY_REPOSITORY'])
+ except (KeyError, ValueError):
+ return None
diff --git a/tests/test_config.py b/tests/test_config.py
new file mode 100644
index 0000000..589ba45
--- /dev/null
+++ b/tests/test_config.py
@@ -0,0 +1,44 @@
+"""Test Config class"""
+# Copyright © 2020 Brett Smith
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import contextlib
+import os
+
+from conservancy_beancount import config as config_mod
+
+def _update_environ(updates):
+ for key, value in updates.items():
+ if value is None:
+ os.environ.pop(key, None)
+ else:
+ os.environ[key] = str(value)
+
+@contextlib.contextmanager
+def update_environ(**kwargs):
+ revert = {key: os.environ.get(key) for key in kwargs}
+ _update_environ(kwargs)
+ yield
+ _update_environ(revert)
+
+def test_repository_from_environment():
+ with update_environ(CONSERVANCY_REPOSITORY='/usr/local'):
+ config = config_mod.Config()
+ assert config.repository_path().parts == ('/', 'usr', 'local')
+
+def test_no_repository():
+ with update_environ(CONSERVANCY_REPOSITORY=None):
+ config = config_mod.Config()
+ assert config.repository_path() is None