diff --git a/git_browse/browse.py b/git_browse/browse.py
index 6a71221..bde7c54 100755
--- a/git_browse/browse.py
+++ b/git_browse/browse.py
@@ -15,15 +15,19 @@ import webbrowser
 
 
 __version__ = '2.6.0'
+GITHUB_HOST = '(?P<host>github\.com)'
+UBER_HOST = '(?P<host>code\.uber\.internal)'
+UBER_CONFIG_HOST = '(?P<host>config\.uber\.internal)'
 USER_REGEX = '(?P<user>[\w\.@:\/~_-]+)'
 REPOSITORY_REGEX = '(?P<repository>[\w\.@:\/~_-]+)'
-GITHUB_SSH_URL = 'git@github.com:%s/%s' % (USER_REGEX, REPOSITORY_REGEX)
-GITHUB_HTTPS_URL = 'https://github.com/%s/%s' % (USER_REGEX, REPOSITORY_REGEX)
-UBER_SSH_GITOLITE_URL = 'gitolite@code.uber.internal:%s' % (REPOSITORY_REGEX)
-UBER_SSH_CONFIG_GITOLITE_URL = 'gitolite@config.uber.internal:%s' % \
-    (REPOSITORY_REGEX)
-UBER_HTTPS_GITOLITE_URL = 'https://code.uber.internal/%s/%s' % \
-    (USER_REGEX, REPOSITORY_REGEX)
+GITHUB_SSH_URL = 'git@%s:%s/%s' % (GITHUB_HOST, USER_REGEX, REPOSITORY_REGEX)
+GITHUB_HTTPS_URL = 'https://%s/%s/%s' % \
+    (GITHUB_HOST, USER_REGEX, REPOSITORY_REGEX)
+UBER_SSH_GITOLITE_URL = 'gitolite@%s:%s' % (UBER_HOST, REPOSITORY_REGEX)
+UBER_SSH_CONFIG_GITOLITE_URL = 'gitolite@%s:%s' % \
+    (UBER_CONFIG_HOST, REPOSITORY_REGEX)
+UBER_HTTPS_GITOLITE_URL = 'https://%s/%s/%s' % \
+    (UBER_HOST, USER_REGEX, REPOSITORY_REGEX)
 
 
 class GithubHost(object):
@@ -115,6 +119,66 @@ class PhabricatorHost(object):
         return None
 
 
+class SourcegraphHost(object):
+    SOURCEGRAPH_URL = 'https://sourcegraph.uberinternal.com/'
+
+    def __init__(self, host: str, repository: str):
+        self.host = host
+        self.repository = repository
+
+    @staticmethod
+    def create(url_regex_match: Match) -> 'SourcegraphHost':
+        repository = url_regex_match.group('repository')
+        if repository[-4:] == '.git':
+            repository = repository[:-4]
+        host = url_regex_match.group('host')
+        return SourcegraphHost(host, repository)
+
+    def get_url(self, git_object: 'GitObject') -> str:
+        repository_url = "%s%s/%s" % (
+            self.SOURCEGRAPH_URL,
+            self.host,
+            self.repository
+        )
+        if git_object.is_commit_hash():
+            return self.commit_hash_url(repository_url, git_object)
+        if git_object.is_root():
+            return repository_url
+        if git_object.is_directory():
+            return self.directory_url(repository_url, git_object)
+        return self.file_url(repository_url, git_object)
+
+    def commit_hash_url(
+            self,
+            repository_url: str,
+            focus_hash: 'GitObject') -> str:
+        repository_url = "%s/-/commit/%s" % (
+            repository_url,
+            focus_hash.identifier
+        )
+        return repository_url
+
+    def directory_url(
+            self,
+            repository_url: str,
+            focus_object: 'GitObject') -> str:
+        repository_url = "%s/-/tree/%s" % (
+            repository_url,
+            focus_object.identifier
+        )
+        return repository_url
+
+    def file_url(self, repository_url: str, focus_object: 'GitObject') -> str:
+        repository_url = "%s/-/blob/%s" % (
+            repository_url,
+            focus_object.identifier
+        )
+        return repository_url
+
+    def valid_focus_object(self, arg: str):
+        return None
+
+
 HOST_REGEXES = {
     GITHUB_SSH_URL: GithubHost,
     GITHUB_HTTPS_URL: GithubHost,
@@ -188,21 +252,24 @@ def get_git_url(git_config_file: str) -> str:
     return git_url
 
 
-def parse_git_url(git_url: str) -> Any:
+def parse_git_url(git_url: str, sourcegraph: bool=False) -> Any:
     for regex, host_class in HOST_REGEXES.items():
         match = re.search(regex, git_url)
         if match:
             break
     if not match:
         raise ValueError("git url not parseable")
-    host = host_class.create(match)
+    if sourcegraph:
+        host = SourcegraphHost.create(match)
+    else:
+        host = host_class.create(match)
     return host
 
 
-def get_repository_host() -> Any:
+def get_repository_host(sourcegraph: bool=False) -> Any:
     git_config_file = get_git_config()
     git_url = get_git_url(git_config_file)
-    repo_host = parse_git_url(git_url)
+    repo_host = parse_git_url(git_url, sourcegraph)
     return repo_host
 
 
@@ -274,12 +341,18 @@ def main() -> None:
         action='store_true',
         help='Do not open the url in the brower, and only print to stdout'
     )
