function onGlob( error, files ) {
		var word;
		var idx;
		var i;

		if ( error ) {
			return clbk( error );
		}
		debug( 'Matched packages: %s', files.join( ', ' ) );

		if ( files.length === 0 ) {
			return clbk( null, {
				'toc': '<div class="namespace-toc">\n\n\n</div>',
				'links': []
			});
		}

		if ( opts.keywords ) {
			keywords = opts.keywords.split( ',' );
			allowed = [];
			forbidden = [];
			for ( i = 0; i < keywords.length; i++ ) {
				word = trim( keywords[ i ] );
				if ( startsWith( word, '+' ) ) {
					allowed.push( removeFirst( word ) );
				} else if ( startsWith( word, '-' ) ) {
					forbidden.push( removeFirst( word ) );
				}
			}
			paths = [];
			idx = 0;
			readJSON( resolve( opts.dir, files[ idx ], 'package.json' ), onPackage );
		} else {
			paths = [];
			for ( i = 0; i < files.length; i++ ) {
				paths.push( resolve( opts.dir, files[ i ], 'README.md' ) );
			}
			readFileList( paths, onContents );
		}

		/**
		* Callback invoked after loading the `package.json` file of the current package (with the file index given by `idx`).
		*
		* @private
		* @param {(Error|null)} error - error object
		* @param {Object} json - package.json object
		* @returns {void}
		*/
		function onPackage( error, json ) {
			var pkgKeywords;
			var include;
			var omit;
			var j;

			if ( error ) {
				return clbk( error );
			}
			pkgKeywords = json.keywords;
			omit = false;
			include = false;
			if ( allowed.length > 0 && forbidden.length > 0 ) {
				for ( j = 0; j < pkgKeywords.length; j++ ) {
					if ( contains( forbidden, pkgKeywords[ j ] ) ) {
						omit = true;
						break;
					} else if ( contains( allowed, pkgKeywords[ j ] ) ) {
						include = true;
					}
				}
			} else if ( allowed.length === 0 && forbidden.length > 0 ) {
				for ( j = 0; j < pkgKeywords.length; j++ ) {
					if ( contains( forbidden, pkgKeywords[ j ] ) ) {
						omit = true;
						break;
					}
				}
				include = true;
			} else if ( allowed.length > 0 && forbidden.length === 0 ) {
				for ( j = 0; j < pkgKeywords.length; j++ ) {
					if ( contains( allowed, pkgKeywords[ j ] ) ) {
						include = true;
						break;
					}
				}
			} else {
				include = true;
			}
			if ( include && !omit ) {
				paths.push( resolve( opts.dir, files[ idx ], 'README.md' ) );
			}
			idx += 1;
			if ( idx === files.length ) {
				readFileList( paths, onContents );
			} else {
				readJSON( resolve( opts.dir, files[ idx ], 'package.json' ), onPackage );
			}
		}
	}
Callback invoked after matching files.

@private
@param {(Error|null)} error - error object
@param {(EmptyArray|StringArray)} files - list of matching files
@returns {void}