def METHOD_NAME(self, path, detail=False, sha=None, _sha=None, **kwargs):
    """List files at given path
    Parameters
    ----------
    path: str
        Location to list, relative to repo root
    detail: bool
        If True, returns list of dicts, one per file; if False, returns
        list of full filenames only
    sha: str (optional)
        List at the given point in the repo history, branch or tag name or commit
        SHA
    _sha: str (optional)
        List this specific tree object (used internally to descend into trees)
    """
    path = self._strip_protocol(path)
    if path == "":
        _sha = sha or self.root
    if _sha is None:
        parts = path.rstrip("/").split("/")
        so_far = ""
        _sha = sha or self.root
        for part in parts:
            out = self.METHOD_NAME(so_far, True, sha=sha, _sha=_sha)
            so_far += "/" + part if so_far else part
            out = [o for o in out if o["name"] == so_far]
            if not out:
                raise FileNotFoundError(path)
            out = out[0]
            if out["type"] == "file":
                if detail:
                    return [out]
                else:
                    return path
            _sha = out["sha"]
    if path not in self.dircache or sha not in [self.root, None]:
        r = requests.get(
            self.url.format(org=self.org, repo=self.repo, sha=_sha), **self.kw
        )
        if r.status_code == 404:
            raise FileNotFoundError(path)
        r.raise_for_status()
        types = {"blob": "file", "tree": "directory"}
        out = [
            {
                "name": path + "/" + f["path"] if path else f["path"],
                "mode": f["mode"],
                "type": types[f["type"]],
                "size": f.get("size", 0),
                "sha": f["sha"],
            }
            for f in r.json()["tree"]
            if f["type"] in types
        ]
        if sha in [self.root, None]:
            self.dircache[path] = out
    else:
        out = self.dircache[path]
    if detail:
        return out
    else:
        return sorted([f["name"] for f in out])