+    parser.add_argument(
+        '-s',
+        '--sourcegraph',
+        action='store_true',
+        help='Open objects in sourcegraph'
+    )
     parser.add_argument(
         '-v', '--version', action='version', version=__version__,
     )
     args = parser.parse_args()
 
-    host = get_repository_host()
+    host = get_repository_host(args.sourcegraph)
     path = os.path.join(os.getcwd(), args.path)
     git_object = get_git_object(args.target, path, host)
     url = host.get_url(git_object)

Support opening git objects in uber sourcegraph
Files: https://sourcegraph.uberinternal.com/code.uber.internal/path/to/repo/-/blob/path/to/file
Repositories: https://sourcegraph.uberinternal.com/code.uber.internal/path/to/repo/
Commits: https://sourcegraph.uberinternal.com/code.uber.internal/path/to/repo/-/commit/commitID


diff --git a/git_browse/tests/test.py b/git_browse/tests/test.py
index 0608c86..0742094 100644
--- a/git_browse/tests/test.py
+++ b/git_browse/tests/test.py
@@ -1,4 +1,5 @@
 import os
+import re
 import shutil
 import sys
 import unittest
@@ -60,6 +61,63 @@ class TestGithubHost(unittest.TestCase):
         )
 
 
+class SourcegraphHost(unittest.TestCase):
+    def setUp(self):
+        self.obj = browse.SourcegraphHost('code.uber.internal', 'asdf')
+
+    def test_init(self):
+        self.assertEqual(self.obj.host, 'code.uber.internal')
+        self.assertEqual(self.obj.repository, 'asdf')
+
+    def test_create(self):
+        repo = 'gitolite@code.uber.internal:a/b'
+        match = re.search(browse.UBER_SSH_GITOLITE_URL, repo)
+        obj = browse.SourcegraphHost.create(match)
+        self.assertEqual(obj.repository, 'a/b')
+
+    def test_create_dot_git(self):
+        repo = 'gitolite@code.uber.internal:a/b.git'
+        match = re.search(browse.UBER_SSH_GITOLITE_URL, repo)
+        obj = browse.SourcegraphHost.create(match)
+        self.assertEqual(obj.repository, 'a/b')
+
+    def test_get_url_commit(self):
+        git_object = browse.FocusHash('abcd')
+        url = self.obj.get_url(git_object)
+        self.assertEqual(
+            url,
+            self.obj.SOURCEGRAPH_URL + 'code.uber.internal/asdf/-/commit/abcd'
+        )
+
+    def test_get_url_root(self):
+        git_object = browse.FocusObject(os.sep)
+        url = self.obj.get_url(git_object)
+        self.assertEqual(
+            url,
+            self.obj.SOURCEGRAPH_URL + 'code.uber.internal/asdf'
+        )
+
+    def test_get_url_directory(self):
+        git_object = browse.FocusObject('zxcv' + os.sep)
+        url = self.obj.get_url(git_object)
+        self.assertEqual(
+            url,
+            self.obj.SOURCEGRAPH_URL + 'code.uber.internal/asdf/-/tree/zxcv/'
+        )
+
+    def test_get_url_file(self):
+        git_object = browse.FocusObject('zxcv')
+        url = self.obj.get_url(git_object)
+        self.assertEqual(
+            url,
+            self.obj.SOURCEGRAPH_URL + 'code.uber.internal/asdf/-/blob/zxcv'
+        )
+
+    def test_valid_focus_object(self):
+        valid = self.obj.valid_focus_object('asdf')
+        self.assertEqual(valid, None)
+
+
 class GitObject(unittest.TestCase):
     def test_is_directory(self):
         obj = browse.GitObject('/asdf')
@@ -159,6 +217,12 @@ class ParseGitURL(unittest.TestCase):
         self.assertEqual(host.user, 'albertyw')
         self.assertEqual(host.repository, 'git-browse')
 
+    def test_sourcegraph_host(self):
+        host = browse.parse_git_url(self.ssh_url, sourcegraph=True)
+        self.assertTrue(host.__class__ is browse.SourcegraphHost)
+        self.assertEqual(host.host, 'github.com')
+        self.assertEqual(host.repository, 'git-browse')
+
     def test_broken_url(self):
         with self.assertRaises(ValueError):
             browse.parse_git_url(self.broken_url)

