Skip to content

Added Commandline Arguments for Chat Creation#392

Open
derDere wants to merge 14 commits intonanbingxyz:mainfrom
derDere:main
Open

Added Commandline Arguments for Chat Creation#392
derDere wants to merge 14 commits intonanbingxyz:mainfrom
derDere:main

Conversation

@derDere
Copy link
Copy Markdown

@derDere derDere commented Nov 27, 2025

This request solves the feature request (issue): #391

I added a command line argument parser that allows the user to create a new custom chat on startup or trigger the creation of a new custom chat if 5ire is already running. The following command line options were created:

5ire command-line options:

General usage:
  --help, -h, /?        Show this help and exit

Chat creation (pass together with --new-chat):
  --new-chat            Create the chat before the UI renders
  --provider <name>     Provider key exactly as configured (e.g. OpenAI)
  --model <name>        Model name exactly as shown in Providers (e.g. gpt-5-nano)
  --system <text>       System/system prompt for the assistant
  --prompt <text>       Initial user message (auto-submitted)
  --summary <text>      Friendly name for the chat (defaults to prompt preview)
  --temperature <num>   Temperature override (falls back to provider default)

Examples:
  5ire.exe --new-chat --provider OpenAI --model gpt-5-nano --system "Be nice" --prompt "Hello" --summary "Demo" --temperature 0.8

I'll admit my demand for this feature was high and urgent, so this solution was quickly vibe coded within two days. My company can't wait too long for this feature, and now with this fork we can already use it. Even if this pull request fails, I hope you make use it to have a deeper look at my feature request mentioned above.

High-level PR Summary

This PR adds command-line argument support to automatically create and configure chats when launching the application. Users can now specify --new-chat along with options like --provider, --model, --system, --prompt, --summary, and --temperature to create pre-configured chat sessions on startup. The implementation includes a dedicated CLI argument parser, IPC communication between main and renderer processes, comprehensive test coverage, and detailed documentation with usage examples. The feature also supports JSON format for bulk configuration and handles edge cases like provider derivation from model strings (e.g., anthropic:claude-3-opus).

⏱️ Estimated Review Time: 30-90 minutes

💡 Review Order Suggestion
Order File Path
1 docs/CLI_ARGUMENTS.md
2 docs/IMPLEMENTATION_SUMMARY.md
3 src/main/cli-args.ts
4 test/main/cli-args.spec.ts
5 src/main/preload.ts
6 src/main/main.ts
7 src/renderer/components/StartupHandler.tsx
8 src/renderer/components/FluentApp.tsx
9 src/renderer/pages/chat/index.tsx
10 src/stores/useChatStore.ts
11 src/renderer/ChatContext.ts
12 .erb/scripts/wait-for-renderer.ts
13 package.json
14 package-lock.json

Need help? Join our Discord

Analyze latest changes

Summary by CodeRabbit

  • New Features

    • Added CLI startup arguments feature enabling automatic chat creation and configuration on app launch using command-line flags (--chat, --provider, --model, --system, --summary, --prompt, --temperature)
    • Integrated CLI help support with guidance on startup arguments
  • Documentation

    • New CLI arguments reference guide documenting all supported startup options, usage patterns, JSON format support, examples, and behavioral notes
    • Added implementation summary documentation for the new feature

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI and others added 14 commits November 25, 2025 11:15
Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
… creation

Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
…dling

Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
…ust regex parsing

Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
Co-authored-by: derDere <36049068+derDere@users.noreply.github.com>
…-args

Implement CLI startup arguments for auto-creating chats
Copilot AI review requested due to automatic review settings November 27, 2025 09:04
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Nov 27, 2025

📝 Walkthrough

Walkthrough

This PR introduces a Terminal Startup Arguments feature that allows users to pass CLI arguments to the 5ire application to auto-create and navigate to chats with specified configurations. It includes CLI parsing, IPC communication, a React startup handler component, test coverage, and comprehensive documentation.

Changes

