diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fbfc4f..4404411 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 - Deprecate the `headers` parameter of `dataframe_to_civis` and always tell Civis
   whether the import has headers or not, rather than autodetecting. (#263, #307)
 - Set `cloudpickle` requirements to <1.2 on Python v3.4. (#309)
+- Fixed an issue in the CLI which prevented users from accessing GET /aliases/{id}
+  and simultaneously generated a warning message. (#298, #316)
 
 ### Changed
 - Loosened version requirements of `pyyaml` to include `pyyaml<=5.99`. (#293)
diff --git a/civis/cli/__main__.py b/civis/cli/__main__.py
index 71613b5..510f50e 100755
--- a/civis/cli/__main__.py
+++ b/civis/cli/__main__.py
@@ -29,6 +29,7 @@ from civis.cli._cli_commands import (
     notebooks_download_cmd, notebooks_new_cmd,
     notebooks_up, notebooks_down, notebooks_open)
 from civis.resources import get_api_spec, CACHED_SPEC_PATH
+from civis.resources._resources import parse_method_name
 from civis._utils import open_session
 from civis.compat import FileNotFoundError
 
@@ -99,27 +100,19 @@ def munge_name(s):
 def make_operation_name(path, method, resource_name):
     """Create an appropriate CLI command for an operation.
 
-    E.g., '/imports/files/{id}/runs/{run_id}' -> 'get_imports_files_runs'
+    Examples
+    --------
+    >>> make_operation_name('/scripts/r/{id}/runs/{run_id}', 'get', 'scripts')
+    get-r-runs
     """
-
-    name = path.lower()
-    name = re.sub(r'{[^}]+}', '', name)
-    name = munge_name(name)
+    path = path.lower().lstrip('/')
 
     # Remove resource prefix. Note that the path name for some operations is
     # just the resource name (e.g., /databases).
-    # Munge the resource name for consistency (e.g.,
-    # remote_hosts -> remote-hosts).
-    if name.startswith(munge_name(resource_name)):
-        name = name[len(resource_name):].strip("-")
-
-    # If there's no ID argument at the end, then it'll be a listing operation.
-    if method == 'get' and not path.endswith('}'):
-        method = 'list'
-
-    # Add HTTP method prefix. For operations whose path name is the resource,
-    # make the command just be the HTTP method.
-    name = '{}-{}'.format(method, name) if name else method
+    if path.startswith(resource_name):
+        path = path[len(resource_name):].strip("-")
+
+    name = parse_method_name(method, path).replace("_", "-")
     return name
 
 
@@ -293,7 +286,8 @@ def add_path_commands(path, path_dict, grp, resource):
                                        help="output in JSON instead of YAML"))
 
         if cmd.name in grp.commands:
-            warn("conflicting command name: %s" % cmd.name)
+            warn('conflicting command name "%s" for path "%s"' %
+                 (cmd.name, path))
 
         grp.add_command(cmd)
 

CLI: GET /aliases/{alias} endpoint is inaccessible
The CLI emitted a confusing `UserWarning` of `UserWarning: conflicting command name: get` when I used the terminal command of `civis files download <file-id> <filename>`. This is the line that triggered the said `UserWarning`:

https://github.com/civisanalytics/civis-python/blob/v1.10.0/civis/cli/__main__.py#L287

My CLI file download operation succeeded and got me the file I needed, with no errors or other warnings. We should look into what triggers the `UserWarning` and suppress/remove/fix it as appropriate, though this ticket is probably low-priority.
diff --git a/civis/tests/test_cli.py b/civis/tests/test_cli.py
index 41466fa..137cac5 100644
--- a/civis/tests/test_cli.py
+++ b/civis/tests/test_cli.py
@@ -2,7 +2,9 @@ from collections import OrderedDict
 import json
 import os
 
-from civis.cli.__main__ import generate_cli, invoke
+import pytest
+
+from civis.cli.__main__ import generate_cli, invoke, make_operation_name
 from civis.compat import mock
 from civis.tests import TEST_SPEC
 
@@ -34,7 +36,9 @@ def test_generate_cli_civis(mock_retrieve_spec_dict):
         civis_spec = json.load(f, object_pairs_hook=OrderedDict)
     mock_retrieve_spec_dict.return_value = civis_spec
 
-    cli = generate_cli()
+    with pytest.warns(None) as warn_rec:
+        cli = generate_cli()
+    assert len(warn_rec) == 0
 
     # Check a regular command.
     list_runs_cmd = cli.commands['scripts'].commands['list-containers-runs']
@@ -102,3 +106,15 @@ def test_parameter_case(mock_session):
         json={},
         params={'firstParameter': 'a', 'secondParameter': 'b'},
         method='WIBBLE')
+
+
+@pytest.mark.parametrize(
+    "path,method,resource_name,exp",
+    [('/imports/files/{id}/runs/{run_id}', 'get', 'imports', 'get-files-runs'),
+     ('/aliases/{object_type}/{alias}', 'get', 'aliases', 'get-object-type'),
+     ('/workflows/', 'get', 'workflows', 'list'),
+     ('/results/{id}/grants', 'delete', 'results', 'delete-grants'),
+     ]
+)
+def test_make_operation_name(path, method, resource_name, exp):
+    assert make_operation_name(path, method, resource_name) == exp

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==24.2.0
cbor2==5.4.6
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
-e git+https://github.com/civisanalytics/civis-python.git@84ecf67d98eef03078e68dbd1dc76d9c9f3a9f02#egg=civis
Click==7.0
cloudpickle==1.6.0
exceptiongroup==1.2.2
idna==3.10
importlib-metadata==6.7.0
iniconfig==2.0.0
joblib==0.13.0
jsonref==0.2
jsonschema==3.0.0
packaging==24.0
pluggy==1.2.0
pubnub==4.8.1
pycryptodomex==3.22.0
pyrsistent==0.19.3
pytest==7.4.4
PyYAML==5.4.1
requests==2.31.0
six==1.17.0
tomli==2.0.1
typing_extensions==4.7.1
urllib3==2.0.7
zipp==3.15.0

name: civis-python
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
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_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
  - pip=22.3.1=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
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==24.2.0
      - cbor2==5.4.6
      - charset-normalizer==3.4.1
      - click==7.0
      - cloudpickle==1.6.0
      - exceptiongroup==1.2.2
      - idna==3.10
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - joblib==0.13.0
      - jsonref==0.2
      - jsonschema==3.0.0
      - packaging==24.0
      - pluggy==1.2.0
      - pubnub==4.8.1
      - pycryptodomex==3.22.0
      - pyrsistent==0.19.3
      - pytest==7.4.4
      - pyyaml==5.4.1
      - requests==2.31.0
      - six==1.17.0
      - tomli==2.0.1
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - zipp==3.15.0
prefix: /opt/conda/envs/civis-python

civis/tests/test_cli.py::test_generate_cli_civis civis/tests/test_cli.py::test_make_operation_name[/aliases/{object_type}/{alias}-get-aliases-get-object-type]
civis/tests/test_cli.py::test_blank_output civis/tests/test_cli.py::test_parameter_case
civis/tests/test_cli.py::test_generate_cli_petstore civis/tests/test_cli.py::test_make_operation_name[/imports/files/{id}/runs/{run_id}-get-imports-get-files-runs] civis/tests/test_cli.py::test_make_operation_name[/workflows/-get-workflows-list] civis/tests/test_cli.py::test_make_operation_name[/results/{id}/grants-delete-results-delete-grants]
civis/cli/__main__.py CHANGELOG.md
civis/cli/__main__.py CHANGELOG.md