pip install -e .[dev]
parse_log_pytest
pytest
coverage flake8 mypy pytest
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
coverage==7.2.7
flake8==5.0.4
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
-e git+https://github.com/albertyw/git-browse.git@f8acdd38d1c28524e0ba5f2c44fdd472bfccb1d7#egg=git_browse
importlib-metadata==4.2.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mccabe==0.7.0
mypy==1.4.1
mypy-extensions==1.0.0
packaging @ file:///croot/packaging_1671697413597/work
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycodestyle==2.9.1
pyflakes==2.5.0
pytest==7.1.2
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typed-ast==1.5.5
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
zipp @ file:///croot/zipp_1672387121353/work

name: git-browse
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==7.2.7
      - flake8==5.0.4
      - importlib-metadata==4.2.0
      - mccabe==0.7.0
      - mypy==1.4.1
      - mypy-extensions==1.0.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - typed-ast==1.5.5
prefix: /opt/conda/envs/git-browse

git_browse/tests/test.py::SourcegraphHost::test_create git_browse/tests/test.py::SourcegraphHost::test_create_dot_git git_browse/tests/test.py::SourcegraphHost::test_get_url_commit git_browse/tests/test.py::SourcegraphHost::test_get_url_directory git_browse/tests/test.py::SourcegraphHost::test_get_url_file git_browse/tests/test.py::SourcegraphHost::test_get_url_root git_browse/tests/test.py::SourcegraphHost::test_init git_browse/tests/test.py::SourcegraphHost::test_valid_focus_object git_browse/tests/test.py::ParseGitURL::test_sourcegraph_host
git_browse/tests/test.py::GetGitURL::test_url
git_browse/tests/test.py::TestGithubHost::test_commit_hash_url git_browse/tests/test.py::TestGithubHost::test_directory_url git_browse/tests/test.py::TestGithubHost::test_file_url git_browse/tests/test.py::TestGithubHost::test_get_url git_browse/tests/test.py::TestGithubHost::test_init git_browse/tests/test.py::TestGithubHost::test_root_url git_browse/tests/test.py::GitObject::test_is_directory git_browse/tests/test.py::FocusObject::test_default git_browse/tests/test.py::FocusObject::test_init git_browse/tests/test.py::FocusObject::test_is_directory git_browse/tests/test.py::FocusObject::test_is_not_directory git_browse/tests/test.py::FocusObject::test_is_not_root git_browse/tests/test.py::FocusObject::test_is_root git_browse/tests/test.py::FocusHash::test_init git_browse/tests/test.py::FocusHash::test_is_commit_hash git_browse/tests/test.py::GetRepositoryRoot::test_fail_get git_browse/tests/test.py::GetRepositoryRoot::test_get git_browse/tests/test.py::GetGitConfig::test_get git_browse/tests/test.py::GetGitURL::test_bad_url git_browse/tests/test.py::ParseGitURL::test_broken_url git_browse/tests/test.py::ParseGitURL::test_https_url git_browse/tests/test.py::ParseGitURL::test_ssh_url git_browse/tests/test.py::TestGetRepositoryHost::test_repository_host git_browse/tests/test.py::TestGetFocusObject::test_default_focus_object git_browse/tests/test.py::TestGetFocusObject::test_directory_focus_object git_browse/tests/test.py::TestGetFocusObject::test_file_focus_object git_browse/tests/test.py::TestGetFocusObject::test_get_focus_hash git_browse/tests/test.py::TestGetFocusObject::test_invalid_phabricator_object git_browse/tests/test.py::TestGetFocusObject::test_nonexistend_focus_object git_browse/tests/test.py::TestGetFocusObject::test_phabricator_object git_browse/tests/test.py::TestGetCommitHash::test_get_hash git_browse/tests/test.py::TestGetCommitHash::test_get_unknown_hash git_browse/tests/test.py::TestOpenURL::test_dry_open_url git_browse/tests/test.py::TestOpenURL::test_open_subprocess git_browse/tests/test.py::TestOpenURL::test_open_url git_browse/tests/test.py::FullTest::test_chdir_subdirectory git_browse/tests/test.py::FullTest::test_chdir_subdirectory_file git_browse/tests/test.py::FullTest::test_check_version git_browse/tests/test.py::FullTest::test_default git_browse/tests/test.py::FullTest::test_directory git_browse/tests/test.py::FullTest::test_file git_browse/tests/test.py::FullTest::test_subdirectory git_browse/tests/test.py::FullTest::test_subdirectory_file
git_browse/browse.py
git_browse/browse.py