Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion __tests__/e2e/__snapshots__/happy-path.e2e.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ exports[`happy-path flow > navigates Welcome → SystemCheck → Authenticate
warehouse setup, migrations, and onboarding — so it can help ● Sign in to Confidence
without searching the docs. ▶ Set up your agent
○ Connect tools
○ Onboard project
◆ Cursor and Codex require full file system access to run ○ Onboard project
onboarding.


──────────────────────────────────────────────────────────────────────────────────────────────────
Expand Down
9 changes: 6 additions & 3 deletions __tests__/e2e/__snapshots__/stale-auth.e2e.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ exports[`when auth token is stale > allows re-authentication after expired token
warehouse setup, migrations, and onboarding — so it can help ● Sign in to Confidence
without searching the docs. ▶ Set up your agent
○ Connect tools
○ Onboard project
◆ Cursor and Codex require full file system access to run ○ Onboard project
onboarding.


──────────────────────────────────────────────────────────────────────────────────────────────────
Expand All @@ -31,7 +32,8 @@ exports[`when auth token is stale > allows signing in after failed refresh and p
warehouse setup, migrations, and onboarding — so it can help ● Sign in to Confidence
without searching the docs. ▶ Set up your agent
○ Connect tools
○ Onboard project
◆ Cursor and Codex require full file system access to run ○ Onboard project
onboarding.


──────────────────────────────────────────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -93,7 +95,8 @@ exports[`when auth token is stale > refreshes and authenticates when choosing ex
warehouse setup, migrations, and onboarding — so it can help ● Sign in to Confidence
without searching the docs. ▶ Set up your agent
○ Connect tools
○ Onboard project
◆ Cursor and Codex require full file system access to run ○ Onboard project
onboarding.


──────────────────────────────────────────────────────────────────────────────────────────────────
Expand Down
7 changes: 7 additions & 0 deletions __tests__/ui/screens/InstallPluginsScreen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ describe('InstallPluginsScreen', () => {
});
});

it('shows file system access warning during IDE selection', async () => {
using sut = renderScreen(<InstallPluginsScreen />, { screen: ScreenId.InstallPlugins });
await waitFor(() => {
expect(sut.lastFrame()).toContain('full file system access');
});
});

it('installs plugin and shows success', async () => {
using project = createProjectDir();
using sut = renderScreen(<InstallPluginsScreen />, {
Expand Down
49 changes: 49 additions & 0 deletions __tests__/ui/screens/OnboardingFlow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,55 @@ describe('Onboarding flow', () => {
});
});

describe('IDE-specific sandbox warning', () => {
it('shows standard warning when IDE is Claude Code', async () => {
using project = createProjectDir();

using sut = renderScreen(<OnboardProjectScreen />, {
screen: ScreenId.OnboardProject,
dir: project.path,
ide: 'claude',
goals: ['feature-flags'],
});

await waitFor(() => {
const frame = sut.lastFrame()!;
expect(frame).toContain('run commands, install packages');
expect(frame).not.toContain('entire file system');
});
});

it('shows elevated warning when IDE is Cursor', async () => {
using project = createProjectDir();

using sut = renderScreen(<OnboardProjectScreen />, {
screen: ScreenId.OnboardProject,
dir: project.path,
ide: 'cursor',
goals: ['feature-flags'],
});

await waitFor(() => {
expect(sut.lastFrame()).toContain('entire file system');
});
});

it('shows elevated warning when IDE is Codex', async () => {
using project = createProjectDir();

using sut = renderScreen(<OnboardProjectScreen />, {
screen: ScreenId.OnboardProject,
dir: project.path,
ide: 'codex',
goals: ['feature-flags'],
});

await waitFor(() => {
expect(sut.lastFrame()).toContain('entire file system');
});
});
});

describe('selected goal display', () => {
it('shows feature flag steps when goal is feature-flags', async () => {
using project = createProjectDir();
Expand Down
8 changes: 8 additions & 0 deletions src/ui/tui/screens/install-plugins/components/MainContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ export function MainContent({ phase, detected, error }: MainContentProps) {
</Text>
</Box>

{phase === 'choose-ide' && (
<Box marginBottom={1}>
<Text color={Colors.warning}>
{Icons.diamond} Cursor and Codex require full file system access to run onboarding.
</Text>
</Box>
)}

{phase === 'detecting' && <Spinner label="Checking for Confidence AI plugins..." />}

{phase === 'already-installed' && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export function OnboardProjectScreen() {
statusLines={onboarding.statusLines}
error={onboarding.error}
goals={session.onboardingGoals}
ide={session.ide}
showTips={showTips}
tip={tip}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@ import { Spinner } from '@inkjs/ui';
import { Colors, Emoji, Icons } from '../../../styles.js';
import { StatusFeed } from '../../../components/StatusFeed.js';
import { TipCard } from '../../../components/TipCard.js';
import type { OnboardingGoal } from '@shared-kernel/types.js';
import type { IdeId, OnboardingGoal } from '@shared-kernel/types.js';
import type { OnboardingPhase } from '../useOnboardingProcess.js';
import type { StatusLine } from '../../../lib/status-line.js';
import type { Tip } from '../../../lib/tips.js';

export const MAX_VISIBLE_STATUS = 3;

const SANDBOX_WARNING =
'The AI agent will be able to run commands, install packages, and modify files in your project.';

type OnboardingLeftPanelProps = {
phase: OnboardingPhase;
statusLines: StatusLine[];
error: string | null;
goals: OnboardingGoal[];
ide: IdeId | null;
showTips: boolean;
tip: Tip;
};
Expand All @@ -27,6 +25,7 @@ export function OnboardingLeftPanel({
statusLines,
error,
goals,
ide,
showTips,
tip,
}: OnboardingLeftPanelProps) {
Expand All @@ -50,7 +49,7 @@ export function OnboardingLeftPanel({
</Box>
<Box marginBottom={1}>
<Text color={Colors.warning}>
{Icons.diamond} {SANDBOX_WARNING}
{Icons.diamond} {sandboxWarning(ide)}
</Text>
</Box>
</>
Expand Down Expand Up @@ -97,3 +96,14 @@ const GOAL_STEPS: Record<OnboardingGoal, string[]> = {
function onboardingSteps(goals: OnboardingGoal[]): string[] {
return ['add the Confidence SDK', ...goals.flatMap((g) => GOAL_STEPS[g])];
}

const WARNING_MSG = {
sandbox:
'The AI agent will be able to run commands, install packages, and modify files in your project.',
relaxed:
'The AI agent will have access to your entire file system as well as run commands and install packages in your project.',
} as const;

function sandboxWarning(ide: IdeId | null): string {
return ide === 'claude' ? WARNING_MSG.sandbox : WARNING_MSG.relaxed;
}