feat(pty): add shellSetup command for per-project terminal initialization#992
Conversation
|
@chrishoffman is attempting to deploy a commit to the General Action Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryAdds Implementation:
Key behavior:
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| src/main/services/LifecycleScriptsService.ts | Added getShellSetup() method to read shellSetup config from .emdash.json - clean implementation following existing patterns |
| src/main/services/ptyIpc.ts | Added resolveShellSetup() helper to look up shellSetup from worktree or project root, properly handles both committed and uncommitted configs |
| src/main/services/ptyManager.ts | Integrated shellSetup into PTY spawn logic for both provider CLIs and regular shells - uses && for providers and ; for shells, then execs back into shell |
| src/renderer/components/ConfigEditorModal.tsx | Added UI input field for shellSetup with proper state management, validation, and JSON serialization |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User configures shellSetup in .emdash.json] --> B[PTY spawn requested]
B --> C[resolveShellSetup reads config]
C --> D{Config found?}
D -->|Yes| E[Pass shellSetup to startPty]
D -->|No| F[Start PTY without shellSetup]
E --> G{Provider CLI or plain shell?}
G -->|Provider CLI| H[Run: shellSetup && cli_command; exec shell]
G -->|Plain shell| I[Run: shellSetup; exec shell -il]
H --> J[Agent terminal ready]
I --> J
F --> K[Start shell with -il flags]
K --> J
Last reviewed commit: e41fdcc
| const chainCommand = shellSetup | ||
| ? `${shellSetup} && ${commandString}; exec ${resumeShell}` | ||
| : `${commandString}; exec ${resumeShell}`; |
There was a problem hiding this comment.
shellSetup is interpolated directly into shell command without escaping, creating command injection risk if .emdash.json is compromised
The shellSetup string from user config is concatenated directly into shell commands. While .emdash.json is a project config file, if it's compromised (e.g., malicious PR, supply chain attack), the arbitrary shell command executes with user privileges. Consider escaping using quoteShellArg() from src/main/utils/shellEscape.ts, or add validation/warnings in the config editor since this is inherently dangerous.
| const chainCommand = shellSetup | |
| ? `${shellSetup} && ${commandString}; exec ${resumeShell}` | |
| : `${commandString}; exec ${resumeShell}`; | |
| const escapedShellSetup = shellSetup ? quoteShellArg(shellSetup) : null; | |
| const chainCommand = escapedShellSetup | |
| ? `${escapedShellSetup} && ${commandString}; exec ${resumeShell}` | |
| : `${commandString}; exec ${resumeShell}`; |
| if (shellSetup) { | ||
| const cFlag = base === 'fish' ? '-ic' : base === 'sh' ? '-lc' : '-lic'; | ||
| const resumeShell = `'${useShell.replace(/'/g, "'\\''")}' -il`; | ||
| args.push(cFlag, `${shellSetup}; exec ${resumeShell}`); |
There was a problem hiding this comment.
Same command injection issue here - shellSetup needs escaping
| if (shellSetup) { | |
| const cFlag = base === 'fish' ? '-ic' : base === 'sh' ? '-lc' : '-lic'; | |
| const resumeShell = `'${useShell.replace(/'/g, "'\\''")}' -il`; | |
| args.push(cFlag, `${shellSetup}; exec ${resumeShell}`); | |
| if (shellSetup) { | |
| const cFlag = base === 'fish' ? '-ic' : base === 'sh' ? '-lc' : '-lic'; | |
| const resumeShell = `'${useShell.replace(/'/g, "'\\''")}' -il`; | |
| args.push(cFlag, `${quoteShellArg(shellSetup)}; exec ${resumeShell}`); |
|
Nice addition and clean implementation @chrishoffman Thanks! |
Adds a
shellSetupfield to.emdash.jsonthat runs a shell command in every terminal (agent and plain) before the session starts. Useful for activating virtual environments, switching Node versions, or any other per-project shell setup.The original inspiration is to prevent the spinning that that the agents do to figure out how to configure your environment. This could be done manually in the launch terminal but there was no way to configure it in the agent terminal.
Here is my setup for emdash:
