diff --git a/cli/cli/command_framework/highlevel/service_identifier_arg/service_identifier_arg.go b/cli/cli/command_framework/highlevel/service_identifier_arg/service_identifier_arg.go
index 85c7274a8b..8adbad19ca 100644
--- a/cli/cli/command_framework/highlevel/service_identifier_arg/service_identifier_arg.go
+++ b/cli/cli/command_framework/highlevel/service_identifier_arg/service_identifier_arg.go
@@ -49,7 +49,7 @@ func NewHistoricalServiceIdentifierArgWithValidationDisabled(
 	return &args.ArgConfig{
 		Key:                   serviceIdentifierArgKey,
 		IsOptional:            isOptional,
-		DefaultValue:          "",
+		DefaultValue:          []string{},
 		IsGreedy:              isGreedy,
 		ArgCompletionProvider: args.NewManualCompletionsProvider(getCompletionsForExistingAndHistoricalServices(enclaveIdentifierArgKey)),
 		ValidationFunc:        noValidationFunc,
diff --git a/cli/cli/command_framework/lowlevel/args/consts_for_test.go b/cli/cli/command_framework/lowlevel/args/consts_for_test.go
index 2b9f5d6062..0a87f1f5a1 100644
--- a/cli/cli/command_framework/lowlevel/args/consts_for_test.go
+++ b/cli/cli/command_framework/lowlevel/args/consts_for_test.go
@@ -24,6 +24,7 @@ var validArgsConfig = []*ArgConfig{
 		IsGreedy: true,
 	},
 }
+
 var validTokens = []string{
 	arg1Value,
 	arg2Value,
diff --git a/cli/cli/commands/service/logs/logs.go b/cli/cli/commands/service/logs/logs.go
index 1f12ec1377..f123f45996 100644
--- a/cli/cli/commands/service/logs/logs.go
+++ b/cli/cli/commands/service/logs/logs.go
@@ -8,6 +8,7 @@ package logs
 import (
 	"context"
 	"fmt"
+	"github.com/fatih/color"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/services"
 	"github.com/kurtosis-tech/kurtosis/api/golang/engine/kurtosis_engine_rpc_api_bindings"
 	"github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context"
@@ -34,10 +35,12 @@ const (
 	isEnclaveIdArgGreedy    = false
 
 	serviceIdentifierArgKey        = "service"
-	isServiceIdentifierArgOptional = false
-	isServiceIdentifierArgGreedy   = false
+	isServiceIdentifierArgOptional = true // don't need to pass this in if they use the return all services flag
+	isServiceIdentifierArgGreedy   = true
 
 	shouldFollowLogsFlagKey  = "follow"
+	returnAllServiceLogs     = "all-services"
+	allServicesWildcard      = "*"
 	returnNumLogsFlagKey     = "num"
 	returnAllLogsFlagKey     = "all"
 	matchTextFilterFlagKey   = "match"
@@ -55,12 +58,25 @@ const (
 	commonInstructionInMatchFlags = "Important: " + matchTextFilterFlagKey + " and " + matchRegexFilterFlagKey + " flags cannot be used at the same time. You should either use one or the other."
 )
 
+type ColorPrinter func(a ...interface{}) string
+
+var colorList = []ColorPrinter{
+	color.New(color.FgBlue).SprintFunc(),
+	color.New(color.FgCyan).SprintFunc(),
+	color.New(color.FgGreen).SprintFunc(),
+	color.New(color.FgMagenta).SprintFunc(),
+	color.New(color.FgYellow).SprintFunc(),
+	color.New(color.FgHiRed).SprintFunc(),
+	color.New(color.FgHiBlue).SprintFunc(),
+	color.New(color.FgHiWhite).SprintFunc(),
+}
+
 var doNotFilterLogLines *kurtosis_context.LogLineFilter = nil
 
 var defaultShouldFollowLogs = strconv.FormatBool(false)
 var defaultInvertMatchFilterFlagValue = strconv.FormatBool(false)
-
 var defaultShouldReturnAllLogs = strconv.FormatBool(false)
+var defaultShouldReturnAllServiceLog = strconv.FormatBool(false)
 var defaultNumLogLinesFlagValue = strconv.Itoa(defaultNumLogLines)
 
 var ServiceLogsCmd = &engine_consuming_kurtosis_command.EngineConsumingKurtosisCommand{
@@ -121,6 +137,13 @@ var ServiceLogsCmd = &engine_consuming_kurtosis_command.EngineConsumingKurtosisC
 			Type:      flags.FlagType_Bool,
 			Default:   defaultInvertMatchFilterFlagValue,
 		},
+		{
+			Key:       returnAllServiceLogs,
+			Usage:     "Returns service log streams for all logs in an enclave",
+			Shorthand: "x",
+			Type:      flags.FlagType_Bool,
+			Default:   defaultShouldReturnAllServiceLog,
+		},
 	},
 	Args: []*args.ArgConfig{
 		enclave_id_arg.NewHistoricalEnclaveIdentifiersArgWithValidationDisabled(
@@ -131,8 +154,8 @@ var ServiceLogsCmd = &engine_consuming_kurtosis_command.EngineConsumingKurtosisC
 		service_identifier_arg.NewHistoricalServiceIdentifierArgWithValidationDisabled(
 			serviceIdentifierArgKey,
 			enclaveIdentifierArgKey,
-			isServiceIdentifierArgGreedy,
 			isServiceIdentifierArgOptional,
+			isServiceIdentifierArgGreedy,
 		),
 	},
 	RunFunc: run,
@@ -151,10 +174,20 @@ func run(
 		return stacktrace.Propagate(err, "An error occurred getting the enclave identifier using arg key '%v'", enclaveIdentifierArgKey)
 	}
 
-	serviceIdentifier, err := args.GetNonGreedyArg(serviceIdentifierArgKey)
+	shouldReturnAllServiceLogs, err := flags.GetBool(returnAllServiceLogs)
+	if err != nil {
+		return stacktrace.Propagate(err, "An error occurred getting the 'all-services' flag using key '%v'", returnAllServiceLogs)
+	}
+
+	var serviceIdentifiers []string
+	serviceIdentifiers, err = args.GetGreedyArg(serviceIdentifierArgKey)
 	if err != nil {
 		return stacktrace.Propagate(err, "An error occurred getting the service identifier using arg key '%v'", serviceIdentifierArgKey)
 	}
+	// if no service identifiers were passed or just the wildcard was passed, default to returning all
+	if len(serviceIdentifiers) == 0 || (len(serviceIdentifiers) == 1 && serviceIdentifiers[0] == allServicesWildcard) { //
+		shouldReturnAllServiceLogs = true
+	}
 
 	shouldFollowLogs, err := flags.GetBool(shouldFollowLogsFlagKey)
 	if err != nil {
@@ -191,10 +224,27 @@ func run(
 		return stacktrace.Propagate(err, "An error occurred connecting to the local Kurtosis engine")
 	}
 
-	serviceUuid := getEnclaveAndServiceUuidForIdentifiers(kurtosisCtx, ctx, enclaveIdentifier, serviceIdentifier)
+	if shouldReturnAllServiceLogs {
+		enclaveCtx, err := kurtosisCtx.GetEnclaveContext(ctx, enclaveIdentifier)
+		if err != nil {
+			return stacktrace.Propagate(err, "An error occurred retrieving enclave context for '%v'", enclaveIdentifier)
+		}
 
-	userServiceUuids := map[services.ServiceUUID]bool{
-		serviceUuid: true,
+		allServiceIdentifiers, err := enclaveCtx.GetExistingAndHistoricalServiceIdentifiers(ctx)
+		if err != nil {
+			return stacktrace.Propagate(err, "An error occurred retrieving service identifiers for enclave '%v'", enclaveIdentifier)
+		}
+		serviceIdentifiers = allServiceIdentifiers.GetOrderedListOfNames()
+	}
+
+	userServiceUuids := map[services.ServiceUUID]bool{}
+	serviceUuids := map[services.ServiceUUID]string{}
+	serviceColorPrinterMap := map[string]ColorPrinter{}
+	for idx, serviceIdentifier := range serviceIdentifiers {
+		serviceUuid := getEnclaveAndServiceUuidForIdentifiers(kurtosisCtx, ctx, enclaveIdentifier, serviceIdentifier)
+		serviceUuids[serviceUuid] = serviceIdentifier
+		serviceColorPrinterMap[serviceIdentifier] = colorList[idx%len(colorList)]
+		userServiceUuids[serviceUuid] = true
 	}
 
 	logLineFilter, err := getLogLineFilterFromFilterFlagValues(matchTextStr, matchRegexStr, invertMatch)
@@ -226,14 +276,16 @@ func run(
 			}
 
 			userServiceLogsByUuid := serviceLogsStreamContent.GetServiceLogsByServiceUuids()
-
-			userServiceLogs, found := userServiceLogsByUuid[serviceUuid]
-			if !found {
-				return stacktrace.NewError("Expected to find logs for user service with UUID '%v' on user service logs map '%+v' but was not found; this should never happen, and is a bug in Kurtosis", serviceUuid, userServiceLogsByUuid)
-			}
-
-			for _, serviceLog := range userServiceLogs {
-				out.PrintOutLn(serviceLog.GetContent())
+			for serviceUuid, serviceIdentifier := range serviceUuids {
+				userServiceLogs, found := userServiceLogsByUuid[serviceUuid]
+				if !found {
+					return stacktrace.NewError("Expected to find logs for user service with UUID '%v' on user service logs map '%+v' but was not found; this should never happen, and is a bug in Kurtosis", serviceUuid, userServiceLogsByUuid)
+				}
+
+				for _, serviceLog := range userServiceLogs {
+					colorPrinter := serviceColorPrinterMap[serviceIdentifier]
+					out.PrintOutLn(fmt.Sprintf("%v %v", colorPrinter("[%v]", serviceIdentifier), serviceLog.GetContent()))
+				}
 			}
 		case <-interruptChan:
 			logrus.Debugf("Received signal interruption in service logs Kurtosis CLI command")
diff --git a/docs/docs/cli-reference/service-logs.md b/docs/docs/cli-reference/service-logs.md
index cc819d6f55..5147e0e888 100644
--- a/docs/docs/cli-reference/service-logs.md
+++ b/docs/docs/cli-reference/service-logs.md
@@ -4,13 +4,13 @@ sidebar_label: service logs
 slug: /service-logs
 ---
 
-To print the logs for a service, run:
+To print the logs for services in an enclave, run:
 
 
 ```bash
-kurtosis service logs $THE_ENCLAVE_IDENTIFIER $THE_SERVICE_IDENTIFIER
+kurtosis service logs $THE_ENCLAVE_IDENTIFIER $THE_SERVICE_IDENTIFIER1 $THE_SERVICE_IDENTIFIER2 $THE_SERVICE_IDENTIFIER3
 ```
-where `$THE_ENCLAVE_IDENTIFIER` and the `$THE_SERVICE_IDENTIFIER` are [resource identifiers](../advanced-concepts/resource-identifier.md) for the enclave and service, respectively. The service identifier (name or UUID) is printed upon inspecting an enclave. 
+where `$THE_ENCLAVE_IDENTIFIER` and the `$THE_SERVICE_IDENTIFIER` are [resource identifiers](../advanced-concepts/resource-identifier.md) for the enclave and services, respectively. The service identifier (name or UUID) is printed upon inspecting an enclave. 
 :::
 
 :::note Number of log lines
@@ -23,7 +23,8 @@ Kurtosis will keep logs for up to 4 weeks before removing them to prevent logs f
 The following optional arguments can be used:
 1. `-a`, `--all` can be used to retrieve all logs.
 1. `-n`, `--num=uint32` can be used to retrieve X last log lines. (eg. `-n 10` will retrieve last 10 log lines, similar to `tail -n 10`)
-1. `-f`, `-follow` can be added to continue following the logs, similar to `tail -f`.
+1. `-f`, `--follow` can be added to continue following the logs, similar to `tail -f`.
+1. `-x`, `--all-services` can be used to retrieve logs for all services in an enclave. Another option is to pass in the escaped wildcard operator like so `kurtosis service logs enclave-name '*'`
 1. `--match=text` can be used for filtering the log lines containing the text.
 1. `--regex-match="regex"` can be used for filtering the log lines containing the regex. This filter will also work for text but will have degraded performance.
 1. `-v`, `--invert-match` can be used to invert the filter condition specified by either `--match` or `--regex-match`. Log lines NOT containing the match will be returned.
diff --git a/engine/server/engine/server/engine_connect_server_service.go b/engine/server/engine/server/engine_connect_server_service.go
index 6dc9804e6b..3fc908e916 100644
--- a/engine/server/engine/server/engine_connect_server_service.go
+++ b/engine/server/engine/server/engine_connect_server_service.go
@@ -280,7 +280,6 @@ func (service *EngineConnectServerService) Clean(ctx context.Context, connectArg
 }
 
 func (service *EngineConnectServerService) GetServiceLogs(ctx context.Context, connectArgs *connect.Request[kurtosis_engine_rpc_api_bindings.GetServiceLogsArgs], stream *connect.ServerStream[kurtosis_engine_rpc_api_bindings.GetServiceLogsResponse]) error {
-
 	args := connectArgs.Msg
 	enclaveIdentifier := args.GetEnclaveIdentifier()
 	enclaveUuid, err := service.enclaveManager.GetEnclaveUuidForEnclaveIdentifier(context.Background(), enclaveIdentifier)