Add `httpie cli plugins` in favor of the new cli namespace.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 509e7ee27c..c8cd462e02 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,8 +5,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
 
 ## [3.1.1.dev0](https://github.com/httpie/httpie/compare/3.1.0...HEAD) (Unreleased)
 
+- Changed `httpie plugins` to the new `httpie cli` namespace as `httpie cli plugins` (`httpie plugins` continues to work as a hidden alias). ([#1320](https://github.com/httpie/httpie/issues/1320))
 - Fixed redundant creation of `Content-Length` header on `OPTIONS` requests. ([#1310](https://github.com/httpie/httpie/issues/1310))
 
+
 ## [3.1.0](https://github.com/httpie/httpie/compare/3.0.2...3.1.0) (2022-03-08)
 
 - **SECURITY** Fixed the [vulnerability](https://github.com/httpie/httpie/security/advisories/GHSA-9w4w-cpc8-h2fq) that caused exposure of cookies on redirects to third party hosts. ([#1312](https://github.com/httpie/httpie/pull/1312))
diff --git a/docs/README.md b/docs/README.md
index 605640f120..dbab8714ec 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -2347,7 +2347,7 @@ However, it is not recommended modifying the default behavior in a way that woul
 #### `plugins_dir`
 
 The directory where the plugins will be installed. HTTPie needs to have read/write access on that directory, since
-`httpie plugins install` will download new plugins to there. See [plugin manager](#plugin-manager) for more information.
+`httpie cli plugins install` will download new plugins to there. See [plugin manager](#plugin-manager) for more information.
 
 ### Un-setting previously specified options
 
@@ -2425,7 +2425,7 @@ $ httpie cli export-args | jq '"Program: " + .spec.name + ", Version: " +  .vers
 "Program: http, Version: 0.0.1a0"
 ```
 
-### `httpie plugins`
+#### `httpie cli plugins`
 
 `plugins` interface is a very simple plugin manager for installing, listing and uninstalling HTTPie plugins.
 
@@ -2436,13 +2436,13 @@ plugin installations on every installation method.
 By default, the plugins (and their missing dependencies) will be stored under the configuration directory,
 but this can be modified through `plugins_dir` variable on the config.
 
-#### `httpie plugins install`
+##### `httpie cli plugins install`
 
-For installing plugins from [PyPI](https://pypi.org/) or from local paths, `httpie plugins install`
+For installing plugins from [PyPI](https://pypi.org/) or from local paths, `httpie cli plugins install`
 can be used.
 
 ```bash
-$ httpie plugins install httpie-plugin
+$ httpie cli plugins install httpie-plugin
 Installing httpie-plugin...
 Successfully installed httpie-plugin-1.0.2
 ```
@@ -2450,12 +2450,12 @@ Successfully installed httpie-plugin-1.0.2
 > Tip: Generally HTTPie plugins start with `httpie-` prefix. Try searching for it on [PyPI](https://pypi.org/search/?q=httpie-)
 > to find out all plugins from the community.
 
-#### `httpie plugins list`
+##### `httpie cli plugins list`
 
 List all installed plugins.
 
 ```bash
-$ httpie plugins list
+$ httpie cli plugins list
 httpie_plugin (1.0.2)
   httpie_plugin (httpie.plugins.auth.v1)
 httpie_plugin_2 (1.0.6)
@@ -2465,21 +2465,21 @@ httpie_converter (1.0.0)
   httpie_konsole_konverter (httpie.plugins.converter.v1)
 ```
 
-#### `httpie plugins upgrade`
+##### `httpie cli plugins upgrade`
 
 For upgrading already installed plugins, use `httpie plugins upgrade`.
 
 ```bash
-$ httpie plugins upgrade httpie-plugin
+$ httpie cli plugins upgrade httpie-plugin
 ```
 
-#### `httpie plugins uninstall`
+##### `httpie cli plugins uninstall`
 
 Uninstall plugins from the isolated plugins directory. If the plugin is not installed
-through `httpie plugins install`, it won’t uninstall it.
+through `httpie cli plugins install`, it won’t uninstall it.
 
 ```bash
-$ httpie plugins uninstall httpie-plugin
+$ httpie cli plugins uninstall httpie-plugin
 ```
 
 ## Meta
diff --git a/httpie/manager/cli.py b/httpie/manager/cli.py
index 313f145007..2ae34fdb40 100644
--- a/httpie/manager/cli.py
+++ b/httpie/manager/cli.py
@@ -12,37 +12,6 @@
 ]
 
 COMMANDS = {
-    'plugins': {
-        'help': 'Manage HTTPie plugins.',
-        'install': [
-            'Install the given targets from PyPI '
-            'or from a local paths.',
-            {
-                'dest': 'targets',
-                'nargs': '+',
-                'help': 'targets to install'
-            }
-        ],
-        'upgrade': [
-            'Upgrade the given plugins',
-            {
-                'dest': 'targets',
-                'nargs': '+',
-                'help': 'targets to upgrade'
-            }
-        ],
-        'uninstall': [
-            'Uninstall the given HTTPie plugins.',
-            {
-                'dest': 'targets',
-                'nargs': '+',
-                'help': 'targets to install'
-            }
-        ],
-        'list': [
-            'List all installed HTTPie plugins.'
-        ],
-    },
     'cli': {
         'help': 'Manage HTTPie for Terminal',
         'export-args': [
@@ -82,6 +51,39 @@
 }
 
 
+COMMANDS['plugins'] = COMMANDS['cli']['plugins'] = {
+    'help': 'Manage HTTPie plugins.',
+    'install': [
+        'Install the given targets from PyPI '
+        'or from a local paths.',
+        {
+            'dest': 'targets',
+            'nargs': '+',
+            'help': 'targets to install'
+        }
+    ],
+    'upgrade': [
+        'Upgrade the given plugins',
+        {
+            'dest': 'targets',
+            'nargs': '+',
+            'help': 'targets to upgrade'
+        }
+    ],
+    'uninstall': [
+        'Uninstall the given HTTPie plugins.',
+        {
+            'dest': 'targets',
+            'nargs': '+',
+            'help': 'targets to install'
+        }
+    ],
+    'list': [
+        'List all installed HTTPie plugins.'
+    ],
+}
+
+
 def missing_subcommand(*args) -> str:
     base = COMMANDS
     for arg in args:
diff --git a/httpie/manager/core.py b/httpie/manager/core.py
index 1289fef1a4..0d669ecc05 100644
--- a/httpie/manager/core.py
+++ b/httpie/manager/core.py
@@ -2,7 +2,6 @@
 from typing import Optional
 
 from httpie.context import Environment
-from httpie.manager.plugins import PluginInstaller
 from httpie.status import ExitStatus
 from httpie.manager.cli import missing_subcommand, parser
 from httpie.manager.tasks import CLI_TASKS
@@ -36,8 +35,7 @@ def program(args: argparse.Namespace, env: Environment) -> ExitStatus:
         parser.error(MSG_NAKED_INVOCATION)
 
     if args.action == 'plugins':
-        plugins = PluginInstaller(env, debug=args.debug)
-        return plugins.run(args.plugins_action, args)
+        return dispatch_cli_task(env, args.action, args)
     elif args.action == 'cli':
         return dispatch_cli_task(env, args.cli_action, args)
 
diff --git a/httpie/manager/tasks/__init__.py b/httpie/manager/tasks/__init__.py
new file mode 100644
index 0000000000..9c591a24fa
--- /dev/null
+++ b/httpie/manager/tasks/__init__.py
@@ -0,0 +1,9 @@
+from httpie.manager.tasks.sessions import cli_sessions
+from httpie.manager.tasks.export_args import cli_export_args
+from httpie.manager.tasks.plugins import cli_plugins
+
+CLI_TASKS = {
+    'sessions': cli_sessions,
+    'export-args': cli_export_args,
+    'plugins': cli_plugins,
+}
diff --git a/httpie/manager/tasks/export_args.py b/httpie/manager/tasks/export_args.py
new file mode 100644
index 0000000000..9a684a4913
--- /dev/null
+++ b/httpie/manager/tasks/export_args.py
@@ -0,0 +1,27 @@
+import argparse
+import json
+
+from httpie.cli.definition import options
+from httpie.cli.options import to_data
+from httpie.output.writer import write_raw_data
+from httpie.status import ExitStatus
+from httpie.context import Environment
+
+
+FORMAT_TO_CONTENT_TYPE = {
+    'json': 'application/json'
+}
+
+
+def cli_export_args(env: Environment, args: argparse.Namespace) -> ExitStatus:
+    if args.format == 'json':
+        data = json.dumps(to_data(options))
+    else:
+        raise NotImplementedError(f'Unexpected format value: {args.format}')
+
+    write_raw_data(
+        env,
+        data,
+        stream_kwargs={'mime_overwrite': FORMAT_TO_CONTENT_TYPE[args.format]},
+    )
+    return ExitStatus.SUCCESS
diff --git a/httpie/manager/plugins.py b/httpie/manager/tasks/plugins.py
similarity index 94%
rename from httpie/manager/plugins.py
rename to httpie/manager/tasks/plugins.py
index 899e992563..e6b1ee2389 100644
--- a/httpie/manager/plugins.py
+++ b/httpie/manager/tasks/plugins.py
@@ -1,18 +1,18 @@
 import argparse
 import os
+import re
+import shutil
 import subprocess
 import sys
 import textwrap
-import re
-import shutil
 from collections import defaultdict
 from contextlib import suppress
 from pathlib import Path
-from typing import Tuple, Optional, List
+from typing import List, Optional, Tuple
 
-from httpie.manager.cli import parser, missing_subcommand
-from httpie.compat import importlib_metadata, get_dist_name
+from httpie.compat import get_dist_name, importlib_metadata
 from httpie.context import Environment
+from httpie.manager.cli import missing_subcommand, parser
 from httpie.status import ExitStatus
 from httpie.utils import as_site
 
@@ -248,3 +248,14 @@ def run(
                 status = self.list()
 
         return status or ExitStatus.SUCCESS
+
+
+def cli_plugins(env: Environment, args: argparse.Namespace) -> ExitStatus:
+    plugins = PluginInstaller(env, debug=args.debug)
+
+    try:
+        action = args.cli_plugins_action
+    except AttributeError:
+        action = args.plugins_action
+
+    return plugins.run(action, args)
diff --git a/httpie/manager/tasks.py b/httpie/manager/tasks/sessions.py
similarity index 78%
rename from httpie/manager/tasks.py
rename to httpie/manager/tasks/sessions.py
index 5b726a9bb5..10866cae68 100644
--- a/httpie/manager/tasks.py
+++ b/httpie/manager/tasks/sessions.py
@@ -1,5 +1,5 @@
 import argparse
-from typing import TypeVar, Callable, Tuple
+from typing import Tuple
 
 from httpie.sessions import SESSIONS_DIR_NAME, get_httpie_session
 from httpie.status import ExitStatus
@@ -7,19 +7,7 @@
 from httpie.legacy import cookie_format as legacy_cookies
 from httpie.manager.cli import missing_subcommand, parser
 
-T = TypeVar('T')
 
-CLI_TASKS = {}
-
-
-def task(name: str) -> Callable[[T], T]:
-    def wrapper(func: T) -> T:
-        CLI_TASKS[name] = func
-        return func
-    return wrapper
-
-
-@task('sessions')
 def cli_sessions(env: Environment, args: argparse.Namespace) -> ExitStatus:
     action = args.cli_sessions_action
     if action is None:
@@ -114,28 +102,3 @@ def cli_upgrade_all_sessions(env: Environment, args: argparse.Namespace) -> Exit
                 session_name=session_name
             )
     return status
-
-
-FORMAT_TO_CONTENT_TYPE = {
-    'json': 'application/json'
-}
-
-
-@task('export-args')
-def cli_export(env: Environment, args: argparse.Namespace) -> ExitStatus:
-    import json
-    from httpie.cli.definition import options
-    from httpie.cli.options import to_data
-    from httpie.output.writer import write_raw_data
-
-    if args.format == 'json':
-        data = json.dumps(to_data(options))
-    else:
-        raise NotImplementedError(f'Unexpected format value: {args.format}')
-
-    write_raw_data(
-        env,
-        data,
-        stream_kwargs={'mime_overwrite': FORMAT_TO_CONTENT_TYPE[args.format]},
-    )
-    return ExitStatus.SUCCESS
diff --git a/tests/test_plugins_cli.py b/tests/test_plugins_cli.py
index 70cecb1fb7..7be110de3b 100644
--- a/tests/test_plugins_cli.py
+++ b/tests/test_plugins_cli.py
@@ -5,8 +5,9 @@
 
 
 @pytest.mark.requires_installation
-def test_plugins_installation(httpie_plugins_success, interface, dummy_plugin):
-    lines = httpie_plugins_success('install', dummy_plugin.path)
+@pytest.mark.parametrize('cli_mode', [True, False])
+def test_plugins_installation(httpie_plugins_success, interface, dummy_plugin, cli_mode):
+    lines = httpie_plugins_success('install', dummy_plugin.path, cli_mode=cli_mode)
     assert lines[0].startswith(
         f'Installing {dummy_plugin.path}'
     )
@@ -28,8 +29,9 @@ def test_plugin_installation_with_custom_config(httpie_plugins_success, interfac
 
 
 @pytest.mark.requires_installation
-def test_plugins_listing(httpie_plugins_success, interface, dummy_plugin):
-    httpie_plugins_success('install', dummy_plugin.path)
+@pytest.mark.parametrize('cli_mode', [True, False])
+def test_plugins_listing(httpie_plugins_success, interface, dummy_plugin, cli_mode):
+    httpie_plugins_success('install', dummy_plugin.path, cli_mode=cli_mode)
     data = parse_listing(httpie_plugins_success('list'))
 
     assert data == {
@@ -50,9 +52,10 @@ def test_plugins_listing_multiple(interface, httpie_plugins_success, dummy_plugi
 
 
 @pytest.mark.requires_installation
-def test_plugins_uninstall(interface, httpie_plugins_success, dummy_plugin):
-    httpie_plugins_success('install', dummy_plugin.path)
-    httpie_plugins_success('uninstall', dummy_plugin.name)
+@pytest.mark.parametrize('cli_mode', [True, False])
+def test_plugins_uninstall(interface, httpie_plugins_success, dummy_plugin, cli_mode):
+    httpie_plugins_success('install', dummy_plugin.path, cli_mode=cli_mode)
+    httpie_plugins_success('uninstall', dummy_plugin.name, cli_mode=cli_mode)
     assert not interface.is_installed(dummy_plugin.name)
 
 
diff --git a/tests/utils/plugins_cli.py b/tests/utils/plugins_cli.py
index a750e664b1..39b515d4ae 100644
--- a/tests/utils/plugins_cli.py
+++ b/tests/utils/plugins_cli.py
@@ -208,12 +208,17 @@ def httpie_plugins(interface):
     from tests.utils import httpie
     from httpie.plugins.registry import plugin_manager
 
-    def runner(*args):
+    def runner(*args, cli_mode: bool = True):
+        args = list(args)
+        if cli_mode:
+            args.insert(0, 'cli')
+        args.insert(cli_mode, 'plugins')
+
         # Prevent installed plugins from showing up.
         original_plugins = plugin_manager.copy()
         clean_sys_path = set(sys.path).difference(site.getsitepackages())
         with patch('sys.path', list(clean_sys_path)):
-            response = httpie('plugins', *args, env=interface.environment)
+            response = httpie(*args, env=interface.environment)
         plugin_manager.clear()
         plugin_manager.extend(original_plugins)
         return response
@@ -223,8 +228,8 @@ def runner(*args):
 
 @pytest.fixture
 def httpie_plugins_success(httpie_plugins):
-    def runner(*args):
-        response = httpie_plugins(*args)
+    def runner(*args, cli_mode: bool = True):
+        response = httpie_plugins(*args, cli_mode=True)
         assert response.exit_status == ExitStatus.SUCCESS
         return response.splitlines()
     return runner

This PR moves `httpie plugins` command from the top level namespace to `cli` namespace, as `httpie cli plugins`. The `httpie plugins` is just a basic alias to the `httpie cli plugins` which we discourage and don't mention in our documentation. 

Also as discussed, the `httpie.manager.tasks` is now a package that contains each task as a submodule.