$env(TCLLIBPATH) is a list of directories to add to $auto_path, which in turn is used by facilities such as package unknown to search for packages.

See Also

magic names


$env(TCLLIBPATH) is a Tcl list, not some platform-specific colon-separated or semi-colon separated format, of paths to prepend to $auto_path. Regardless of platform, each item in $env(TCLLIBPATH) should use / to delimit parts of a path.


set env(TCLLIBPATH) [list /opt/tcl/site-lib /users/pat/working]

$env(TCLLIBPATH) is often not set by Tcl, and is designed to be set on a case-by-case basis depending on the needs of the site or the individual user to provide Tcl with additional site-specific locations to search for packages, or to test a package without installing it.

Isues with mingw/msys2

jmn 2023

Mingw munges some things in the environment during process startup - before Tcl gets a chance to view or interpret it in another way.

For example a TCLLIBPATH value of C:/TCLPKGS may be converted to something like C;C:\Users\someone\somewhere\TCLPKGS (it is viewing this as two paths C and /TCLPKGS and calling cygpath -m on each)

This will also result in ::auto_path being messed up.

You can avoid this issue by setting an environment variable either permanently, or on the commandline in which tclsh is invoked. e.g


Note that whether you encounter this issue depends on which tcl shell you are running within the msys2/mingw shell(s)

The plain tcl 8.6x package runs as tcl_platform(platform) = unix and the munging doesn't occur.

If you use pacman to install others such as:

mingw-w64-ucrt-x86_64-tcl 8.6.12-2

mingw-w64-x86_64-tcl 8.6.12-2

These run as tcl_platform(platform) = windows

Also if you call your own e.g /c/tcl/bin/tclsh8.7 (or c:/tclbin/tclsh8.7) then it will run as platform windows and require the MSYS2_ENV_CONV_EXCL environment variable to be set.

Conversely - the base tcl at /usr/bin/tclsh (The one that is platform = unix above) will have problems with entries in your TCLX_X_TM_PATH environment variable.

This is not the environment variable being munged - but appears to be Tcl's tm.tcl script which, upon seeing platform 'unix' splits on : instead of ;

It is possible to work around this by adjusting tm.tcl to look for a match of MSYS* or MINGW* in tcl_platform(os) (or platform::generic result as below) and telling it to split on ; - but that isn't an official fix - so do your own reviews on whether there are other considerations.

Some platform::generic return examples are: mingw64-x86_64, mingw32-x86_64, msys-x86_64

Example: Personal site-lib directory

PT 2004-07-20:

I like to keep all my local packages separate from the ActiveTcl installation that I use as a base. So I install all additional packages to a site-lib directory and then set $env(TCLLIBPATH) to this directory path. With this in place package require XYZ searches ActiveTcl and my site-lib directory for the most recent version of XYZ.

Determining which directory to add to TCLLIBPATH

LV 2009-06-29:

I download a package onto my machine. The package has a README, a demo directory, a lib directory, etc. Within the lib directory I see 3 sub-directories, and within the sub-directories are the pkgIndex.tcl file, etc.

So the basic layout is:

Installation directory/

So, what path(s) go into TCLLIBPATH? the path to the lib/, or each of the individual packages?


PT: the lib directory.

LV PT, thank you for the answer. I tried using that, and ran into my long time nemesis - Windows folders with spaces in the names. So eventually, when I have time, I need to change to using file join to set $env(TCLLIBPATH) rather than just hard coding it, so that it has some chance of working.

Example: Windows with Git version 1.7.10-preview20120409


I ran git, then do 'cd' to be in HOME directory and then add file .bashrc with these lines:

$ cd
$ cat .bashrc
TCLLIBPATH=" . C:/Tcl/lib"

Then at the next start of git, you will be able to use library packages from external (to git) Tcl installation (for instance Activestate Tcl).

Space character seems to be required at the beginning of $env(TCLLIBPATH): you can try the following lines on command line to experience it

$ TCLLIBPATH=". C:/Tcl/lib"
$ tclsh
% package require Expect
can't find package Expect
% exit
$ TCLLIBPATH=" . C:/Tcl/lib "
$ tclsh
% package require Expect
% exit

PYK 2014-05-23: This statement about the space character doesn't sound plausible. Could someone confirm or deny ? APN Works for me without the space. At least for 8.6.0.

DKF: It's a Tcl list. That should tell you exactly how to make things work, and should also indicate that leading and trailing whitespace will be ignored.

JMN 2023 - only a bit over 10years since LGT had this problem - I can confirm the effect with the space is real (testing with MingW bash which is I believe comparable to the Git bash they were using)

The leading space seems to be another way to prevent msys/mingw etc from munging the environment variable - but I wouldn't rely on it.

Setting MSYS2_ENV_CONV_EXCL=TCLLIBPATH is probably more robust (I don't think this option existed back when LGT posted this issue)

Bad interaction with Tclkit

AMG: I'm having serious trouble with TCLLIBPATH being ignored by Tclkit. Does anyone else have this issue?

APN I believe this is by design. Tclkits are intended to work without being affected by the host environment where the user may have other Tcl distributions installed.

AMG: An override would be most welcome. I'm trying to use my own bundled tclkit to run the tcllib and critcl build/install scripts in an automated overarching build script for my application, and I need to not rely on the system tclsh and Tcl libraries which may not exist. Yet, I'm also not bundling tcllib inside my bootstrap tclkit because that's a chicken-and-egg situation. The final tclkit does end up containing pieces of tcllib and packages built with the aid of critcl, but I obviously can't use it in the process of building itself. Right now, my solution is to patch critcl's build.tcl between unpacking and running it, adding a line to point auto_path to my libraries. Naturally, I'd prefer to avoid the maintenance burden imposed by digging into critcl internals, but I see no alternative at this time.