Cohort / File(s) Summary
CLI Argument Parsing & Configuration
src/main/cli-args.ts, test/main/cli-args.spec.ts
New TypeScript module exposing StartupChatArgs interface and parseStartupArgs() function to parse CLI arguments (--provider, --model, --system, --summary, --prompt, --temperature, --chat, --new-chat) with manual fallback parsing and normalization. Comprehensive test suite validates parsing logic, JSON handling, temperature conversion, and provider/model derivation.
Main Process Integration
src/main/main.ts
Integrates CLI argument handling into Electron main process: adds help flag detection and output, enqueues startup args during cold start and second-instance scenarios, coordinates renderer readiness via IPC listeners ('install-tool-listener-ready', 'startup-handler-ready'), and flushes pending args when ready.
Preload IPC API
src/main/preload.ts
Expands IPC Channels union with 'startup-handler-ready' and 'startup-new-chat'. Adds new startup.onNewChat() API to electronHandler, enabling renderer-side listeners for startup arguments with disposer function.
Renderer Startup Handler
src/renderer/components/StartupHandler.tsx
New React component that listens for startup arguments via window.electron.startup.onNewChat, creates chats with resolved provider/model, navigates to the new chat, and auto-submits prompts via event bus. Signals readiness to main process on mount.
Chat Page Refinements
src/renderer/pages/chat/index.tsx
Updates chat initialization to derive provider/model from current chat state, adds startup-submit event listener for auto-prompting, improves message creation to use resolved provider/model names, refines dependency arrays, and conditionally updates chat properties on creation vs. edit.
Chat Store Improvements
src/stores/useChatStore.ts
Refines createChat merge strategy to leverage currentChat with explicit provider/model override semantics, enhances debug logging in editChat and fetchChat, adds eslint directives around IChatStore interface.
Wait-for-Renderer Script & Build Config
.erb/scripts/wait-for-renderer.ts, package.json
New Node.js script polls port 1212 for renderer availability using detect-port, retrying every second up to 60 seconds. Adds npm script start:main:wait and dependencies argparse (^2.0.1) and @postlight/parser (^2.2.3).
Debug Enhancements
src/renderer/ChatContext.ts
Adds debug logging to getProvider showing chosen provider label and usage context (chat-specific vs. default), and preliminary logging in getModel.
Documentation
docs/CLI_ARGUMENTS.md, docs/IMPLEMENTATION_SUMMARY.md
Comprehensive documentation of CLI argument usage, syntax, examples, and an end-to-end implementation summary covering parsing, IPC flow, preload API, renderer handling, data flow, testing, security, and edge cases.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI / Process<br/>Args
    participant Main as Main Process
    participant IPC as IPC Channel
    participant Renderer as Renderer Process
    participant React as StartupHandler<br/>Component
    participant Store as Chat Store

    CLI->>Main: app launch with --provider --model --prompt args
    Main->>Main: parseStartupArgs(argv)
    Main->>Main: enqueueStartupArgs(parsed args)
    Main->>Renderer: app ready event
    
    Renderer->>React: mount StartupHandler
    React->>IPC: send startup-handler-ready
    IPC->>Main: receive startup-handler-ready
    Main->>IPC: send startup-new-chat with queued args
    
    IPC->>React: onNewChat listener triggered
    React->>React: normalize provider/model names
    React->>Store: createChat(chatData)
    Store-->>React: new chat created
    React->>React: navigate to new chat
    React->>React: editStage(resolved provider/model)
    alt prompt provided
        React->>React: emit startup-submit event
        React->>Store: auto-submit message with prompt
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Provider/Model Normalization Logic (src/main/cli-args.ts, src/renderer/components/StartupHandler.tsx): Verify correctness of provider derivation from model format strings (e.g., "Provider:model") and case-sensitivity handling in provider matching.
  • IPC Coordination Timing (src/main/main.ts, src/renderer/components/StartupHandler.tsx): Ensure race conditions are prevented between multiple IPC listeners and startup arg flushing; validate that startupHandlerReady flag prevents premature sending.
  • Chat Creation Merge Strategy (src/stores/useChatStore.ts): Review the explicit provider/model override semantics in createChat to confirm it correctly prioritizes incoming values over currentChat while handling empty-string edge cases.
  • Error Handling & Logging (src/renderer/components/StartupHandler.tsx, src/renderer/pages/chat/index.tsx): Verify comprehensive error handling in async flows (createChat, editStage, message submission) and confirm debug logging is sufficient for troubleshooting.
  • Dependency Arrays & Event Listeners (src/renderer/pages/chat/index.tsx): Validate that dependency arrays are complete to prevent stale closures, and confirm cleanup of event bus listeners (retry and startup-submit) prevents memory leaks.

Poem

🐇 A fluffy tale of CLI starts,
With startup args in many parts,
The renderer waits, then takes its cue,
New chats spring forth—hooray, it's true!
From prompt to chat, we leap with glee, 🎯✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and accurately summarizes the main feature added: command-line arguments for creating chats, which is the primary change across all modified files.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 7a9c592..11ab98e

✨ No bugs found, your code is sparkling clean

✅ Files analyzed, no issues (14)

.erb/scripts/wait-for-renderer.ts
docs/CLI_ARGUMENTS.md
docs/IMPLEMENTATION_SUMMARY.md
package-lock.json
package.json
src/main/cli-args.ts
src/main/main.ts
src/main/preload.ts
src/renderer/ChatContext.ts
src/renderer/components/FluentApp.tsx
src/renderer/components/StartupHandler.tsx
src/renderer/pages/chat/index.tsx
src/stores/useChatStore.ts
test/main/cli-args.spec.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements command-line arguments for automatic chat creation on startup or when launching a second instance of 5ire. It addresses feature request issue #391 by adding a CLI argument parser, IPC communication between main and renderer processes, and a React component to handle startup events.

