anchor.diff:        return list.first;
       }
   
  -    return Script.fromComponents(
  -        name ?? list.map((script) => script.name).join(" | "), () {
  -      for (var i = 0; i < list.length - 1; i++) {
  -        list[i].stdout.pipe(list[i + 1].stdin);
  -      }
  -
  -      return ScriptComponents(
  -          list.first.stdin,
  -          // Wrap the final script's stdout and stderr in [SubscriptionStream]s
  -          // so that the inner scripts will see that someone's listening and not
  -          // try to top-level the streams' output.
  -          SubscriptionStream(list.last.stdout.listen(null)),
  -          SubscriptionStream(list.last.stderr.listen(null)),
  -          Future.wait(list.map((script) => script.exitCode)).then((exitCodes) =>
  -              exitCodes.lastWhere((code) => code != 0, orElse: () => 0)));
  -    });
  +    for (var i = 0; i < list.length - 1; i++) {
  +      list[i].stdout.pipe(list[i + 1].stdin);
  +    }
  +
  +    return Script._(
  +        name ?? list.map((script) => script.name).join(" | "),
  +        list.first.stdin,
  +        // Wrap the final script's stdout and stderr in [SubscriptionStream]s so
  +        // that the inner scripts will see that someone's listening and not try
  +        // to top-level the streams' output.
  +        SubscriptionStream(list.last.stdout.listen(null)),
  +        SubscriptionStream(list.last.stderr.listen(null)),
  +        Future.wait(list.map((script) => script.exitCode)).then((exitCodes) =>
  +            exitCodes.lastWhere((code) => code != 0, orElse: () => 0)));
     }
   
     /// Creates a script from existing [stdin], [stdout], [stderr], and [exitCode]
  
positive.code:   /// See also [operator |], which provides a syntax for creating pipelines two
    /// scripts at a time.
    factory Script.pipeline(Iterable<Script> scripts, {String? name}) {
      var list = scripts.toList();
      if (list.isEmpty) {
        throw ArgumentError.value(list, "script", "May not be empty");
  
negative.code:   factory Script.capture(
        FutureOr<void> Function(Stream<List<int>> stdin) callback,
        {String? name}) {
      _checkCapture();
  
      var childScripts = FutureGroup<void>();
      var stdinController = StreamController<List<int>>();
      var stdoutGroup = StdioGroup();
      var stderrGroup = StdioGroup();
      var exitCodeCompleter = Completer<int>();
  
      runZonedGuarded(
          () async {
            await callback(stdinController.stream);
  
            // Once there are no child scripts still spawning or running, mark
            // this script as done.
            void checkIdle() {
              if (childScripts.isIdle && !exitCodeCompleter.isCompleted) {
                stdoutGroup.close();
                stderrGroup.close();
                childScripts.close();
                exitCodeCompleter.complete(0);
              }
            }
  
            checkIdle();
            childScripts.onIdle.listen((_) => Timer.run(checkIdle));
          },
          (error, stackTrace) {
            if (!exitCodeCompleter.isCompleted) {
              stdoutGroup.close();
              stderrGroup.close();
              childScripts.close();
              exitCodeCompleter.completeError(error, stackTrace);
            }
          },
          zoneValues: {
            #_childScripts: childScripts,
            stdoutKey: stdoutGroup,
            stderrKey: stderrGroup
          },
          zoneSpecification: ZoneSpecification(print: (_, parent, zone, line) {
            if (!exitCodeCompleter.isCompleted) {
              // Add a separate stream rather than using [stdoutGroup.sink] so
              // that prints will go through even if the user has put the sink
              // in a weird state by calling [StreamSink.close] or
              // [StreamSink.addStream].
              stdoutGroup.add(Stream.value(utf8.encode("$line\n")));
            }
          }));
  
      return Script._(name ?? "capture", stdinController.sink, stdoutGroup.stream,
          stderrGroup.stream, exitCodeCompleter.future);
    }
  
    /// Pipes each script's [stdout] into the next script's [stdin].
  