Getting started#

Installation#

conda-subchannel is a conda subcommand plugin with no extra dependencies. As such you need to install it in your base environment:

$ conda install -n base -c conda-forge conda-subchannel

Once the installation has succeeded, this command should run without errors:

$ conda subchannel --help

Your first subchannel#

We call subchannel to a subset of an already existing conda channel.

Let’s say we start with conda-forge but we are not interested in keeping EOL’d versions of Python around. We could fetch the repodata.json files and remove any python record with version 3.7 and below.

The resulting repodata.json will not have these records present and as a result the solver will never see them or load them! All we have to do is put our new repodata.json in a location that looks like a conda channel and point our conda client there!

This works wonderfully for dry-run solves, but downloads won’t work yet. The problem is that conda clients always assumed that the downloadable artifacts (e.g. python-3.9.3-h123abc_0.conda) were available next to the repodata.json. In your new location, these files won’t be found unless you also copy them over… and that’s expensive to store and serve!

Fortunately, CEP-15 introduced a new metadata field in the repodata.json file, base_url that tells the conda client to find artifacts in that location instead of using the repodata.json location. So now you just need to set base_url to the conda-forge location and you are done!

You can do all those steps manually, but conda subchannel is here to help! To summarize, this is what we will do for you:

  1. Fetch the remote channel and create a local copy.

  2. Edit the repodata.json file(s) and choose which records will be kept in the new subchannel according to your provided filter conditions.

  3. Add base_url pointing to the original remote location.

  4. Publish the repodata.json file(s) in a channel-like directory structure.

Create your local channel#

Let’s say we want to make sure that our team only uses python=3.10 on linux-64. We can create a subchannel that removes any versions that don’t match that specification. If we start with conda-forge:

$ conda subchannel -c conda-forge --subdir linux-64 --keep-tree python=3.10

You should see this output:

Syncing source channel: done
 - conda-forge linux-64
 - conda-forge noarch
Filtering package records: done
 - Reduced from 669094 to 1100 records
Writing output to subchannel: done

The files will be available under ./subchannel:

$ tree -sh ./subchannel
./subchannel
├── [ 169]  index.md
├── [ 192]  linux-64
│   ├── [ 736]  index.md
│   ├── [591K]  repodata.json
│   ├── [ 81K]  repodata.json.bz2
│   └── [ 82K]  repodata.json.zst
└── [ 192]  noarch
    ├── [ 731]  index.md
    ├── [ 10K]  repodata.json
    ├── [2.2K]  repodata.json.bz2
    └── [1.9K]  repodata.json.zst

Use it with conda#

You can now use it locally to make sure you can only install python=3.10.

This works:

$ conda create -dnx --override-channel -c ./subchannel python=3.10 --platform=linux-64
Channels:
 - ./subchannel
Platform: linux-64
Collecting package metadata (repodata.json): done
Solving environment: done

## Package Plan ##

  environment location: ...

  added / updated specs:
    - python=3.10


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    _libgcc_mutex-0.1          |      conda_forge           3 KB  ./subchannel
    _openmp_mutex-4.5          |            2_gnu          23 KB  ./subchannel
    bzip2-1.0.8                |       hd590300_5         248 KB  ./subchannel
    ca-certificates-2024.2.2   |       hbcca054_0         152 KB  ./subchannel
    ld_impl_linux-64-2.40      |       hf3520f5_1         691 KB  ./subchannel
    libffi-3.4.2               |       h7f98852_5          57 KB  ./subchannel
    libgcc-ng-13.2.0           |       h77fa898_7         758 KB  ./subchannel
    libgomp-13.2.0             |       h77fa898_7         412 KB  ./subchannel
    libnsl-2.0.1               |       hd590300_0          33 KB  ./subchannel
    libsqlite-3.45.3           |       h2797004_0         840 KB  ./subchannel
    libuuid-2.38.1             |       h0b41bf4_0          33 KB  ./subchannel
    libxcrypt-4.4.36           |       hd590300_1          98 KB  ./subchannel
    libzlib-1.2.13             |       h4ab18f5_6          60 KB  ./subchannel
    ncurses-6.5                |       h59595ed_0         867 KB  ./subchannel
    openssl-3.3.0              |       h4ab18f5_3         2.8 MB  ./subchannel
    python-3.10.14             |hd12c33a_0_cpython        24.3 MB  ./subchannel
    readline-8.2               |       h8228510_1         275 KB  ./subchannel
    tk-8.6.13                  |noxft_h4845f30_101         3.2 MB  ./subchannel
    tzdata-2024a               |       h0c530f3_0         117 KB  ./subchannel
    xz-5.2.6                   |       h166bdaf_0         409 KB  ./subchannel
    ------------------------------------------------------------
                                           Total:        35.2 MB

