Class Ghostwriter
Ghostwriter scans a project's files or directories and processes them with GenAI guidance. It supports two processing modes:
- Guidance mode (default) — processes files using inline
guidance comments found in the scanned content, via
GuidanceProcessor. - Act mode (enabled with
--act) — runs a predefined, possibly interactive, prompt ("act") against the project, viaActProcessor.
Runtime behavior can be configured through command-line options, a persisted
properties file (see PropertiesConfigurator), or a combination of
both, with command-line options taking precedence. This class is responsible
for parsing CLI arguments, resolving effective settings, wiring up the
appropriate processor, and mapping processing outcomes to JVM exit codes.
This class is not intended to be instantiated; it exposes only a static
main(String[]) entry point.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final classMutable holder for startup settings resolved before processor creation. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final Stringprivate static final Stringprivate static final Stringstatic final Stringprivate static final Stringprivate static final intprivate static final Stringprivate static final Stringprivate static final org.slf4j.Loggerprivate static final Stringprivate static final Stringprivate static final Stringstatic final String -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate static voidappendContinuedLine(StringBuilder sb, String nextLine) Appends a continued input line to the buffer, stripping the trailing continuation marker and replacing it with the platform line separator.private static voidapplyCommonSettings(AIFileProcessor processor, Ghostwriter.RuntimeSettings settings) Applies shared processor settings — instructions, excludes, and concurrency — to the given processor, skipping any setting that was not resolved.private static voidapplyConcurrency(AIFileProcessor processor, String threads) Applies the configured concurrency (thread count) setting to the processor when present, logging the resolved value at INFO level.private static voidapplyExcludes(AIFileProcessor processor, String[] excludes) Applies exclude patterns to the processor when configured, logging the full list at INFO level.private static voidapplyInstructions(AIFileProcessor processor, String instructions) Applies custom instructions to the processor when present, logging an abbreviated version of the text at INFO level.private static voidconfigureActsLocation(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, ActProcessor actProcessor) Configures a custom acts location on the given processor when one is provided via the--actscommand-line option or configuration.private static voidconfigureDefaultAct(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, Scanner scanner, ActProcessor actProcessor) Configures the default act to run when act mode is enabled.private static ActProcessorcreateActProcessor(Scanner scanner, PropertiesConfigurator config, Ghostwriter.RuntimeSettings settings) Creates anActProcessorwith console-backed interactive input, overridingAIFileProcessor.input()to read from the CLI scanner instead of the default input source.private static org.apache.commons.cli.OptionsCreates the supported CLI option definitions.private static AIFileProcessorcreateProcessor(Scanner scanner, PropertiesConfigurator config, org.apache.commons.cli.CommandLine cmd, Ghostwriter.RuntimeSettings settings) Creates either aGuidanceProcessor(default mode) or anActProcessor(when--actis specified), fully configured for the current run.private static voidexecute(Scanner scanner, PropertiesConfigurator config, org.apache.commons.cli.CommandLine cmd, Ghostwriter.RuntimeSettings settings) Creates and runs the selected processor (guidance or act mode) against the resolved scan paths, then applies the resulting exit code.private static voidformatConsole(Console console, String message) Writes a prompt message to the console when available.private static voidhandleExitCode(int exitCode) Terminates the JVM with the given exit code when it is non-zero.private static inthandleProcessingFailure(String message, Exception exception) Logs a processing failure with the given message prefix and returns the generic error exit code.private static intHandles an explicit process termination request raised by a processor or tool, logging the termination message and reason before returning the exit code requested by the exception.private static voidinitializeConfiguration(org.apache.commons.cli.CommandLine cmd, String projectDir, PropertiesConfigurator config) Loads the external configuration properties file when present, using either theGWConstants.CONFIG_PROP_NAMEsystem property or the default Ghostwriter properties file name, resolved relative to the home directory.private static Ghostwriter.RuntimeSettingsloadRuntimeSettings(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, Scanner scanner) Resolves runtime settings from CLI arguments and persisted configuration.private static voidlogAbbreviatedMessage(String label, String value) Logs an abbreviated value at INFO level, skipping the abbreviation work entirely when INFO logging is disabled.private static voidlogStartup(File projectDir) Logs basic startup path information at INFO level: the resolved Ghostwriter home directory and the resolved project directory.private static voidLogs the application version when available from package metadata.static voidStarts the Ghostwriter CLI.private static voidprintHelp(org.apache.commons.cli.Options options) Prints CLI help text, including usage syntax, all available options, and example invocations, to standard output.private static intprocessPathectories(AIFileProcessor processor, String[] paths, File projectDir) Processes all requested scan paths using the given processor, converting recognized failures into an appropriate exit code instead of propagating them further, and always logging usage statistics and completion.private static StringpromptForValue(Scanner scanner, String prompt) Prompts the user for a single (possibly multi-line) piece of input on standard input, printing the prompt viaConsolewhen available or plainSystem.outotherwise.private static StringreadActInput(Scanner scanner) Reads possibly multi-line interactive act input from standard input, printing theUSER_INPUT_PREFIXprompt before each line and supporting the same continuation-marker convention aspromptForValue(Scanner, String).private static String[]resolveExcludes(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the exclude list from the--excludescommand-line option or configuration, splitting the comma-separated value into individual patterns.private static StringresolveGenai(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the configured AI provider/model, preferring the--modelcommand-line option over the corresponding configuration value.private static StringresolveInstructions(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, Scanner scanner) Resolves the system instruction text from CLI input or configuration.private static StringresolveMultiThread(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the concurrency (thread count) setting from the--threadscommand-line option or configuration.private static String[]resolvePaths(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the scan directories or patterns to process, in order of precedence: positional command-line arguments, then the configured path property, then the current directory (".") as a final fallback.private static FileresolveProjectDir(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the project directory from the-dcommand-line option or configuration.
-
Field Details
-
LOGGER
private static final org.slf4j.Logger LOGGER -
USER_INPUT_PREFIX
- See Also:
-
HELP_OPTION
- See Also:
-
THREADS_OPTION
- See Also:
-
PROJECT_DIR_PROP_NAME
- See Also:
-
INSTRUCTIONS_PROP_NAME
- See Also:
-
MODEL_OPTION
- See Also:
-
EXCLUDES_OPTION
- See Also:
-
ACT_OPTION
- See Also:
-
ACTS_OPTION
- See Also:
-
CONFIG_OPTION
- See Also:
-
EXIT_CODE_ERROR
private static final int EXIT_CODE_ERROR- See Also:
-
DEFAULT_MODEL_MSG
- See Also:
-
-
Constructor Details
-
Ghostwriter
private Ghostwriter()
-
-
Method Details
-
main
Starts the Ghostwriter CLI.Parses command-line arguments, loads configuration, resolves runtime settings, and delegates to the appropriate processor. If
--helpis specified, prints usage information and returns without processing anything.- Parameters:
args- command-line arguments- Throws:
IOException- if configuration or processing fails with an I/O errororg.apache.commons.cli.ParseException- if command-line parsing fails
-
createOptions
private static org.apache.commons.cli.Options createOptions()Creates the supported CLI option definitions.- Returns:
- configured options describing every flag accepted by the CLI
-
printHelp
Prints CLI help text, including usage syntax, all available options, and example invocations, to standard output.- Parameters:
options- available command-line options- Throws:
IOException
-
logVersion
private static void logVersion()Logs the application version when available from package metadata. If no implementation version is present (e.g., when running from an IDE without a packaged manifest), no log entry is produced. -
initializeConfiguration
private static void initializeConfiguration(org.apache.commons.cli.CommandLine cmd, String projectDir, PropertiesConfigurator config) throws IOException Loads the external configuration properties file when present, using either theGWConstants.CONFIG_PROP_NAMEsystem property or the default Ghostwriter properties file name, resolved relative to the home directory.Failures to locate or load the file are tolerated: a missing file is silently ignored, while unexpected runtime errors are logged as warnings so startup can continue.
- Parameters:
config- configuration source to populateprojectDir-- Throws:
IOException
-
loadRuntimeSettings
private static Ghostwriter.RuntimeSettings loadRuntimeSettings(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, Scanner scanner) Resolves runtime settings from CLI arguments and persisted configuration.For every setting, an explicit command-line value takes precedence over the corresponding value from
config, which in turn takes precedence over any built-in default.- Parameters:
cmd- parsed command lineconfig- configuration sourcescanner- console scanner used for optional interactive prompts- Returns:
- populated runtime settings ready to be applied to a processor
-
resolveGenai
private static String resolveGenai(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the configured AI provider/model, preferring the--modelcommand-line option over the corresponding configuration value.- Parameters:
cmd- parsed command lineconfig- configuration source- Returns:
- provider/model identifier (e.g.
"OpenAI:gpt-5.1"), ornullif not configured
-
resolveInstructions
private static String resolveInstructions(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, Scanner scanner) Resolves the system instruction text from CLI input or configuration.If the
--instructionsoption is present without a value, the user is interactively prompted (viascanner) to enter the instruction text.- Parameters:
cmd- parsed command lineconfig- configuration sourcescanner- console scanner used for prompting when no value is supplied- Returns:
- resolved instruction text, or
nullif not configured
-
resolveExcludes
private static String[] resolveExcludes(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the exclude list from the--excludescommand-line option or configuration, splitting the comma-separated value into individual patterns.- Parameters:
cmd- parsed command lineconfig- configuration source- Returns:
- exclude patterns split by comma, or
nullif not configured
-
resolveMultiThread
private static String resolveMultiThread(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the concurrency (thread count) setting from the--threadscommand-line option or configuration.- Parameters:
cmd- parsed command lineconfig- configuration source- Returns:
- configured thread count as text, or
nullif not configured
-
resolveProjectDir
private static File resolveProjectDir(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the project directory from the-dcommand-line option or configuration.- Parameters:
cmd- parsed command lineconfig- configuration source- Returns:
- project directory; falls back to the current user directory when not explicitly configured
-
resolvePaths
private static String[] resolvePaths(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config) Resolves the scan directories or patterns to process, in order of precedence: positional command-line arguments, then the configured path property, then the current directory (".") as a final fallback.- Parameters:
cmd- parsed command lineconfig- configuration source- Returns:
- scan path(s) or pattern(s) to process; never
nullor empty
-
promptForValue
Prompts the user for a single (possibly multi-line) piece of input on standard input, printing the prompt viaConsolewhen available or plainSystem.outotherwise.Lines ending with
GWConstants.MULTIPLE_LINES_BREAKERare treated as continued: the breaker is stripped and a line separator is appended, and reading continues on the next line. Reading stops at the first line that does not end with the breaker. After input is collected, a right-aligned signature footer with the current user name is printed.- Parameters:
scanner- scanner reading standard inputprompt- prompt text to display before reading- Returns:
- the entered value, with continuation markers removed and multiple lines joined by the platform line separator
-
logStartup
Logs basic startup path information at INFO level: the resolved Ghostwriter home directory and the resolved project directory.- Parameters:
projectDir- project directory
-
execute
private static void execute(Scanner scanner, PropertiesConfigurator config, org.apache.commons.cli.CommandLine cmd, Ghostwriter.RuntimeSettings settings) throws IOException Creates and runs the selected processor (guidance or act mode) against the resolved scan paths, then applies the resulting exit code.Recognized failures are logged and translated into a non-zero exit code via
handleExitCode(int)rather than propagating as uncaught exceptions, except for I/O errors during processor creation, which are rethrown.- Parameters:
scanner- console scannerconfig- configuration sourcecmd- parsed command linesettings- resolved runtime settings- Throws:
IOException- if processor creation fails with an I/O error
-
handleExitCode
private static void handleExitCode(int exitCode) Terminates the JVM with the given exit code when it is non-zero. A zero exit code is treated as success and does not triggerSystem.exit(int).- Parameters:
exitCode- exit code to apply
-
createProcessor
private static AIFileProcessor createProcessor(Scanner scanner, PropertiesConfigurator config, org.apache.commons.cli.CommandLine cmd, Ghostwriter.RuntimeSettings settings) throws IOException Creates either aGuidanceProcessor(default mode) or anActProcessor(when--actis specified), fully configured for the current run.- Parameters:
scanner- console scannerconfig- configuration sourcecmd- parsed command linesettings- resolved runtime settings- Returns:
- configured processor ready for use
- Throws:
IOException- if act initialization fails
-
createActProcessor
private static ActProcessor createActProcessor(Scanner scanner, PropertiesConfigurator config, Ghostwriter.RuntimeSettings settings) Creates anActProcessorwith console-backed interactive input, overridingAIFileProcessor.input()to read from the CLI scanner instead of the default input source. Logs the resolved AI model, if any, at INFO level.- Parameters:
scanner- console scannerconfig- configuration sourcesettings- resolved runtime settings- Returns:
- act processor configured for CLI-driven interactive input
-
readActInput
Reads possibly multi-line interactive act input from standard input, printing theUSER_INPUT_PREFIXprompt before each line and supporting the same continuation-marker convention aspromptForValue(Scanner, String).- Parameters:
scanner- scanner reading standard input- Returns:
- collected input text, with continuation markers removed and multiple lines joined by the platform line separator
-
formatConsole
Writes a prompt message to the console when available. If noConsoleis attached (e.g., input is redirected), no output is produced.- Parameters:
console- console instance, may benullmessage- message to print, followed by": "
-
appendContinuedLine
Appends a continued input line to the buffer, stripping the trailing continuation marker and replacing it with the platform line separator.- Parameters:
sb- buffer receiving the linenextLine- line that ends with the continuation marker
-
configureActsLocation
private static void configureActsLocation(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, ActProcessor actProcessor) Configures a custom acts location on the given processor when one is provided via the--actscommand-line option or configuration. Leaves the processor's default acts location unchanged if none is configured.- Parameters:
cmd- parsed command lineconfig- configuration sourceactProcessor- act processor to configure
-
configureDefaultAct
private static void configureDefaultAct(org.apache.commons.cli.CommandLine cmd, PropertiesConfigurator config, Scanner scanner, ActProcessor actProcessor) throws IOException Configures the default act to run when act mode is enabled.The act name/prompt is resolved from the
--actcommand-line option value or configuration. If--actis present without a value, the user is interactively prompted (viascanner) to enter the act name.- Parameters:
cmd- parsed command lineconfig- configuration sourcescanner- scanner used for prompting when no value is suppliedactProcessor- act processor to configure- Throws:
IOException- if act loading fails
-
applyCommonSettings
private static void applyCommonSettings(AIFileProcessor processor, Ghostwriter.RuntimeSettings settings) Applies shared processor settings — instructions, excludes, and concurrency — to the given processor, skipping any setting that was not resolved.- Parameters:
processor- processor to configuresettings- resolved runtime settings
-
applyInstructions
Applies custom instructions to the processor when present, logging an abbreviated version of the text at INFO level.- Parameters:
processor- processor to configureinstructions- instruction text, ornullto leave unset
-
applyExcludes
Applies exclude patterns to the processor when configured, logging the full list at INFO level.- Parameters:
processor- processor to configureexcludes- exclude patterns, ornullto leave unset
-
applyConcurrency
Applies the configured concurrency (thread count) setting to the processor when present, logging the resolved value at INFO level.- Parameters:
processor- processor to configurethreads- thread count as text, ornullto leave unset; parsed withInteger.parseInt(String)
-
logAbbreviatedMessage
Logs an abbreviated value at INFO level, skipping the abbreviation work entirely when INFO logging is disabled.- Parameters:
label- message labelvalue- message value
-
processPathectories
Processes all requested scan paths using the given processor, converting recognized failures into an appropriate exit code instead of propagating them further, and always logging usage statistics and completion.- Parameters:
processor- configured processorpaths- scan directories or patterns to process, in orderprojectDir- project directory- Returns:
0on success; the termination exception's exit code if processing was explicitly terminated;EXIT_CODE_ERRORfor any other handled failure
-
handleProcessTermination
Handles an explicit process termination request raised by a processor or tool, logging the termination message and reason before returning the exit code requested by the exception.- Parameters:
exception- termination exception carrying the requested exit code- Returns:
- exit code to use, as specified by
exception
-
handleProcessingFailure
Logs a processing failure with the given message prefix and returns the generic error exit code.- Parameters:
message- log prefix describing the failure categoryexception- failure that occurred during processing- Returns:
EXIT_CODE_ERROR
-