( root: Root, permissionMode: PermissionMode, allowDangerouslySkipPermissions: boolean, commands?: Command[], claudeInChrome?: boolean, devChannels?: ChannelEntry[], )
| 129 | } |
| 130 | |
| 131 | export async function showSetupScreens( |
| 132 | root: Root, |
| 133 | permissionMode: PermissionMode, |
| 134 | allowDangerouslySkipPermissions: boolean, |
| 135 | commands?: Command[], |
| 136 | claudeInChrome?: boolean, |
| 137 | devChannels?: ChannelEntry[], |
| 138 | ): Promise<boolean> { |
| 139 | if ( |
| 140 | process.env.NODE_ENV === 'test' || |
| 141 | isEnvTruthy(false) || |
| 142 | process.env.IS_DEMO // Skip onboarding in demo mode |
| 143 | ) { |
| 144 | return false; |
| 145 | } |
| 146 | |
| 147 | const config = getGlobalConfig(); |
| 148 | let onboardingShown = false; |
| 149 | if ( |
| 150 | !config.theme || |
| 151 | !config.hasCompletedOnboarding // always show onboarding at least once |
| 152 | ) { |
| 153 | onboardingShown = true; |
| 154 | const { Onboarding } = await import('./components/Onboarding.js'); |
| 155 | await showSetupDialog( |
| 156 | root, |
| 157 | done => ( |
| 158 | <Onboarding |
| 159 | onDone={() => { |
| 160 | completeOnboarding(); |
| 161 | void done(); |
| 162 | }} |
| 163 | /> |
| 164 | ), |
| 165 | { onChangeAppState }, |
| 166 | ); |
| 167 | } |
| 168 | |
| 169 | // Always show the trust dialog in interactive sessions, regardless of permission mode. |
| 170 | // The trust dialog is the workspace trust boundary — it warns about untrusted repos |
| 171 | // and checks CLAUDE.md external includes. bypassPermissions mode |
| 172 | // only affects tool execution permissions, not workspace trust. |
| 173 | // Note: non-interactive sessions (CI/CD with -p) never reach showSetupScreens at all. |
| 174 | // Skip permission checks in claubbit |
| 175 | if (!isEnvTruthy(process.env.CLAUBBIT)) { |
| 176 | // Fast-path: skip TrustDialog import+render when CWD is already trusted. |
| 177 | // If it returns true, the TrustDialog would auto-resolve regardless of |
| 178 | // security features, so we can skip the dynamic import and render cycle. |
| 179 | if (!checkHasTrustDialogAccepted()) { |
| 180 | const { TrustDialog } = await import('./components/TrustDialog/TrustDialog.js'); |
| 181 | await showSetupDialog(root, done => <TrustDialog commands={commands} onDone={done} />); |
| 182 | } |
| 183 | |
| 184 | // Signal that trust has been verified for this session. |
| 185 | // GrowthBook checks this to decide whether to include auth headers. |
| 186 | setSessionTrustAccepted(true); |
| 187 | |
| 188 | // Reset and reinitialize GrowthBook after trust is established. |
no test coverage detected