The following NEW packages will be INSTALLED:

  _libgcc_mutex      subchannel/linux-64::_libgcc_mutex-0.1-conda_forge 
  _openmp_mutex      subchannel/linux-64::_openmp_mutex-4.5-2_gnu 
  bzip2              subchannel/linux-64::bzip2-1.0.8-hd590300_5 
  ca-certificates    subchannel/linux-64::ca-certificates-2024.2.2-hbcca054_0 
  ld_impl_linux-64   subchannel/linux-64::ld_impl_linux-64-2.40-hf3520f5_1 
  libffi             subchannel/linux-64::libffi-3.4.2-h7f98852_5 
  libgcc-ng          subchannel/linux-64::libgcc-ng-13.2.0-h77fa898_7 
  libgomp            subchannel/linux-64::libgomp-13.2.0-h77fa898_7 
  libnsl             subchannel/linux-64::libnsl-2.0.1-hd590300_0 
  libsqlite          subchannel/linux-64::libsqlite-3.45.3-h2797004_0 
  libuuid            subchannel/linux-64::libuuid-2.38.1-h0b41bf4_0 
  libxcrypt          subchannel/linux-64::libxcrypt-4.4.36-hd590300_1 
  libzlib            subchannel/linux-64::libzlib-1.2.13-h4ab18f5_6 
  ncurses            subchannel/linux-64::ncurses-6.5-h59595ed_0 
  openssl            subchannel/linux-64::openssl-3.3.0-h4ab18f5_3 
  python             subchannel/linux-64::python-3.10.14-hd12c33a_0_cpython 
  readline           subchannel/linux-64::readline-8.2-h8228510_1 
  tk                 subchannel/linux-64::tk-8.6.13-noxft_h4845f30_101 
  tzdata             subchannel/noarch::tzdata-2024a-h0c530f3_0 
  xz                 subchannel/linux-64::xz-5.2.6-h166bdaf_0 



DryRunExit: Dry run. Exiting.

These do not, as expected. python=3.9 is not available because we filtered it out:

$ conda create -dnx --override-channel -c ./subchannel python=3.9 --platform=linux-64
Channels:
 - ./subchannel
Platform: linux-64
Collecting package metadata (repodata.json): done
Solving environment: failed

PackagesNotFoundError: The following packages are not available from current channels:

  - python=3.9*

Current channels:

  - ./subchannel

To search for alternate channels that may provide the conda package you're
looking for, navigate to

    https://anaconda.org

python=3.10 is not available on osx-64, only linux-64:

$ conda create -dnx --override-channel -c ./subchannel python=3.10 --platform=osx-64  
Channels:
 - ./subchannel
Platform: osx-64
Collecting package metadata (repodata.json): done
Solving environment: failed

PackagesNotFoundError: The following packages are not available from current channels:

  - python=3.10*

Current channels:

  - ./subchannel

To search for alternate channels that may provide the conda package you're
looking for, navigate to

    https://anaconda.org

and use the search bar at the top of the page.

Check how to work with the other filters in Usage.

Publish it#

You can push this directory structure to any location online, including:

  • Static website providers like Github Pages, Netlify or Vercel

  • Any HTTP(S) or FTP servers you control

  • Network locations that can be mounted on your filesystem

  • S3 buckets

Just remember to to maintain the directory tree intact, namely:

  1. Make sure your channel is served under a directory, not the root of the server. In other words, you want them available at https://my-channels.org/my-channel/noarch/repodata.json, and not https://my-channels.org/noarch/repodata.json. Otherwise conda clients might fail to assign a name to the channel.

  2. You always need noarch/repodata.json even if empty.

  3. In practice, a platform specific subdir will also need to be there (e.g. linux-64/repodata.json).

Tip

We also provide a Github Actions action you can use to both run conda subchannel and then publish it to the Github Pages deployment in the repository