Documentation Index Fetch the complete documentation index at: https://mintlify.com/conda/conda/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Plugin types are dataclass definitions that specify the structure and requirements for each plugin hook. Every plugin hook returns an iterable of these typed objects.
All plugin types inherit from CondaPlugin base class which provides name validation and normalization.
Base Classes
CondaPlugin
Base class for all conda plugins.
Fields:
Field Type Description namestrUser-facing plugin name (automatically lowercased and stripped)
Usage:
from conda.plugins.types import CondaPlugin
@dataclass
class MyPlugin ( CondaPlugin ):
name: str
# additional fields...
Plugin names are automatically normalized to lowercase and stripped of whitespace. Invalid names raise PluginError.
Plugin Type Definitions
CondaSubcommand
Defines a conda subcommand plugin.
Fields:
Field Type Required Description namestrYes Subcommand name (e.g., conda my-subcommand) summarystrYes Short description shown in conda --help actionCallableYes Function executed when subcommand is invoked configure_parserCallableNo Function to configure argparse parser
Action Signature:
def action ( args : Namespace | tuple[ str ]) -> int | None :
# Command implementation
return 0 # exit code
Parser Configuration Signature:
def configure_parser ( parser : ArgumentParser) -> None :
parser.add_argument( '--my-option' , help = 'My option' )
Example:
from conda import plugins
from argparse import ArgumentParser
def my_command ( args ):
print ( f "Running with option: { args.my_option } " )
return 0
def configure_my_parser ( parser : ArgumentParser):
parser.add_argument(
'--my-option' ,
default = 'default' ,
help = 'An example option'
)
@plugins.hookimpl
def conda_subcommands ():
yield plugins.types.CondaSubcommand(
name = "my-command" ,
summary = "An example subcommand" ,
action = my_command,
configure_parser = configure_my_parser,
)
CondaVirtualPackage
Defines a virtual package representing system capabilities.
Fields:
Field Type Required Description namestrYes Virtual package name (e.g., my_custom_os) version`str None Callable` Yes Package version or callable returning version build`str None Callable` Yes Build string or callable returning build override_entity`“version" "build” None` No Which field can be overridden via environment variable empty_override`None NULL` No Value when override is empty string (default: NULL) version_validationCallableNo Optional version validation function
Example (Static Values):
from conda import plugins
@plugins.hookimpl
def conda_virtual_packages ():
yield plugins.types.CondaVirtualPackage(
name = "my_os" ,
version = "10.5.0" ,
build = "x86_64" ,
)
Example (Dynamic Values):
from conda import plugins
import platform
def get_os_version ():
return platform.release()
def get_arch ():
return platform.machine()
@plugins.hookimpl
def conda_virtual_packages ():
yield plugins.types.CondaVirtualPackage(
name = "my_os" ,
version = get_os_version,
build = get_arch,
)
Example (With Override):
from conda import plugins
@plugins.hookimpl
def conda_virtual_packages ():
yield plugins.types.CondaVirtualPackage(
name = "cuda" ,
version = "11.8" ,
build = "0" ,
override_entity = "version" , # Allow CONDA_OVERRIDE_CUDA env var
)
Environment Variable Overrides
When override_entity is set, users can override the value using:
Environment variable: CONDA_OVERRIDE_{name} (uppercase)
Config setting: context.override_virtual_packages[name]
Example: CONDA_OVERRIDE_CUDA=12.0 conda install ...
CondaSolver
Defines a custom solver implementation.
Fields:
Field Type Required Description namestrYes Solver name (e.g., custom-solver) backendtype[Solver]Yes Solver class (must inherit from conda.core.solve.Solver)
Example:
from conda import plugins
from conda.core.solve import Solver
class MySolver ( Solver ):
def solve_final_state ( self , * args , ** kwargs ):
# Custom solving logic
return super ().solve_final_state( * args, ** kwargs)
@plugins.hookimpl
def conda_solvers ():
yield plugins.types.CondaSolver(
name = "my-solver" ,
backend = MySolver,
)
CondaPreCommand
Defines a pre-command hook.
Fields:
Field Type Required Description namestrYes Pre-command identifier actionCallable[[str], None]Yes Function to execute before commands run_forset[str]Yes Set of command names to trigger on
Example:
from conda import plugins
def validate_environment ( command : str ):
print ( f "Running pre-command validation for: { command } " )
# Perform validation...
@plugins.hookimpl
def conda_pre_commands ():
yield plugins.types.CondaPreCommand(
name = "env-validator" ,
action = validate_environment,
run_for = { "install" , "update" , "create" },
)
CondaPostCommand
Defines a post-command hook.
Fields:
Field Type Required Description namestrYes Post-command identifier actionCallable[[str], None]Yes Function to execute after commands run_forset[str]Yes Set of command names to trigger on
Example:
from conda import plugins
def report_metrics ( command : str ):
print ( f "Reporting metrics for: { command } " )
# Send metrics...
@plugins.hookimpl
def conda_post_commands ():
yield plugins.types.CondaPostCommand(
name = "metrics-reporter" ,
action = report_metrics,
run_for = { "install" , "remove" },
)
CondaAuthHandler
Defines a custom authentication handler.
Fields:
Field Type Required Description namestrYes Auth handler identifier handlertype[ChannelAuthBase]Yes Auth handler class (must inherit from ChannelAuthBase)
Example:
from conda import plugins
from conda.plugins.types import ChannelAuthBase
class TokenAuth ( ChannelAuthBase ):
def __init__ ( self , channel_name : str , token : str ):
super (). __init__ (channel_name)
self .token = token
def __call__ ( self , request ):
request.headers[ "Authorization" ] = f "Bearer { self .token } "
return request
@plugins.hookimpl
def conda_auth_handlers ():
yield plugins.types.CondaAuthHandler(
name = "token-auth" ,
handler = TokenAuth,
)
CondaHealthCheck
Defines a health check for conda doctor.
Fields:
Field Type Required Description namestrYes Health check identifier actionCallable[[str, bool], None]Yes Check function (receives prefix and verbose flag) fixerCallableNo Optional fix function summarystrNo Short description of the check fixstrNo Short description of the fix
Fixer Signature:
def fixer ( prefix : str , args : Namespace, confirm : ConfirmCallback) -> int :
# Fix implementation
return 0 # exit code
Example:
from conda import plugins
from conda.plugins.types import ConfirmCallback
from argparse import Namespace
def check_permissions ( prefix : str , verbose : bool ):
if verbose:
print ( f "Checking permissions in { prefix } " )
# Check logic...
def fix_permissions ( prefix : str , args : Namespace, confirm : ConfirmCallback) -> int :
issues = [] # Find issues...
if not issues:
print ( "No permission issues found" )
return 0
confirm( f "Fix { len (issues) } permission issues?" )
# Perform fixes...
return 0
@plugins.hookimpl
def conda_health_checks ():
yield plugins.types.CondaHealthCheck(
name = "permissions" ,
action = check_permissions,
fixer = fix_permissions,
summary = "Check file permissions" ,
fix = "Fix incorrect permissions" ,
)
CondaPreSolve
Defines a pre-solve hook.
Fields:
Field Type Required Description namestrYes Pre-solve identifier actionCallableYes Function called before solving
Action Signature:
def action (
specs_to_add : frozenset[MatchSpec],
specs_to_remove : frozenset[MatchSpec]
) -> None :
pass
Example:
from conda import plugins
from conda.models.match_spec import MatchSpec
def log_solve_input (
specs_to_add : frozenset[MatchSpec],
specs_to_remove : frozenset[MatchSpec]
):
print ( f "Solving with { len (specs_to_add) } additions" )
print ( f "Removing { len (specs_to_remove) } packages" )
@plugins.hookimpl
def conda_pre_solves ():
yield plugins.types.CondaPreSolve(
name = "solve-logger" ,
action = log_solve_input,
)
CondaPostSolve
Defines a post-solve hook.
Fields:
Field Type Required Description namestrYes Post-solve identifier actionCallableYes Function called after solving
Action Signature:
def action (
repodata_fn : str ,
unlink_precs : tuple[PackageRecord, ... ],
link_precs : tuple[PackageRecord, ... ]
) -> None :
pass
Example:
from conda import plugins
from conda.models.records import PackageRecord
def analyze_solve_result (
repodata_fn : str ,
unlink_precs : tuple[PackageRecord, ... ],
link_precs : tuple[PackageRecord, ... ]
):
print ( f "Repodata: { repodata_fn } " )
print ( f "Packages to unlink: { len (unlink_precs) } " )
print ( f "Packages to link: { len (link_precs) } " )
@plugins.hookimpl
def conda_post_solves ():
yield plugins.types.CondaPostSolve(
name = "solve-analyzer" ,
action = analyze_solve_result,
)
CondaSetting
Defines a custom configuration setting.
Fields:
Field Type Required Description namestrYes Setting name descriptionstrYes User-facing description parameterParameterYes Parameter definition (e.g., PrimitiveParameter) aliasestuple[str, ...]No Alternative names for the setting
Example:
from conda import plugins
from conda.common.configuration import PrimitiveParameter, SequenceParameter
@plugins.hookimpl
def conda_settings ():
# String setting
yield plugins.types.CondaSetting(
name = "my_api_key" ,
description = "API key for my service" ,
parameter = PrimitiveParameter( "" , element_type = str ),
aliases = ( "my_key" ,),
)
# List setting
yield plugins.types.CondaSetting(
name = "my_servers" ,
description = "List of server URLs" ,
parameter = SequenceParameter([], element_type = str ),
)
CondaReporterBackend
Defines a custom output reporter.
Fields:
Field Type Required Description namestrYes Reporter backend name descriptionstrYes Short description renderertype[ReporterRendererBase]Yes Renderer implementation
Example:
from conda import plugins
from conda.plugins.types import (
ReporterRendererBase,
ProgressBarBase,
SpinnerBase,
)
class MyRenderer ( ReporterRendererBase ):
def detail_view ( self , data , ** kwargs ):
return str (data)
def envs_list ( self , data , ** kwargs ):
return " \n " .join(data)
def progress_bar ( self , description , ** kwargs ):
return MyProgressBar(description)
def spinner ( self , message , failed_message ):
return MySpinner(message, failed_message)
def prompt ( self , message = "Proceed" , choices = ( "yes" , "no" ), default = "yes" ):
return input ( f " { message } [ { '/' .join(choices) } ]? " )
class MyProgressBar ( ProgressBarBase ):
def update_to ( self , fraction ):
pass
def refresh ( self ):
pass
def close ( self ):
pass
class MySpinner ( SpinnerBase ):
def __enter__ ( self ):
return self
def __exit__ ( self , exc_type , exc_val , exc_tb ):
pass
@plugins.hookimpl
def conda_reporter_backends ():
yield plugins.types.CondaReporterBackend(
name = "my-reporter" ,
description = "Custom reporter implementation" ,
renderer = MyRenderer,
)
Defines a custom HTTP request header.
Fields:
Field Type Required Description namestrYes HTTP header name valuestrYes HTTP header value
Example:
from conda import plugins
@plugins.hookimpl
def conda_session_headers ( host : str ):
if host == "my-channel.com" :
yield plugins.types.CondaRequestHeader(
name = "X-API-Version" ,
value = "v2" ,
)
yield plugins.types.CondaRequestHeader(
name = "X-Client" ,
value = "conda-plugin" ,
)
CondaPreTransactionAction
Defines a pre-transaction action.
Fields:
Field Type Required Description namestrYes Action identifier actiontype[Action]Yes Action class (must inherit from conda.core.path_actions.Action)
Example:
from conda import plugins
from conda.core.path_actions import Action
class BackupAction ( Action ):
def verify ( self ):
self ._verified = True
def execute ( self ):
print ( f "Backing up { self .target_prefix } " )
# Backup logic...
def reverse ( self ):
print ( "Restoring from backup" )
# Restore logic...
def cleanup ( self ):
print ( "Cleaning up backup" )
@plugins.hookimpl
def conda_pre_transaction_actions ():
yield plugins.types.CondaPreTransactionAction(
name = "backup" ,
action = BackupAction,
)
CondaPostTransactionAction
Defines a post-transaction action.
Fields:
Field Type Required Description namestrYes Action identifier actiontype[Action]Yes Action class (must inherit from conda.core.path_actions.Action)
Example:
from conda import plugins
from conda.core.path_actions import Action
class NotifyAction ( Action ):
def verify ( self ):
self ._verified = True
def execute ( self ):
print ( "Sending notification..." )
# Notification logic...
def reverse ( self ):
pass # Nothing to reverse
def cleanup ( self ):
pass
@plugins.hookimpl
def conda_post_transaction_actions ():
yield plugins.types.CondaPostTransactionAction(
name = "notify" ,
action = NotifyAction,
)
CondaPrefixDataLoader
Defines a custom prefix data loader.
Fields:
Field Type Required Description namestrYes Loader identifier loaderCondaPrefixDataLoaderCallableYes Loader function
Loader Signature:
def loader (
prefix : PathType,
records : dict[ str , PrefixRecord]
) -> dict[ str , PrefixRecord]:
# Load and return new records
pass
Example:
from pathlib import Path
from conda import plugins
from conda.common.path import PathType
from conda.models.records import PrefixRecord
def load_npm_packages (
prefix : PathType,
records : dict[ str , PrefixRecord]
) -> dict[ str , PrefixRecord]:
npm_records = {}
node_modules = Path(prefix) / "node_modules"
if node_modules.exists():
for package_dir in node_modules.iterdir():
if package_dir.is_dir():
# Parse package.json and create PrefixRecord
npm_records[package_dir.name] = PrefixRecord(
name = package_dir.name,
version = "1.0.0" ,
build_number = 0 ,
build = "npm" ,
)
records.update(npm_records)
return npm_records
@plugins.hookimpl
def conda_prefix_data_loaders ():
yield plugins.types.CondaPrefixDataLoader(
name = "npm-loader" ,
loader = load_npm_packages,
)
CondaEnvironmentSpecifier
EXPERIMENTAL - This API may change in future releases.
Defines a custom environment specification format.
Fields:
Field Type Required Description namestrYes Specifier name environment_spectype[EnvironmentSpecBase]Yes Spec parser class
Example:
import json
from conda import plugins
from conda.plugins.types import EnvironmentSpecBase
from conda.env.env import Environment
class JsonSpec ( EnvironmentSpecBase ):
def __init__ ( self , filename : str ):
self .filename = filename
def can_handle ( self ) -> bool :
return self .filename.endswith( '.json' )
@ property
def env ( self ) -> Environment:
with open ( self .filename) as f:
data = json.load(f)
return Environment(
name = data[ 'name' ],
channels = data.get( 'channels' , []),
dependencies = data.get( 'dependencies' , []),
)
@plugins.hookimpl
def conda_environment_specifiers ():
yield plugins.types.CondaEnvironmentSpecifier(
name = "json" ,
environment_spec = JsonSpec,
)
CondaEnvironmentExporter
Defines a custom environment export format.
Fields:
Field Type Required Description namestrYes Exporter name aliasestuple[str, ...]Yes Format aliases (e.g., ("yaml", "yml")) default_filenamestuple[str, ...]Yes Default filenames (e.g., ("environment.yml",)) exportSinglePlatformEnvironmentExportNo* Single-platform export function multiplatform_exportMultiPlatformEnvironmentExportNo* Multi-platform export function
*Exactly one of export or multiplatform_export must be provided.
Export Signature:
def export ( env : Environment) -> str :
# Return serialized environment
pass
Example:
import json
from conda import plugins
from conda.models.environment import Environment
def export_json ( env : Environment) -> str :
data = {
"name" : env.name,
"channels" : env.channels,
"dependencies" : [ str (dep) for dep in env.dependencies],
}
return json.dumps(data, indent = 2 )
@plugins.hookimpl
def conda_environment_exporters ():
yield plugins.types.CondaEnvironmentExporter(
name = "environment-json" ,
aliases = ( "json" ,),
default_filenames = ( "environment.json" ,),
export = export_json,
)
Defines a custom package extractor.
Fields:
Field Type Required Description namestrYes Extractor name extensionslist[str]Yes Supported file extensions (e.g., [".conda", ".tar.bz2"]) extractPackageExtractYes Extraction function
Extract Signature:
def extract ( source_path : PathType, destination_directory : PathType) -> None :
# Extract package contents
pass
Example:
import tarfile
from conda import plugins
from conda.common.path import PathType
def extract_tar_xz ( source_path : PathType, destination_directory : PathType) -> None :
with tarfile.open(source_path, 'r:xz' ) as tar:
tar.extractall(destination_directory)
@plugins.hookimpl
def conda_package_extractors ():
yield plugins.types.CondaPackageExtractor(
name = "tar-xz" ,
extensions = [ ".tar.xz" ],
extract = extract_tar_xz,
)
Abstract Base Classes
ReporterRendererBase
Base class for custom reporter renderers.
Methods to Implement:
class MyRenderer ( ReporterRendererBase ):
def detail_view ( self , data : dict[ str , str | int | bool ], ** kwargs ) -> str :
"""Render tabular output."""
pass
def envs_list ( self , data : Iterable[ str ] | dict , ** kwargs ) -> str :
"""Render environment list."""
pass
def progress_bar ( self , description : str , ** kwargs ) -> ProgressBarBase:
"""Return progress bar instance."""
pass
def spinner ( self , message : str , failed_message : str ) -> SpinnerBase:
"""Return spinner instance."""
pass
def prompt ( self , message : str = "Proceed" , choices = ( "yes" , "no" ), default : str = "yes" ) -> str :
"""Prompt user for confirmation."""
pass
ProgressBarBase
Base class for progress bar implementations.
Methods to Implement:
class MyProgressBar ( ProgressBarBase ):
def update_to ( self , fraction : float ) -> None :
"""Update progress to fraction (0.0 to 1.0)."""
pass
def refresh ( self ) -> None :
"""Refresh the progress bar display."""
pass
def close ( self ) -> None :
"""Close and clean up the progress bar."""
pass
SpinnerBase
Base class for spinner implementations.
Methods to Implement:
class MySpinner ( SpinnerBase ):
def __enter__ ( self ):
"""Start the spinner."""
return self
def __exit__ ( self , exc_type , exc_val , exc_tb ):
"""Stop the spinner."""
pass
EnvironmentSpecBase
EXPERIMENTAL - This API may change in future releases.
Base class for environment specification parsers.
Class Attributes:
Attribute Type Description detection_supportedboolWhether auto-detection is enabled (default: True)
Methods to Implement:
class MySpec ( EnvironmentSpecBase ):
detection_supported = True
def can_handle ( self ) -> bool :
"""Determine if this spec can handle the file."""
pass
@ property
def env ( self ) -> Environment:
"""Parse and return the Environment object."""
pass
Type Aliases
Useful type aliases defined in the types module:
# Prefix data loader callable
CondaPrefixDataLoaderCallable = Callable[
[PathType, dict[ str , PrefixRecord]],
dict[ str , PrefixRecord],
]
# Package extraction callable
PackageExtract = Callable[
[PathType, PathType], # (source_path, destination_directory)
None ,
]
# Environment export callables
SinglePlatformEnvironmentExport = Callable[[Environment], str ]
MultiPlatformEnvironmentExport = Callable[[Iterable[Environment]], str ]
# Confirm callback for health check fixers
ConfirmCallback = Callable[[ str ], None ]
Plugin Overview Learn about the plugin system architecture
Hook Specifications Explore all available plugin hooks