Key changes:

  • Added CLI argument parser supporting both individual flags (--new-chat --provider openai) and JSON format (--chat '{...}')
  • Integrated argument handling into main process with queuing for pending args until renderer is ready
  • Created StartupHandler component to listen for IPC events and create chats with pre-configured settings

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
test/main/cli-args.spec.ts Comprehensive test suite covering argument parsing, normalization, and edge cases
src/main/cli-args.ts CLI argument parser with support for individual flags and JSON format
src/main/main.ts Main process integration for handling startup args on cold start and second instance
src/main/preload.ts IPC API exposed via contextBridge for startup events
src/renderer/components/StartupHandler.tsx React component handling startup events and chat creation
src/renderer/components/FluentApp.tsx Integration of StartupHandler component
src/stores/useChatStore.ts Enhanced createChat to preserve explicit provider/model overrides and debug logging
src/renderer/pages/chat/index.tsx Event bus handling for startup-submit, dependency array fixes, and model/provider tracking
src/renderer/ChatContext.ts Enhanced debug logging for provider/model resolution
package.json Added argparse dependency and moved @postlight/parser to devDependencies
docs/CLI_ARGUMENTS.md User documentation for CLI arguments
docs/IMPLEMENTATION_SUMMARY.md Technical implementation documentation
.erb/scripts/wait-for-renderer.ts Utility script to wait for renderer before starting main process

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const isReady = useMemo(() => {
return chatContext.isReady();
}, [provider, model, chatContext]);
}, [chatContext, readySignature]);
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The readySignature dependency is problematic. When provider or model changes, readySignature is recreated, causing the useMemo to re-run. However, readySignature itself is never used in the memo callback. Instead, include provider and model directly in the dependency array: [chatContext, provider, model]. This makes the intent clearer and avoids creating an intermediate variable that's not actually needed.

Suggested change
}, [chatContext, readySignature]);
}, [chatContext, provider, model]);

Copilot uses AI. Check for mistakes.
isUserScrollingRef.current = false;
};
}, []);
}, [handleScroll]);
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including handleScroll in the dependency array causes an infinite loop. The handleScroll function is defined with useCallback earlier, but it's not shown in this diff. If handleScroll changes on every render (which is likely if it doesn't have proper dependencies), this useEffect will continuously add/remove event listeners. Verify that handleScroll is properly memoized with useCallback and has stable dependencies, or remove it from this dependency array if it's stable.

Suggested change
}, [handleScroll]);
}, []);

Copilot uses AI. Check for mistakes.
setKeyword,
countInput,
countOutput,
countBlobInput,
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency countBlobInput is added to the onSubmit callback's dependency array, but countBlobInput is not visible in the diff and may not have been used in the callback before. If this function wasn't previously listed as a dependency and is now being added, ensure it's actually used within the onSubmit callback. Adding unused dependencies increases re-renders unnecessarily.

Suggested change
countBlobInput,

Copilot uses AI. Check for mistakes.
const modelCtx = chatContext.getModel();
const temperature = chatContext.getTemperature();
const maxTokens = chatContext.getMaxTokens();
let currentChat = chatContext.getActiveChat();
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The variable currentChat is declared with let and reassigned later (lines 314 and 338), which makes the control flow harder to follow. Consider refactoring to use const declarations with more descriptive names for each stage (e.g., initialChat, createdChat, updatedChat) to make the logic clearer and prevent accidental reassignment.

Suggested change
let currentChat = chatContext.getActiveChat();
const initialChat = chatContext.getActiveChat();

Copilot uses AI. Check for mistakes.
} else {
tempStage = pick(tempStage, Object.keys(defaultTempStage));
}
/* eslint-disable @typescript-eslint/no-unused-vars, no-shadow */
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The eslint-disable comment disables no-unused-vars and no-shadow for the entire IChatStore interface. Consider addressing the underlying issues rather than disabling the rules. If specific parameters or variables are intentionally unused in interface definitions, use prefixed underscores (e.g., _unused) to indicate this explicitly.

Suggested change
/* eslint-disable @typescript-eslint/no-unused-vars, no-shadow */

