 		commenter = CodeCat.Commenters[ext]
 		if commenter? then regexpEscape(commenter) else ''
 
-	joinFiles = (paths, encoding, separator, stream) ->
-		paths.forEach (path, notFirst) ->
+	concatToStream = (stream, options, callback) ->
+		{recursive = true} = options
+		{encoding, source} = this
+		@findConcats relative: true, (concats) ->
+			error = null
+			concats = mapConcats(concats, (c) => new CodeCat(c, @options)) if recursive
+			paths = [concats.prepend..., source, concats.append...]
+			joinFiles paths, encoding, stream, options, -> callback?(error)
+	
+	joinFiles = (files, encoding, stream, options = {}, finishedFn) ->
+		{separator = EOL} = options
+		callbackForEach files, finishedFn, (file, notFirst, done) ->
 			output = (notFirst and separator) or ''
-			output += readFileSync(path, encoding: encoding)
-			stream.write(output)
+			writeEndCb =
+				if file instanceof CodeCat
+					-> concatToStream.call(file, stream, options, done)
+				else
+					output += readFileSync(file, encoding: encoding)
+					done
+			stream.write(output, encoding, writeEndCb)
 
 	ensureStream = (dest, options, fn) ->
 		[options, fn] = discernOptions(options, fn)
 		if isString(dest)
 			stream = createWriteStream(dest, options)
-			stream.once('open', -> fn(stream))
+			end = (endCb) -> stream.end(endCb)
+			stream.once('open', -> fn(stream, end))
 		else
-			fn(dest)
+			end = (endCb) -> endCb?()
+			fn(dest, end)
 
 	mapConcats = (concats, map, thisArg) ->
 		mapped = {}

		@concatTo stream, options, (error) -> callback?(concatted)

	concatTo: (dest, options, callback) ->
		[{separator = EOL}, callback] = discernOptions(options, callback)
		@findConcats relative: true, (concats) =>
			error = null
			paths = [concats.prepend..., @source, concats.append...]
			ensureStream dest, defaultEncoding: @encoding, (stream) ->
				joinFiles(paths, @encoding, separator, stream)
				stream.end -> callback?(error)

	getRelativePath: (file) ->
		sourceDir = Path.dirname(@source)

		Object.defineProperties this,
			source:
				value: source
			options:
				value: options
			prefix:
				value: prefix
			commenter:
