@@ -7,12 +7,23 @@ import { loadConfig } from "./config.ts"
77import { runLoop } from "./loop.ts"
88import type { CliOptions } from "./types.ts"
99
10- const VERSION = "0.1 .0"
10+ const VERSION = "1.0 .0"
1111
1212/**
13- * Parse CLI arguments and run the application
13+ * Result of CLI argument parsing.
14+ * Contains the parsed options and optional hint argument.
1415 */
15- export async function run ( ) : Promise < void > {
16+ export interface ParsedCli {
17+ /** Parsed CLI options (project, model, verbose, etc.) */
18+ options : CliOptions
19+ /** Optional hint/instruction for the AI, passed as a positional argument */
20+ hint ?: string
21+ }
22+
23+ /**
24+ * Create and configure the CLI program
25+ */
26+ function createProgram ( ) : Command {
1627 const program = new Command ( )
1728
1829 program
@@ -25,23 +36,9 @@ export async function run(): Promise<void> {
2536 . option ( "-P, --plan-model <model>" , "Model for plan phase (provider/model format)" )
2637 . option ( "-B, --build-model <model>" , "Model for build phase (provider/model format)" )
2738 . option ( "-v, --verbose" , "Enable verbose logging" )
28- . action ( async ( hint : string | undefined , opts : Record < string , unknown > ) => {
29- try {
30- const cliOptions : CliOptions = {
31- project : opts . project as string | undefined ,
32- model : opts . model as string | undefined ,
33- planModel : opts . planModel as string | undefined ,
34- buildModel : opts . buildModel as string | undefined ,
35- verbose : opts . verbose as boolean | undefined ,
36- }
37-
38- const config = await loadConfig ( cliOptions , hint )
39- await runLoop ( config )
40- } catch ( err ) {
41- console . error ( `Error: ${ err instanceof Error ? err . message : String ( err ) } ` )
42- process . exit ( 1 )
43- }
44- } )
39+ . option ( "--no-auto-commit" , "Disable automatic commits after tasks" )
40+ . option ( "--no-auto-push" , "Disable automatic push after cycles" )
41+ . option ( "-s, --signoff" , "Add Signed-off-by line to commits" )
4542
4643 // Add examples to help
4744 program . addHelpText (
@@ -60,27 +57,127 @@ Examples:
6057 $ opencoder -m openai/gpt-4o -p ./myproject -v
6158 Run with verbose logging in a specific directory
6259
60+ $ opencoder -m anthropic/claude-sonnet-4 --no-auto-commit --no-auto-push
61+ Run without automatic git operations
62+
63+ $ opencoder -m anthropic/claude-sonnet-4 -s
64+ Run with commit signoff enabled
65+
6366Options:
6467 -p, --project <dir> Project directory (default: current directory)
6568 -m, --model <model> Model for both plan and build
6669 -P, --plan-model Model for plan phase
6770 -B, --build-model Model for build phase
6871 -v, --verbose Enable verbose logging
72+ --no-auto-commit Disable automatic commits after tasks
73+ --no-auto-push Disable automatic push after cycles
74+ -s, --signoff Add Signed-off-by line to commits
6975
7076Environment variables:
7177 OPENCODER_PLAN_MODEL Default plan model
7278 OPENCODER_BUILD_MODEL Default build model
7379 OPENCODER_VERBOSE Enable verbose logging (true/1)
7480 OPENCODER_PROJECT_DIR Default project directory
81+ OPENCODER_AUTO_COMMIT Enable auto-commit (true/1, default: true)
82+ OPENCODER_AUTO_PUSH Enable auto-push (true/1, default: true)
83+ OPENCODER_COMMIT_SIGNOFF Add signoff to commits (true/1, default: false)
7584
7685Config file (.opencode/opencoder/config.json):
7786 {
7887 "planModel": "anthropic/claude-sonnet-4",
7988 "buildModel": "anthropic/claude-sonnet-4",
80- "verbose": false
89+ "verbose": false,
90+ "autoCommit": true,
91+ "autoPush": true,
92+ "commitSignoff": false
8193 }
8294` ,
8395 )
8496
97+ return program
98+ }
99+
100+ /**
101+ * Parse CLI arguments without executing the action.
102+ * Useful for testing or when you need to inspect arguments before running.
103+ *
104+ * @param argv - Command line arguments array. Defaults to process.argv.
105+ * Should include the node executable and script name as first two elements.
106+ * @returns Parsed CLI options and hint
107+ *
108+ * @example
109+ * ```typescript
110+ * // Parse default process arguments
111+ * const { options, hint } = parseCli()
112+ *
113+ * // Parse custom arguments for testing
114+ * const { options, hint } = parseCli(['node', 'opencoder', '-m', 'anthropic/claude-sonnet-4', 'my hint'])
115+ * ```
116+ */
117+ export function parseCli ( argv : string [ ] = process . argv ) : ParsedCli {
118+ const program = createProgram ( )
119+
120+ // Parse without running the action
121+ program . parse ( argv )
122+
123+ const opts = program . opts ( )
124+ const args = program . args
125+
126+ return {
127+ options : {
128+ project : opts . project as string | undefined ,
129+ model : opts . model as string | undefined ,
130+ planModel : opts . planModel as string | undefined ,
131+ buildModel : opts . buildModel as string | undefined ,
132+ verbose : opts . verbose as boolean | undefined ,
133+ autoCommit : opts . autoCommit as boolean | undefined ,
134+ autoPush : opts . autoPush as boolean | undefined ,
135+ commitSignoff : opts . signoff as boolean | undefined ,
136+ } ,
137+ hint : args [ 0 ] ,
138+ }
139+ }
140+
141+ /**
142+ * Parse CLI arguments and run the autonomous development loop.
143+ * This is the main entry point for the CLI application.
144+ *
145+ * Parses command line arguments, loads configuration from all sources
146+ * (defaults, config file, environment variables, CLI options), and
147+ * starts the autonomous development loop.
148+ *
149+ * @throws Will call process.exit(1) if configuration is invalid or an error occurs
150+ *
151+ * @example
152+ * ```typescript
153+ * // In your entry point (e.g., index.ts)
154+ * import { run } from './cli.ts'
155+ * await run()
156+ * ```
157+ */
158+ export async function run ( ) : Promise < void > {
159+ const program = createProgram ( )
160+
161+ program . action ( async ( hint : string | undefined , opts : Record < string , unknown > ) => {
162+ try {
163+ const cliOptions : CliOptions = {
164+ project : opts . project as string | undefined ,
165+ model : opts . model as string | undefined ,
166+ planModel : opts . planModel as string | undefined ,
167+ buildModel : opts . buildModel as string | undefined ,
168+ verbose : opts . verbose as boolean | undefined ,
169+ autoCommit : opts . autoCommit as boolean | undefined ,
170+ autoPush : opts . autoPush as boolean | undefined ,
171+ commitSignoff : opts . signoff as boolean | undefined ,
172+ }
173+
174+ const config = await loadConfig ( cliOptions , hint )
175+ await runLoop ( config )
176+ } catch ( err ) {
177+ console . error ( `Error: ${ err instanceof Error ? err . message : String ( err ) } ` )
178+ process . exit ( 1 )
179+ }
180+ } )
181+
85182 await program . parseAsync ( )
86183}
0 commit comments