Author image Neil Bowers
and 1 contributors


PAUSE::Permissions - interface to PAUSE's module permissions file (06perms.txt)


  use PAUSE::Permissions;
  my $pp = PAUSE::Permissions->new;
  my $mp = $pp->module_permissions('HTTP::Client');
  my $owner    = $mp->owner;
  my @comaints = $mp->co_maintainers;


PAUSE::Permissions provides an interface to the 06perms.txt file produced by the Perl Authors Upload Server (PAUSE). The file records who has what permissions for every module on CPAN. The format and interpretation of this file are covered in "The 06perms.txt file" below.

By default, the module will mirror 06perms.txt from CPAN, using HTTP::Tiny to request it and store it locally. By default it will get the file from, but you can pass an alternate URI to the constructor:

  $perms_uri = "http://$CPAN_MIRROR/modules/06perms.txt";
  $pp = PAUSE::Permissions->new(uri => $perms_uri);

If you've already got a copy lying around, you can tell the module to use that:

  $pp = PAUSE::Permissions->new( filename => '/tmp/06perms.txt' );

Having created an instance of PAUSE::Permissions, you can then call the module_permissions method to get the permissions for a particular module. The SYNOPSIS gives the basic usage.


There are only two methods you need to know: the constructor (new) and module_permissions().


The constructor takes a hash of options:

  • filename: the path to a local copy of 06perms.txt. The constructor will die() if the file doesn't exist, or isn't readable. If you don't provide this parameter, then we'll try and get 06perms.txt from the uri parameter.

  • uri: the URI for 06perms.txt; defaults to

  • cachedir: if we're getting 06perms.txt from CPAN, then this is the directory where we'll cache the file locally. By default we call tmpdir() from File::Spec, and append PAUSE-Permissions.

So you might use the following, to get 06perms.txt from your 'local' CPAN mirror and store it somewhere of your choosing:

  $pp = PAUSE::Permissions->new(
                uri     => '',
                cachdir => '/tmp/pause',


The module_permissions method takes a single module name, and returns an instance of PAUSE::Permissions::Module:

  $mp = $pp->module_permissions( $module_name );

Refer to the documentation for PAUSE::Permissions::Module, but the key methods are:

  • owner() returns the PAUSE id of the owner (see "The 06perms.txt file" below), or undef if there isn't a defined owner.

  • co_maintainers() returns a list of PAUSE ids, or an empty list if the module has no co-maintainers.

It returns undef if the module wasn't found in the permissions list.

The 06perms.txt file

You can find the file on CPAN:

As of October 2012 this file is 8.4M in size.

The file starts with a header, followed by one blank line, then the body. The body contains one line per module per user:


Each line has three values, separated by commas:

  • The name of a module.

  • A PAUSE user id, which by convention is always given in upper case.

  • A single character that specifies what permissions the user has with respect to the module. See below.

Note that this file lists modules, not distributions. Every module in a CPAN distribution will be listed in this file. Modules are listed in alphabetical order, and for a given module, the PAUSE ids are listed in alphabetical order.

There are three characters that can appear in the permissions column:

  • 'm' identifies the user as the registered maintainer of the module. A module can only ever have zero or one user listed with the 'm' permission. For more details on registering a module, see 04pause.html.

  • 'f' identifies the user as the first person to upload the module to CPAN. You don't have to register a module before uploading it, and ownership in this case is first-come-first-served. A module can only ever have zero or one user listed with the 'f' permission.

  • 'c' identifies the user as a co-maintainer of the module. A module can have any number of co-maintainers.

If you first upload a module, you'll get an 'f' against you in the file. If you subsequently register the module, you'll get an 'm' against you. Internally PAUSE will have you recorded with both an 'm' and an 'f', but 06perms.txt only lists the highest precedence permission for each user.

What do the permissions mean?

  • Various places refer to the 'owner' of the module. This will be either the 'm' or 'f' permission, with 'm' taking precedence. If a module has both an 'm' and an 'f' user listed, then the 'm' user is considered the owner, and the 'f' user isn't. If a module has a user with 'f' listed, but no 'm', then the 'f' user is considered the owner.

  • If a module is listed in 06perms.txt, then only the people listed (m, f, or c) are allowed to upload (new) versions of the module. If anyone else uploads a version of the module, then the offending distribution will not be indexed: it will appear in the uploader's directory on CPAN, but won't be indexed under the module.

  • Only the owner for a module can grant co-maintainer status for a module. I.e. if you have the 'm' permission, you can always do it. If you have the 'f' permission, you can only do it if no-one else has the 'm' permission. You can grant co-maintainer status using the PAUSE web interface.

  • Regardless of your permissions, you can only remove things from CPAN that you uploaded. If you're the owner, you can't delete a version uploaded by a co-maintainer. If you weren't happy with it, you could revoke their co-maintainer status and then upload a superseding version. But we'd recommend you talk to them (first).

  • If you upload a distribution containing a number of previously unseen modules, and haven't pre-registered them, then you'll get an 'f' permission for all of the modules. Let's say you upload a second release of the distribution, which doesn't include one of the modules, and then delete the first release from CPAN (via the PAUSE web interface). After some time the module will no longer be on CPAN, but you'll still have the 'f' permission in 06perms.txt. You can free up the namespace using the PAUSE interface ("Change Permissions").

  • If your first upload of a module is a Developer Release, then you won't get permissions for the module. You don't get permissions for a module until you've uploaded a non-developer release containing the module, that was accepted for indexing.

  • If you take over maintenance of a module, then you'll generally be given the permissions of the previous maintainer. So if the previous maintainer had 'm', then you'll get 'm', and (s)he will be downgraded to 'c'. If the previous maintainer had 'f', then you'll get 'f', and the previous owner will be downgraded to 'c'.


tmpdir() in File::Spec::Functions is used to get a local directory for caching 06perms.txt.

HTTP::Tiny is used to mirror 06perms.txt from CPAN.


  • Request the file gzip'd, if we've got an appropriate module that can be used to gunzip it.

  • At construct time we currently mirror the file; should do this lazily, triggering it the first time you want a module's perms.

  • Every time you ask for a module, I scan the file from the start, then close it once I've got the details for the requested module. Would be a lot more efficient to keep the file open and start the search from there, as the file is sorted. A binary chop on the file would be much more efficient as well.

  • The 06perms.txt file is currently mirrored with an If-Modified-Since request. We should probably also support a mechanism for saying things like "only get it if my copy is more than N days old". And consider using rsync as well.

  • A command-line script.



Neil Bowers <>

Thanks to Andreas König, for patiently answering many questions on how this stuff all works.


This software is copyright (c) 2012 by Neil Bowers <>.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 412:

Non-ASCII character seen before =encoding in 'König,'. Assuming UTF-8