Copilot uses AI. Check for mistakes.
// Force UI update by setting the stage with the correct provider/model
// This ensures the ModelCtrl component displays the right values
// Use longer delay to ensure chat context fully refreshes before auto-submit
setTimeout(async () => {
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 1000ms timeout on line 90 (later line 111) is another magic number. This should be extracted to a named constant (e.g., STAGE_UPDATE_DELAY_MS = 1000) with documentation explaining why this delay is necessary for the stage update to take effect.

Copilot uses AI. Check for mistakes.
},
"devDependencies": {
"@postlight/parser": "^2.2.3",
"@axiomhq/js": "^1.0.0-rc.1",
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency @postlight/parser was moved from dependencies to devDependencies (line 99), but this change wasn't mentioned in the PR description. If this package is only used in development/testing, this is correct. However, verify that no production code imports this package. If it's used in the renderer process (which is bundled), it should remain in dependencies.

Copilot uses AI. Check for mistakes.
- When launched with startup arguments, 5ire will:
1. Create a new chat with the specified configuration
2. Navigate to the newly created chat
3. If a `--prompt` is provided, it will be set as the initial input (but not automatically sent)
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement conflicts with the implementation. Looking at StartupHandler.tsx lines 104-109, when a prompt is provided, it emits a 'startup-submit' event, which triggers auto-submission via the onSubmit callback in the chat page. Either update the documentation to accurately reflect that the prompt IS auto-submitted, or remove the auto-submit functionality from the code.

Suggested change
3. If a `--prompt` is provided, it will be set as the initial input (but not automatically sent)
3. If a `--prompt` is provided, it will be set as the initial input and automatically sent

Copilot uses AI. Check for mistakes.
const availablePort = await detectPort(port);
if (availablePort !== port) {
console.log(chalk.greenBright('✓ Renderer is ready!'));
return;
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return statement on line 32 is unnecessary after process.exit(1). The process.exit() call immediately terminates the process, so the return will never execute. Remove this redundant return statement.

Copilot uses AI. Check for mistakes.
Comment on lines +334 to 342

// Handle startup arguments first to create chat if needed
handleStartupArgs(commandLine);

// Then check for deep links (can coexist with startup args)
const deepLink = commandLine.find((arg) => arg.startsWith(`${protocol}://`));
if (deepLink) {
onDeepLink(deepLink);
}
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment mentions that startup args and deep links "can coexist", but there's no explanation of the expected behavior when both are present. Should the chat be created first, then the deep link handled? Or should one take precedence? Document the intended interaction between these two features.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (9)
.erb/scripts/wait-for-renderer.ts (2)

4-4: Consider using environment variable for port consistency.

The port is hardcoded as 1212, but check-port-in-use.js uses process.env.PORT || '1212'. For consistency across scripts, consider reading from the environment variable.

-const port = 1212;
+const port = parseInt(process.env.PORT || '1212', 10);

24-26: Remove unreachable code after process.exit(1).

The return statement on line 25 is unreachable since process.exit(1) terminates the process.

     console.log(chalk.red('✗ Renderer did not start within 60 seconds.'));
     console.log(
       chalk.yellow(
         'Please start the renderer manually with: npm run start:renderer',
       ),
     );
     process.exit(1);
-    return;
   }
test/main/cli-args.spec.ts (1)

1-194: Good test coverage!

The test suite comprehensively covers the CLI argument parsing including edge cases for malformed model strings with colons.

Consider adding a test to verify the documented behavior that --chat JSON format takes precedence over individual flags when both are provided (per docs/CLI_ARGUMENTS.md line 121).

Example test to add:

test('should prioritize --chat JSON over individual flags', () => {
  const argv = [
    'node',
    'app.js',
    '--new-chat',
    '--provider',
    'openai',
    '--chat',
    JSON.stringify({ provider: 'anthropic', model: 'claude-3' }),
  ];
  const result = parseStartupArgs(argv);
  expect(result).toEqual({
    provider: 'anthropic',
    model: 'claude-3',
  });
});
docs/IMPLEMENTATION_SUMMARY.md (1)

93-101: Add language specifier to fenced code block.

The data flow diagram code block should have a language specifier for markdown linting compliance. Since it's a text diagram, use text or plaintext.

-```
+```text
 CLI Args → parseStartupArgs() → handleStartupArgs() → IPC Event
src/renderer/components/StartupHandler.tsx (2)

90-111: Hardcoded delays may be fragile.

The nested setTimeout calls with hardcoded delays (1000ms and 500ms) are timing-based workarounds that may not be sufficient on slower systems or under heavy load. Consider using a more robust approach with event-driven coordination or retry logic.

If refactoring isn't feasible now, consider:

  1. Making the delays configurable
  2. Adding a comment explaining why these specific values were chosen
  3. Using a single combined delay or implementing a proper ready-state check

This is acceptable for the initial implementation but may cause flaky behavior in some environments.


112-116: Consider surfacing errors to the user.

The error is logged via debug() but the user receives no feedback when chat creation fails from startup arguments. For a better UX, consider showing a toast notification on failure.

} catch (error) {
  debug('Failed to create chat from startup args:', error);
  // Optionally show user feedback:
  // showToast({ message: 'Failed to create chat from startup arguments', type: 'error' });
}
src/main/preload.ts (1)

273-302: Consider extracting the duplicated type definition.

The args type definition duplicates StartupChatArgs from src/main/cli-args.ts. While preload scripts have limitations on imports, this creates maintenance burden if the interface changes.

The implementation correctly follows the existing IPC subscription pattern with proper cleanup via the returned disposer function.

Consider creating a shared types file that both modules can reference, or add a comment noting the duplication:

+  // Note: This type mirrors StartupChatArgs from cli-args.ts
   startup: {
     onNewChat(
       callback: (args: {
src/main/main.ts (1)

73-78: Redundant exit calls.

Both app.exit(0) and process.exit(0) are called. app.exit() should be sufficient as it triggers Electron's graceful shutdown. The process.exit(0) is redundant and may bypass cleanup.

 if (hasCliHelpFlag(originalArgv)) {
   console.log(CLI_HELP_TEXT);
   logging.info(CLI_HELP_TEXT);
   app.exit(0);
-  process.exit(0);
 }
src/main/cli-args.ts (1)

25-30: Consider using debug-level logging for argv.

Logging the full argv array at info level on every invocation could be noisy in production. Consider using debug level for this diagnostic output.

-  logging.info(
+  logging.debug?.(
     'parseStartupArgs received argv:',
     JSON.stringify(argv, null, 2),
   );

Or if debug isn't available, gate behind a check:

+  if (process.env.NODE_ENV === 'development') {
     logging.info(
       'parseStartupArgs received argv:',
       JSON.stringify(argv, null, 2),
     );
+  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a9c592 and 11ab98e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (13)
  • .erb/scripts/wait-for-renderer.ts (1 hunks)
  • docs/CLI_ARGUMENTS.md (1 hunks)
  • docs/IMPLEMENTATION_SUMMARY.md (1 hunks)
  • package.json (3 hunks)
  • src/main/cli-args.ts (1 hunks)
  • src/main/main.ts (7 hunks)
  • src/main/preload.ts (2 hunks)
  • src/renderer/ChatContext.ts (2 hunks)
  • src/renderer/components/FluentApp.tsx (2 hunks)
  • src/renderer/components/StartupHandler.tsx (1 hunks)
  • src/renderer/pages/chat/index.tsx (11 hunks)
  • src/stores/useChatStore.ts (4 hunks)
  • test/main/cli-args.spec.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
src/main/cli-args.ts (2)
src/main/logging.ts (1)
  • error (65-67)
.erb/scripts/remove-useless.js (1)
  • path (3-3)
src/renderer/components/StartupHandler.tsx (2)
src/main/preload.ts (1)
  • unsubscribe (234-236)
src/intellichat/types.ts (1)
  • IStage (247-258)
test/main/cli-args.spec.ts (1)
src/main/cli-args.ts (1)
  • parseStartupArgs (25-151)
src/main/main.ts (1)
src/main/cli-args.ts (2)
  • StartupChatArgs (9-16)
  • parseStartupArgs (25-151)
.erb/scripts/wait-for-renderer.ts (1)
.erb/scripts/check-port-in-use.js (1)
  • port (4-4)
src/stores/useChatStore.ts (4)
src/renderer/logging.ts (1)
  • debug (29-31)
src/intellichat/types.ts (1)
  • IChat (14-30)
src/main/preload.ts (2)
  • get (62-64)
  • get (159-161)
src/utils/util.ts (1)
  • date2unix (6-8)
src/renderer/components/FluentApp.tsx (1)
src/renderer/components/StartupHandler.tsx (1)
  • StartupHandler (15-128)
🪛 markdownlint-cli2 (0.18.1)
docs/IMPLEMENTATION_SUMMARY.md

93-93: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Agent
🔇 Additional comments (16)
src/renderer/components/FluentApp.tsx (1)

21-21: LGTM!

The StartupHandler component is correctly imported and placed inside the Router context, which is necessary for the useNavigate hook it uses. Since it renders null, there's no visual impact on the UI.

Also applies to: 141-141

src/renderer/ChatContext.ts (1)

44-52: LGTM!

The added debug statements provide useful visibility into provider/model resolution logic, which will help troubleshoot issues with the new startup argument feature. Using the debug module ensures these logs can be easily toggled on/off.

src/renderer/components/StartupHandler.tsx (1)

15-127: Overall implementation looks solid.

The component properly:

  • Uses a ref-based guard against race conditions
  • Normalizes provider/model names for case-insensitive matching
  • Cleans up the IPC listener on unmount
  • Signals readiness via IPC after mounting

The integration with the chat store and navigation is well-structured.

package.json (1)

125-125: The review comment is based on incorrect information about the package.json contents.

The dependency at line 125 of package.json is "cross-env": "^7.0.3", not argparse. The argparse package (v2.0.1) only appears in package-lock.json as a transitive dependency of js-yaml and markdown-it, both of which are legitimate dev dependencies. argparse is not a direct dependency that was added to the project, so there is no unused dependency issue here.

src/main/preload.ts (1)

41-47: LGTM - Channel types properly extended.

The new startup-handler-ready and startup-new-chat channels are correctly added to the Channels union type, following the existing pattern.

src/main/main.ts (4)

54-61: LGTM - Early argv caching is essential.

Caching process.argv before any hooks can modify it is the correct approach for handling electronmon's argument reordering. The help flag detection using a Set with lowercase comparison is efficient.


279-305: Startup args handling is well-structured.

The queue-based approach with flushStartupArgs and enqueueStartupArgs correctly handles the timing between main process startup and renderer readiness. The early return guards in flushStartupArgs prevent premature sends.


311-342: Good handling of second-instance with CLI args and deep links.

The second-instance handler correctly prioritizes showing help dialog, then processes startup args before deep links. This allows both features to coexist as documented.

Minor: Consider adding a guard to avoid processing startup args if help was shown (line 320 returns early, so this is actually fine).


430-436: IPC listeners correctly flush pending args.

Both install-tool-listener-ready and startup-handler-ready trigger flushStartupArgs(), ensuring args are sent regardless of which ready signal arrives first. This is a robust approach.

src/main/cli-args.ts (1)

160-184: LGTM - Normalization handles Provider:model format well.

The regex properly validates the format (exactly one colon with non-empty parts on both sides) and correctly preserves an explicitly provided --provider over the extracted one.

src/renderer/pages/chat/index.tsx (3)

118-121: LGTM - Ready state now reacts to provider/model changes.

Using a composite signature string ensures isReady is recalculated when provider or model changes. The nullish coalescing with empty strings handles undefined values gracefully.


683-728: LGTM - Startup-submit event handling properly integrated.

The event bus listener pattern is consistent with the retry handler. Using a local eventBusRef and cleaning up both handlers on unmount prevents memory leaks. The debug logging provides good traceability.


656-680: Dependency array is comprehensive.

The expanded dependency array correctly captures all external references used within the onSubmit callback, preventing stale closure bugs.

src/stores/useChatStore.ts (3)

50-51: ESLint suppressions are appropriate for the interface declaration.

The @typescript-eslint/no-unused-vars and no-shadow rules can incorrectly flag interface method parameters. The scoped disable/enable pattern is clean.

Also applies to: 120-120


374-389: createChat merge strategy correctly prioritizes explicit arguments.

The change from using chat directly to merging onto currentChat with explicit undefined checks for provider/model allows:

  1. Inheriting current state when no value provided
  2. Overriding with any value (including empty string) when explicitly passed

This is important for the startup args flow where provider/model should be honored even if they differ from current stage.


542-543: Debug logging improvements aid troubleshooting.

Adding provider/model to the fetchChat debug output helps trace where chat configuration values originate, which is useful given the new startup args flow.

Comment on lines +111 to +112
3. If a `--prompt` is provided, it will be set as the initial input (but not automatically sent)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Documentation contradicts implementation behavior.

The documentation states the prompt "will be set as the initial input (but not automatically sent)". However, reviewing src/renderer/components/StartupHandler.tsx (lines 103-110), the implementation explicitly auto-submits the prompt via eventBus.emit('startup-submit', args.prompt).

Update the documentation to reflect the actual behavior:

-- If a `--prompt` is provided, it will be set as the initial input (but not automatically sent)
+  3. If a `--prompt` is provided, it will be automatically submitted

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In docs/CLI_ARGUMENTS.md around lines 111 to 112, the documentation incorrectly
says a provided --prompt is set as initial input but not automatically sent; in
reality StartupHandler.tsx (lines 103–110) emits eventBus.emit('startup-submit',
args.prompt) which auto-submits the prompt. Update the documentation text to
state that when --prompt is provided it will be automatically submitted on
startup (mentioning the startup-submit event for clarity) and remove the "(but
not automatically sent)" clause so the docs match the implementation.

Comment on lines +47 to +52
ipcMain.on('install-tool-listener-ready', () => {
if (pendingStartupArgs !== null) {
mainWindow?.webContents.send('startup-new-chat', pendingStartupArgs);
pendingStartupArgs = null;
}
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

IPC channel name mismatch.

The documentation references install-tool-listener-ready but src/renderer/components/StartupHandler.tsx (line 119) sends startup-handler-ready. Update the documentation to match the implementation.

-// Send pending args when renderer is ready
-ipcMain.on('install-tool-listener-ready', () => {
+// Send pending args when startup handler is ready
+ipcMain.on('startup-handler-ready', () => {
   if (pendingStartupArgs !== null) {

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In docs/IMPLEMENTATION_SUMMARY.md around lines 47 to 52 the IPC channel name is
incorrect: the doc shows "install-tool-listener-ready" but the renderer actually
sends "startup-handler-ready" (see src/renderer/components/StartupHandler.tsx
line 119); update the documentation to use "startup-handler-ready" (leave the
rest of the snippet including the "startup-new-chat" send call unchanged) so the
docs match the implementation.

Comment on lines +37 to +53
// Handle --chat JSON format
const chatIndex = argv.indexOf('--chat');
if (chatIndex !== -1) {
try {
// Find the next non-flag argument after --chat
for (let i = chatIndex + 1; i < argv.length; i += 1) {
const arg = argv[i];
if (!arg.startsWith('--') && !arg.endsWith('.js') && arg !== '.') {
const parsed = JSON.parse(arg);
return normalizeStartupArgs(parsed);
}
}
} catch (error) {
logging.error('Failed to parse --chat JSON argument:', error);
return null;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

JSON parsing for --chat may skip valid JSON argument.

The loop at line 42 searches for a non-flag argument after --chat, but if electronmon scrambles args such that another flag appears between --chat and its value, this could fail silently. The current fallback to manual parsing should handle this, but the try-catch returns null on parse failure rather than falling through to manual parsing.

Consider falling through to manual parsing on JSON parse failure instead of returning null:

     } catch (error) {
       logging.error('Failed to parse --chat JSON argument:', error);
-      return null;
+      // Fall through to manual parsing
     }
   }
+
+  // If --chat was present but JSON parsing failed, continue with manual parsing
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Handle --chat JSON format
const chatIndex = argv.indexOf('--chat');
if (chatIndex !== -1) {
try {
// Find the next non-flag argument after --chat
for (let i = chatIndex + 1; i < argv.length; i += 1) {
const arg = argv[i];
if (!arg.startsWith('--') && !arg.endsWith('.js') && arg !== '.') {
const parsed = JSON.parse(arg);
return normalizeStartupArgs(parsed);
}
}
} catch (error) {
logging.error('Failed to parse --chat JSON argument:', error);
return null;
}
}
// Handle --chat JSON format
const chatIndex = argv.indexOf('--chat');
if (chatIndex !== -1) {
try {
// Find the next non-flag argument after --chat
for (let i = chatIndex + 1; i < argv.length; i += 1) {
const arg = argv[i];
if (!arg.startsWith('--') && !arg.endsWith('.js') && arg !== '.') {
const parsed = JSON.parse(arg);
return normalizeStartupArgs(parsed);
}
}
} catch (error) {
logging.error('Failed to parse --chat JSON argument:', error);
// Fall through to manual parsing
}
}
// If --chat was present but JSON parsing failed, continue with manual parsing
🤖 Prompt for AI Agents
In src/main/cli-args.ts around lines 37 to 53, the current handling of --chat
returns null inside the catch when JSON.parse fails, preventing the code from
falling back to the subsequent manual parsing path; change the catch to log the
parse error but do NOT return — allow execution to continue so the existing
manual parsing logic can run as a fallback; ensure the try only surrounds the
JSON.parse and parsed normalization, and after catching the error simply
break/continue out of the inner loop (or continue outer flow) so the function
falls through to manual parsing instead of exiting early.

Comment on lines +113 to +146
// Match flags to values by position
const args: StartupChatArgs = {};

for (let i = 0; i < foundFlags.length && i < values.length; i += 1) {
const flag = foundFlags[i];
const value = values[i];

switch (flag) {
case '--provider':
args.provider = value;
break;
case '--model':
args.model = value;
break;
case '--system':
args.system = value;
break;
case '--summary':
args.summary = value;
break;
case '--prompt':
args.prompt = value;
break;
case '--temperature': {
const temp = parseFloat(value);
if (!Number.isNaN(temp)) {
args.temperature = temp;
}
break;
}
default:
break;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for electronmon references in the codebase
rg -i "electronmon" -n -B2 -A2

Repository: nanbingxyz/5ire

Length of output: 2378


🏁 Script executed:

#!/bin/bash
# Search for the cli-args.ts file and examine its content
fd "cli-args.ts" --exec wc -l {}

Repository: nanbingxyz/5ire

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Look for foundFlags and values array population
rg -n "foundFlags\s*=" src/main/cli-args.ts -A3 -B3

Repository: nanbingxyz/5ire

Length of output: 119


🏁 Script executed:

#!/bin/bash
# Find cli-args.ts file
fd "cli-args\.ts" -type f

Repository: nanbingxyz/5ire

Length of output: 229


🏁 Script executed:

#!/bin/bash
# List the directory structure to understand the layout
git ls-files | grep -E "\.(ts|js)$" | head -30

Repository: nanbingxyz/5ire

Length of output: 936


🏁 Script executed:

#!/bin/bash
# Search for cli-args.ts more broadly
fd "cli-args"

Repository: nanbingxyz/5ire

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Check if the file exists in any form
find . -name "*cli-args*" 2>/dev/null

Repository: nanbingxyz/5ire

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Check git status and branch
git status
git branch -a

Repository: nanbingxyz/5ire

Length of output: 409


🏁 Script executed:

#!/bin/bash
# Search for StartupChatArgs type definition which is referenced in the code snippet
rg "StartupChatArgs" -n

Repository: nanbingxyz/5ire

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Search for the pattern of matching flags to values
rg "foundFlags" -n -B2 -A2

Repository: nanbingxyz/5ire

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Checkout the PR branch
git checkout coderabbit_392
git log --oneline -5

Repository: nanbingxyz/5ire

Length of output: 478


🏁 Script executed:

#!/bin/bash
# Now search for the files and patterns
rg "StartupChatArgs" -n
fd "cli-args"

Repository: nanbingxyz/5ire

Length of output: 840


🏁 Script executed:

#!/bin/bash
# Read the cli-args.ts file to understand the implementation
cat -n src/main/cli-args.ts

Repository: nanbingxyz/5ire

Length of output: 6189


🏁 Script executed:

#!/bin/bash
# Read the test file to understand how this is being tested
cat -n test/main/cli-args.spec.ts

Repository: nanbingxyz/5ire

Length of output: 6860


🏁 Script executed:

#!/bin/bash
# Check for any other references to electronmon in the codebase
rg "electronmon" -n -B2 -A2

Repository: nanbingxyz/5ire

Length of output: 2916


🌐 Web query:

electronmon npm package argument handling behavior

💡 Result:

Short answer: electronmon forwards CLI arguments to the Electron process unchanged (you can also supply an args array via the JS API). If you run electronmon from an npm script, use the usual double-dash (--) to separate npm/script flags from app arguments so they reach Electron via process.argv. (npmjs.com)

Citations:


🏁 Script executed:

#!/bin/bash
# Search for any GitHub issues or comments discussing electronmon argument scrambling
rg -i "scramble|scrambl" -n -B3 -A3

Repository: nanbingxyz/5ire

Length of output: 421


🏁 Script executed:

#!/bin/bash
# Check git history for this file to understand why this approach was taken
git log --oneline --all -- src/main/cli-args.ts

Repository: nanbingxyz/5ire

Length of output: 508


🏁 Script executed:

#!/bin/bash
# Check if there are any comments or issues in the repo about electronmon
rg -i "electronmon" --type md -A5 -B5

Repository: nanbingxyz/5ire

Length of output: 41


electronmon does not scramble arguments; it forwards them unchanged

Based on verification, electronmon's official documentation states it "forwards CLI arguments to the Electron process unchanged." The code comment claiming "electronmon's scrambled argument order" appears to be incorrect.

However, the review's underlying concern remains valid: the positional matching strategy (collecting all flags separately, then all values, then matching by position) is fragile and lacks validation. While the current implementation works with normal argument order, it's unnecessarily complex and relies on an unverified assumption about electronmon's behavior.

Suggested improvements:

  • Verify the actual need for this strategy by testing electronmon's actual argument handling
  • Add validation to detect when the number of flags doesn't match values
  • Consider a more direct approach of matching each flag to the immediately following value (standard CLI parsing)
  • Correct the misleading comment about "scrambled" arguments

The existing debug logging (lines 110-111, 148) is helpful but insufficient—add explicit validation or error handling for mismatches.

🤖 Prompt for AI Agents
In src/main/cli-args.ts around lines 113 to 146, the comment about
"electronmon's scrambled argument order" is incorrect and the current positional
matching (collecting flags and values separately then matching by index) is
fragile; replace the comment, add validation to detect mismatched counts, and
simplify parsing by iterating through the original argv sequence so each flag is
matched to its immediate following value (the standard CLI pattern).
Specifically: remove or correct the misleading comment, check that the number of
discovered flags equals the number of values and log an explicit error/throw if
they differ, and refactor the loop to walk argv once assigning the next token as
the value for a recognized flag (with the same conversions/validation for
temperature), falling back to clear error handling when a value is missing.
Ensure existing debug logs are preserved and augmented with the validation
failure message.

Comment on lines +317 to +336
const shouldUpdateProvider =
!currentChat.provider || currentChat.provider === providerCtx.name;
const shouldUpdateModel =
!currentChat.model || currentChat.model === modelCtx.name;

if (shouldUpdateProvider && shouldUpdateModel) {
await updateChat({
id: activeChatId,
provider: providerCtx.name,
model: modelCtx.name,
temperature,
summary,
});
} else {
await updateChat({
id: activeChatId,
temperature,
summary,
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inverted or confusing condition logic for provider/model updates.

The variable names shouldUpdateProvider and shouldUpdateModel suggest these should be true when an update is needed. However, the conditions check if the current value is empty OR equals the new value, which would be true when no update is needed (values already match).

This appears to preserve provider/model from the first message, but the naming is misleading.

Consider renaming for clarity:

-          const shouldUpdateProvider =
-            !currentChat.provider || currentChat.provider === providerCtx.name;
-          const shouldUpdateModel =
-            !currentChat.model || currentChat.model === modelCtx.name;
+          const canOverrideProvider =
+            !currentChat.provider || currentChat.provider === providerCtx.name;
+          const canOverrideModel =
+            !currentChat.model || currentChat.model === modelCtx.name;

-          if (shouldUpdateProvider && shouldUpdateModel) {
+          if (canOverrideProvider && canOverrideModel) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const shouldUpdateProvider =
!currentChat.provider || currentChat.provider === providerCtx.name;
const shouldUpdateModel =
!currentChat.model || currentChat.model === modelCtx.name;
if (shouldUpdateProvider && shouldUpdateModel) {
await updateChat({
id: activeChatId,
provider: providerCtx.name,
model: modelCtx.name,
temperature,
summary,
});
} else {
await updateChat({
id: activeChatId,
temperature,
summary,
});
}
const canOverrideProvider =
!currentChat.provider || currentChat.provider === providerCtx.name;
const canOverrideModel =
!currentChat.model || currentChat.model === modelCtx.name;
if (canOverrideProvider && canOverrideModel) {
await updateChat({
id: activeChatId,
provider: providerCtx.name,
model: modelCtx.name,
temperature,
summary,
});
} else {
await updateChat({
id: activeChatId,
temperature,
summary,
});
}
🤖 Prompt for AI Agents
In src/renderer/pages/chat/index.tsx around lines 317 to 336, the booleans
shouldUpdateProvider and shouldUpdateModel are inverted/misnamed: they are true
when the current chat provider/model is empty or already equals the new value
(i.e., no update needed). Change the logic (or rename variables) so they are
true only when the stored value differs from the new value (meaning an update is
required), then call updateChat with provider and model when those flags
indicate a change; otherwise call updateChat without provider/model. Ensure
variable names match the semantics (e.g., needsProviderUpdate/needsModelUpdate)
and update the conditional that decides which fields to include in the update
accordingly.

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

@Lilili14333
Copy link
Copy Markdown

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Copy link
Copy Markdown

@recurseml recurseml bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by RecurseML

🔍 Review performed on 11ab98e..11ab98e

✨ No files to analyze

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants