diff --git a/tlatools/src/tlc2/TLC.java b/tlatools/src/tlc2/TLC.java
index 4ebfd8e67de918593df8f2d6e285681d8dc9e69f..d3d9101212320ee4e55a349697b892d4238a372d 100644
--- a/tlatools/src/tlc2/TLC.java
+++ b/tlatools/src/tlc2/TLC.java
@@ -458,7 +458,9 @@ public class TLC {
 								final TLAMonolithCreator monolithCreator
 										= new TLAMonolithCreator(TLAConstants.TraceExplore.ERROR_STATES_MODULE_NAME,
 																 mcOutputConsumer.getSourceDirectory(),
-																 extendedModules, mcParserResults.getAllExtendedModules());
+																 extendedModules,
+																 mcParserResults.getAllExtendedModules(),
+																 mcParserResults.getAllInstantiatedModules());
 								monolithCreator.copy();
 							}
 							
diff --git a/tlatools/src/tlc2/input/MCParser.java b/tlatools/src/tlc2/input/MCParser.java
index 518527ea63728901d338165f4a8fb2bbeaa8a216..b4fe53ebe4abaef18a20bbaaae2d5eae438e51be 100644
--- a/tlatools/src/tlc2/input/MCParser.java
+++ b/tlatools/src/tlc2/input/MCParser.java
@@ -8,6 +8,7 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 
+import tla2sany.semantic.InstanceNode;
 import tla2sany.semantic.ModuleNode;
 import tla2sany.semantic.OpDefNode;
 import tla2sany.semantic.SymbolMatcher;
@@ -77,10 +78,26 @@ public class MCParser {
 		root.getExtendedModuleSet(true).stream().forEach(moduleNode -> allExtendees.add(moduleNode.getName().toString()));
 		
 		rootModuleName = root.getName().toString();
+		
+		final HashSet<String> instantiatedModules = new HashSet<>();
+		collectionInstantiatedModules(root, instantiatedModules, allExtendees);
 
-		return new MCParserResults(rootModuleName, extendees, allExtendees, initNextLocationsToDelete,
-								   isInitNext, nextOrSpecName, modelConfig);
-	}	
+		return new MCParserResults(rootModuleName, extendees, allExtendees, instantiatedModules,
+								   initNextLocationsToDelete, isInitNext, nextOrSpecName, modelConfig);
+	}
+	
+	private static void collectionInstantiatedModules(final ModuleNode node, final HashSet<String> modulesList,
+													  final HashSet<String> allExtendees) {
+		final InstanceNode[] instances = node.getInstances();
+		for (final InstanceNode instance : instances) {
+			final ModuleNode instanceModule = instance.getModule();
+			instanceModule.getExtendedModuleSet(true)
+							.stream().forEach(moduleNode -> allExtendees.add(moduleNode.getName().toString()));
+			modulesList.add(instanceModule.getName().toString());
+			collectionInstantiatedModules(instanceModule, modulesList, allExtendees);
+		}
+	}
+	
 	
 	private final ModelConfig configParser;
 
@@ -195,7 +212,7 @@ public class MCParser {
 				// we'll have a zero size if the output generated came from a TLC run that did not have the '-tool' flag
 				parserResults = new MCParserResults(null, ((outputParser != null) ? outputParser.getError() : null),
 													encounteredMessages, new ArrayList<>(), new HashSet<>(),
-													new ArrayList<>(), true, null, configParser);
+													new HashSet<>(), new ArrayList<>(), true, null, configParser);
 			}
 			
 			return parserResults;
diff --git a/tlatools/src/tlc2/input/MCParserResults.java b/tlatools/src/tlc2/input/MCParserResults.java
index 2545aab9a7df82f99ecde6bebc05117216247d69..b3f57e89acfc96ddf63dbb780e7c88098551954c 100644
--- a/tlatools/src/tlc2/input/MCParserResults.java
+++ b/tlatools/src/tlc2/input/MCParserResults.java
@@ -15,6 +15,7 @@ public class MCParserResults {
 
 	private final List<String> immediateExtendedModules;
 	private final Set<String> allExtendedModules;
+	private final Set<String> modulesInstantiated;
 
 	private final List<Location> initNextLocationsToDelete;
 
@@ -25,13 +26,15 @@ public class MCParserResults {
 	private final ModelConfig modelConfig;
 
 	MCParserResults(final String rootModuleName, final List<String> immediateExtendeds, final Set<String> allExtendeds,
-					final List<Location> initNextLocations, final boolean wasInitNext, final String nextOrSpecName,
-					final ModelConfig config) {
+			 		final Set<String> allInstantiated, final List<Location> initNextLocations,
+			 		final boolean wasInitNext, final String nextOrSpecName, final ModelConfig config) {
 		moduleName = rootModuleName;
 		
 		immediateExtendedModules = immediateExtendeds;
 		allExtendedModules = allExtendeds;
 		
+		modulesInstantiated = allInstantiated;
+		
 		initNextLocationsToDelete = initNextLocations;
 		
 		behaviorIsInitNext = wasInitNext;
@@ -43,9 +46,10 @@ public class MCParserResults {
 	
 	MCParserResults(final String rootModuleName, final MCError mcError, final List<MCOutputMessage> messages,
 					final List<String> immediateExtendeds, final Set<String> allExtendeds,
-					final List<Location> initNextLocations, final boolean wasInitNext, final String nextOrSpecName,
-					final ModelConfig config) {
-		this(rootModuleName, immediateExtendeds, allExtendeds, initNextLocations, wasInitNext, nextOrSpecName, config);
+					final Set<String> allInstantiated, final List<Location> initNextLocations,
+					final boolean wasInitNext, final String nextOrSpecName, final ModelConfig config) {
+		this(rootModuleName, immediateExtendeds, allExtendeds, allInstantiated, initNextLocations, wasInitNext,
+			 nextOrSpecName, config);
 		
 		error = mcError;
 		outputMessages = messages;
@@ -94,6 +98,16 @@ public class MCParserResults {
 	public Set<String> getAllExtendedModules() {
 		return allExtendedModules;
 	}
+	
+	/**
+	 * @return this returns a {@link Set} of all instantiated modules - in other words, all modules, X, found in any
+	 * 				module of the entire module tree that is instantiated in TLA+ code like {@code ... = INSTANCE X}
+	 * 				<b>Note:</b> the is the possibility of a non-null intersection between this set and the set of
+	 * 				extended modules.
+	 */
+	public Set<String> getAllInstantiatedModules() {
+		return modulesInstantiated;
+	}
 
 	/**
 	 * @return ordered from location first in document to that which is last in document
diff --git a/tlatools/src/tlc2/output/TLAMonolithCreator.java b/tlatools/src/tlc2/output/TLAMonolithCreator.java
index 7ad35876246743f400853aaa2f0a59c42687ba27..cd5f0ea05a6957aed173603cabdd36858906807e 100644
--- a/tlatools/src/tlc2/output/TLAMonolithCreator.java
+++ b/tlatools/src/tlc2/output/TLAMonolithCreator.java
@@ -22,32 +22,48 @@ import tlc2.input.MCParserResults;
 import util.TLAConstants;
 
 public class TLAMonolithCreator extends AbstractTLACopier {
+	private static final String NESTED_MODULE_INDENT = "    ";
+	
+	
 	// these are modules which SANY logs that it has parsed
-	private final List<File> extendedModules;
+	private final List<File> modulesToEmbed;
 	// these are the modules which the root ModuleNode or one of its sub-ModuleNodes (or one or their sub-ModuleNodes
 	//		and so on, turtles all the way down) has defined as EXTENDS-ing in their spec
 	private final Set<String> modulesToSpecifyInExtends;
+	// TODO this is insufficient for nestings beyond one level
+	private final List<File> modulesToNest;
 	
 	public TLAMonolithCreator(final String rootSpecName, final File sourceLocation, final List<File> extendeds,
-							  final Set<String> entireExtendsList) {
+							  final Set<String> entireExtendsList, final Set<String> allInstantiatedModules) {
 		super(rootSpecName, ("tmp_" + System.currentTimeMillis() + "_monolith"), sourceLocation);
 		
-		extendedModules = new ArrayList<File>();
+		final HashSet<String> instantiatedModules = new HashSet<>(allInstantiatedModules);
+		modulesToEmbed = new ArrayList<>();
 		for (final File f : extendeds) {
 			final String name = f.getName();
 			final int index = name.toLowerCase().indexOf(TLAConstants.Files.TLA_EXTENSION);
 			final boolean keep;
+			final String moduleName;
 			if (index == -1) {
 				// this should never be the case
 				keep = true;
+				moduleName = name;
 			} else {
-				final String baseName = name.substring(0, index);
+				moduleName = name.substring(0, index);
 
-				keep = !StandardModules.isDefinedInStandardModule(baseName);
+				keep = !StandardModules.isDefinedInStandardModule(moduleName);
 			}
 			
 			if (keep) {
-				extendedModules.add(f);
+				modulesToEmbed.add(f);
+				instantiatedModules.remove(moduleName);
+			}
+		}
+		
+		modulesToNest = new ArrayList<>();
+		for (final String module : instantiatedModules) {
+			if (!StandardModules.isDefinedInStandardModule(module)) {
+				modulesToNest.add(new File(sourceLocation, (module + TLAConstants.Files.TLA_EXTENSION)));
 			}
 		}
 		
@@ -72,8 +88,12 @@ public class TLAMonolithCreator extends AbstractTLACopier {
 			if (originalLine.trim().startsWith(TLAConstants.KeyWords.EXTENDS)) {
 				writer.write(TLAConstants.KeyWords.EXTENDS + " " + String.join(", ", modulesToSpecifyInExtends) + "\n");
 
-				for (final File f : extendedModules) {
-					insertModuleIntoMonolith(f, writer);
+				for (final File f : modulesToNest) {
+					insertModuleIntoMonolith(f, writer, true);
+				}
+
+				for (final File f : modulesToEmbed) {
+					insertModuleIntoMonolith(f, writer, false);
 				}
 				
 				final StringBuilder commentLine = new StringBuilder(TLAConstants.CR);
@@ -98,7 +118,9 @@ public class TLAMonolithCreator extends AbstractTLACopier {
 		Files.move(monolithPath, originalPath, new CopyOption[0]);
 	}	
 	
-	private void insertModuleIntoMonolith(final File module, final BufferedWriter monolithWriter) throws IOException {
+	private void insertModuleIntoMonolith(final File module, final BufferedWriter monolithWriter,
+										  final boolean nestedModule)
+			throws IOException {
 		final StringBuilder commentLine = new StringBuilder(TLAConstants.CR);
 		final String moduleFilename = module.getName();
 		final int index = moduleFilename.indexOf(TLAConstants.Files.TLA_EXTENSION);
@@ -126,14 +148,23 @@ public class TLAMonolithCreator extends AbstractTLACopier {
 					final Matcher m = insertingModuleMatcher.matcher(line);
 
 					inModuleBody = m.find();
+					if (inModuleBody && nestedModule) {
+						monolithWriter.write(NESTED_MODULE_INDENT + line + '\n');
+					}
 				} else {
 					if (!line.trim().startsWith(TLAConstants.KeyWords.EXTENDS)) {
 						final Matcher m = CLOSING_BODY_PATTERN.matcher(line);
 
 						if (m.matches()) {
+							if (nestedModule) {
+								monolithWriter.write(NESTED_MODULE_INDENT + line + '\n');
+							}
 							break;
 						}
 
+						if (nestedModule) {
+							monolithWriter.write(NESTED_MODULE_INDENT);
+						}
 						monolithWriter.write(line + '\n');
 					}
 				}
@@ -188,7 +219,8 @@ public class TLAMonolithCreator extends AbstractTLACopier {
 			}
 			
 			final TLAMonolithCreator creator = new TLAMonolithCreator(specName, sourceDirectory, extendeds,
-																	  results.getAllExtendedModules());
+																	  results.getAllExtendedModules(),
+																	  results.getAllInstantiatedModules());
 			creator.copy();
 			
 			System.out.println("The monolith file is now present at: " + originalTLA.getAbsolutePath());