Skip to content

Expand vfs#133

Merged
kiliantyler merged 25 commits intomainfrom
expand-vfs
Oct 10, 2025
Merged

Expand vfs#133
kiliantyler merged 25 commits intomainfrom
expand-vfs

Conversation

@kiliantyler
Copy link
Copy Markdown
Collaborator

@kiliantyler kiliantyler commented Oct 10, 2025

Summary by CodeRabbit

  • New Features

    • Secret Console: added clear, tree, uptime, and confetti commands with confetti subcommand completion.
    • Draggable console resize, session persistence for entries/history/cwd/height, and cwd-aware prompts with tilde expansion.
    • Expanded virtual filesystem with richer directories, dynamic content, file metadata/stat, and theme/achievement-derived files.
    • Global confetti trigger via a browser event.
  • Bug Fixes

    • cat, head, tail, and wc now detect and block binary files.
  • Tests

    • Updated and added suites covering clear, tree, uptime, VFS/path resolution, completion, and many command behaviors.

Greatly expands the virtual file system (VFS) to provide a richer and more realistic console experience.

Implements dynamic content generation for VFS files and directories, reflecting real-time application state (e.g., themes, achievements).

Adds support for tilde (`~`) expansion in all VFS path operations, including `cd`, `ls`, `cat`, and tab completion. Enhances the console prompt to display the current working directory in a more familiar `~` format.

Refactors VFS utility functions into a new module and updates all relevant console command tests.
@vercel
Copy link
Copy Markdown

vercel bot commented Oct 10, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
kil-dev Ready Ready Preview Comment Oct 10, 2025 2:34am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 10, 2025

📝 Walkthrough

Walkthrough

Adds confetti event handling and a confetti console command. Persists and resizes the secret console UI with cwd-aware prompts. Reworks VFS resolution, dynamic content, and stats. Adds new console commands (clear, tree, uptime), binary-file guards across readers, type updates, and multiple test adjustments to the new VFS and behaviors.

Changes

Cohort / File(s) Summary
Confetti integration
src/components/providers/confetti-provider.tsx, src/utils/console/confetti.ts, src/utils/console/completion.ts
Adds window listener for kd:trigger-confetti and validation; wires provider triggers for types (default,corners,top,center). Adds confetti console command that dispatches the CustomEvent and exposes subcommand completion; completion module extended to support confetti subcommands.
Secret console UI & session state
src/components/secret-console/secret-console.tsx, src/lib/storage-keys.ts
Persists entries, history, cwd, and height to sessionStorage (new SESSION_STORAGE_KEYS). Adds draggable height-resize UI, cwd-aware prompts and tilde formatting, per-entry cwd, safe sessionStorage parsing/clear on corruption, and exposes clearOutput on the console env.
VFS core & data
src/utils/secret-console-vfs.ts, src/lib/secret-console-files.ts, src/types/secret-console.d.ts
Reworks VFS: normalizePath with tilde/relative resolution, dynamic children/content (functions), vfsStat returning size/binary/executable, makeBinaryFile and binChildren, theme/achievement dynamic content helpers, and a much-expanded SECRET_CONSOLE_VFS tree. Types updated: VfsFileNode, VfsDirNode, VfsNode, VfsStat; SecretConsoleEnv gains stat and clearOutput.
New commands & registry
src/utils/console/clear.ts, src/utils/console/tree.ts, src/utils/console/uptime.ts, src/utils/console/index.ts
Adds clear (clears console output), tree (directory tree with -L/-d), and uptime (since load + loadavg); registers these commands in the console index.
Binary-file guards & command changes
src/utils/console/cat.ts, src/utils/console/head.ts, src/utils/console/tail.ts, src/utils/console/wc.ts, src/utils/console/uname.ts
Adds env.stat-based binary-file guards to cat/head/tail/wc to short-circuit on binaries. uname now sources /etc/os-release and /etc/hostname and derives machine from navigator info.
Tests & test utilities
src/utils/console/__tests__/*, src/utils/console/__tests__/test-utils.ts
Tests adjusted for new VFS layout and looser content assertions; new tests for clear/tree/uptime. Test utils now use shared SECRET_CONSOLE_VFS, normalizePath/vfsStat helpers, and createMockEnv returns env plus output and getCloseRequested.
Completion improvements
src/utils/console/completion.ts
Adds completion mode for confetti subcommands using getConfettiSubcommands and integrates it into computeTabCompletion.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Console as SecretConsole (command)
  participant Window as window
  participant Provider as ConfettiProvider
  participant Engine as ConfettiEngine

  User->>Console: confetti <type>
  Console->>Window: dispatch CustomEvent("kd:trigger-confetti", { detail: { type } })
  Note right of Window: Browser-only dispatch (guarded)
  Window-->>Provider: kd:trigger-confetti event
  Provider->>Provider: validate CustomEvent & detail.type is string
  alt type in {default,corners,top,center}
    Provider->>Engine: trigger[type]()
  else invalid type
    Provider->>Provider: console.warn("Unexpected confetti type")
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed “Expand vfs” accurately describes the significant expansion of the virtual file system hierarchy and new VFS utilities added in this pull request, anchoring it in a real and substantial aspect of the change. Though the PR also adds various console commands and state persistence features, the VFS expansion is a clear focal point. The title is concise and specific enough for a teammate to quickly understand the primary enhancement.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch expand-vfs

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

Copy link
Copy Markdown
Contributor

@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: 1

♻️ Duplicate comments (3)
src/utils/console/tail.ts (1)

33-37: Binary file guard is duplicated.

This guard is identical to the one in cat.ts (lines 13-17). See the refactoring suggestion in the review comment for cat.ts to extract this shared logic.

src/utils/console/head.ts (1)

33-37: Binary file guard is duplicated.

This guard is identical to the ones in cat.ts (lines 13-17) and tail.ts (lines 33-37). See the refactoring suggestion in the review comment for cat.ts to extract this shared logic.

src/utils/console/wc.ts (1)

13-17: Binary file guard is duplicated.

This guard is identical to the ones in cat.ts (lines 13-17), head.ts (lines 33-37), and tail.ts (lines 33-37). See the refactoring suggestion in the review comment for cat.ts to extract this shared logic.

🧹 Nitpick comments (10)
src/utils/console/__tests__/cd.test.ts (1)

28-30: Add assertions: ensure target is a file and cwd remains unchanged

Verify the error case more thoroughly by asserting the target is a file and that cwd didn’t change.

   it('shows error when target is not a directory', () => {
     const { env, output } = createMockEnv()
     cd.execute(['/home/kil/.bashrc'], env)
     expect(output).toEqual([formatCdNotDirectory('/home/kil/.bashrc')])
+    // Optional: strengthen the test
+    expect(env.stat('/home/kil/.bashrc')?.kind).toBe('file')
+    expect(env.pwd()).toBe('/home/kil')
   })
src/utils/console/uname.ts (2)

23-33: Fix architecture detection to avoid mislabeling Intel Macs

Using “mac OR arm ⇒ aarch64” labels Intel Macs as aarch64. Prefer checking for arm/aarch hints, otherwise default to x86_64.

-  const machine = (() => {
-    if (typeof navigator === 'undefined') return ''
-    const nav: Navigator & { userAgentData?: { platform?: string } } = navigator
-    const platform = nav.userAgentData?.platform ?? nav.platform ?? ''
-    const p = platform.toLowerCase()
-    return p.includes('mac') || p.includes('arm') ? 'aarch64' : 'x86_64'
-  })()
+  const machine = (() => {
+    if (typeof navigator === 'undefined') return ''
+    const nav: Navigator & { userAgentData?: { platform?: string } } = navigator
+    const platform = (nav.userAgentData?.platform ?? nav.platform ?? '').toLowerCase()
+    const ua = (nav.userAgent ?? '').toLowerCase()
+    const hints = `${platform} ${ua}`
+    return /arm|aarch/.test(hints) || /apple\s?silicon/.test(hints) ? 'aarch64' : 'x86_64'
+  })()

38-38: Avoid extra spaces when some fields are missing

Join non-empty parts for -a output to prevent double spaces.

-    env.appendOutput(`${sysname} ${nodename} ${release} ${version} ${machine}`)
+    env.appendOutput([sysname, nodename, release, version, machine].filter(Boolean).join(' '))
src/utils/secret-console-vfs.ts (4)

11-15: Centralize home path for tilde expansion

Minor: extract '/home/kil' into a constant to avoid scattering literals and ease future changes.

+const HOME_DIR = '/home/kil'
 ...
-  if (path === '~' || path.startsWith('~/')) {
-    expandedPath = path.replace(/^~/, '/home/kil')
+  if (path === '~' || path.startsWith('~/')) {
+    expandedPath = path.replace(/^~/, HOME_DIR)
   }

71-83: Make vfsStat size computation resilient across environments

TextEncoder may be unavailable in some runtimes; add safe fallbacks.

-  const size = new TextEncoder().encode(content).length
+  const size = (() => {
+    try {
+      if (typeof TextEncoder !== 'undefined') return new TextEncoder().encode(content).length
+    } catch {}
+    // Node fallback
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore Buffer may not exist in browsers
+    if (typeof Buffer !== 'undefined' && typeof Buffer.byteLength === 'function') {
+      // @ts-ignore
+      return Buffer.byteLength(content)
+    }
+    return content.length
+  })()

85-91: Use proper ELF magic byte

Use 0x7F "ELF" instead of NUL prefix.

   return {
     type: 'file',
-    content: '\u0000ELF\n',
+    content: '\x7FELF\n',
     meta: { binary: true, executable: true },
   } as VfsNode

93-116: Guard getAvailableThemes to avoid storage-related failures

If theme helpers touch localStorage and throw, this file’s content generation could fail. Wrap in try/catch and degrade gracefully.

 export function getThemeCacheContent(): string {
   let activeTheme = 'system'
   try {
     if (typeof localStorage !== 'undefined') {
       activeTheme = localStorage.getItem(LOCAL_STORAGE_KEYS.THEME) ?? 'system'
     }
   } catch {
     // localStorage not available
   }
-  const availableThemes = getAvailableThemes()
+  let availableThemes: string[] = []
+  try {
+    availableThemes = getAvailableThemes()
+  } catch {
+    // Fallback to empty list if theme resolution fails
+    availableThemes = []
+  }
   return (
src/utils/console/cat.ts (1)

13-17: Consider extracting the binary file guard to reduce duplication.

This binary file check is duplicated identically in cat.ts, head.ts, tail.ts, and wc.ts. Consider extracting it to a shared utility function.

Create a shared utility in a common file (e.g., src/utils/console/common.ts):

export function checkAndRejectBinary(
  target: string,
  env: SecretConsoleEnv,
  commandName: string
): boolean {
  const stat = env.stat(target)
  if (stat && stat.kind === 'file' && stat.binary) {
    env.appendOutput(`${commandName}: ${target}: Is a binary file`)
    return true
  }
  return false
}

Then in each command file:

-  const stat = env.stat(target)
-  if (stat && stat.kind === 'file' && stat.binary) {
-    env.appendOutput(`cat: ${target}: Is a binary file`)
+  if (checkAndRejectBinary(target, env, 'cat')) {
     return
   }
src/utils/console/completion.ts (1)

283-305: Consider extracting shared completion logic.

The completeConfettiSubcommands function duplicates the logic from completeAchievementSubcommands (Lines 259-281). Both follow the identical pattern of filtering subcommands and handling completion cases.

Consider extracting a shared helper function to reduce duplication:

+function completeSubcommands(
+  token: string,
+  before: string,
+  after: string,
+  getSubcommands: () => string[],
+): CompletionResult | null {
+  const subcommands = getSubcommands()
+  const filtered = subcommands.filter(s => s.startsWith(token))
+
+  if (filtered.length === 0) return { value: `${before}${token}${after}`, caret: (before + token).length }
+  if (filtered.length === 1) {
+    const completed = filtered[0]!
+    const nextToken = `${completed} `
+    const nextValue = `${before}${nextToken}${after}`
+    const nextCaret = (before + nextToken).length
+    return { value: nextValue, caret: nextCaret }
+  }
+  if (token.length === 0)
+    return { value: `${before}${token}${after}`, caret: (before + token).length, suggestions: filtered }
+  const common = longestCommonPrefix(filtered)
+  if (common && common.length > token.length) {
+    const nextToken = common
+    const nextValue = `${before}${nextToken}${after}`
+    const nextCaret = (before + nextToken).length
+    return { value: nextValue, caret: nextCaret }
+  }
+  return { value: `${before}${token}${after}`, caret: (before + token).length, suggestions: filtered }
+}

Then replace both functions:

function completeAchievementSubcommands(token: string, before: string, after: string): CompletionResult | null {
  return completeSubcommands(token, before, after, getAchievementSubcommands)
}

function completeConfettiSubcommands(token: string, before: string, after: string): CompletionResult | null {
  return completeSubcommands(token, before, after, getConfettiSubcommands)
}
src/utils/console/confetti.ts (1)

3-8: Deduplicate confetti type literals.

ConfettiType and getConfettiSubcommands() both hardcode the same string list; keeping two sources in sync is brittle. Hoisting the literals into a single const tuple lets the type alias and completion helper share the same source of truth.

-type ConfettiType = 'default' | 'corners' | 'top' | 'center'
-
-// Get available confetti subcommands for completion
-export function getConfettiSubcommands(): string[] {
-  return ['default', 'corners', 'top', 'center']
-}
+const CONFETTI_TYPES = ['default', 'corners', 'top', 'center'] as const
+type ConfettiType = (typeof CONFETTI_TYPES)[number]
+
+// Get available confetti subcommands for completion
+export function getConfettiSubcommands(): string[] {
+  return [...CONFETTI_TYPES]
+}

Also applies to: 26-33

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6493093 and 1245454.

📒 Files selected for processing (30)
  • src/components/providers/confetti-provider.tsx (1 hunks)
  • src/components/secret-console/secret-console.tsx (8 hunks)
  • src/lib/secret-console-files.ts (1 hunks)
  • src/lib/storage-keys.ts (1 hunks)
  • src/types/secret-console.d.ts (3 hunks)
  • src/utils/console/__tests__/cat.test.ts (1 hunks)
  • src/utils/console/__tests__/cd.test.ts (2 hunks)
  • src/utils/console/__tests__/clear.test.ts (1 hunks)
  • src/utils/console/__tests__/completion.test.ts (4 hunks)
  • src/utils/console/__tests__/head.test.ts (3 hunks)
  • src/utils/console/__tests__/ls.test.ts (1 hunks)
  • src/utils/console/__tests__/pwd.test.ts (1 hunks)
  • src/utils/console/__tests__/tail.test.ts (1 hunks)
  • src/utils/console/__tests__/test-utils.ts (2 hunks)
  • src/utils/console/__tests__/tree.test.ts (1 hunks)
  • src/utils/console/__tests__/uname.test.ts (1 hunks)
  • src/utils/console/__tests__/uptime.test.ts (1 hunks)
  • src/utils/console/__tests__/wc.test.ts (1 hunks)
  • src/utils/console/cat.ts (1 hunks)
  • src/utils/console/clear.ts (1 hunks)
  • src/utils/console/completion.ts (3 hunks)
  • src/utils/console/confetti.ts (1 hunks)
  • src/utils/console/head.ts (1 hunks)
  • src/utils/console/index.ts (2 hunks)
  • src/utils/console/tail.ts (1 hunks)
  • src/utils/console/tree.ts (1 hunks)
  • src/utils/console/uname.ts (1 hunks)
  • src/utils/console/uptime.ts (1 hunks)
  • src/utils/console/wc.ts (1 hunks)
  • src/utils/secret-console-vfs.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx,cjs,mjs}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

**/*.{ts,tsx,js,jsx,cjs,mjs}: Never hardcode or hallucinate the PostHog API key; always read it from the value populated in the .env file
Create new feature flag names that are clear and descriptive
Gate flag-dependent code on a check that verifies the flag’s values are valid and expected
If a custom property for a person or event is referenced in two or more files or in two or more callsites within the same file, centralize the property name in an enum (TS) or const object (JS)

Files:

  • src/utils/console/__tests__/tail.test.ts
  • src/utils/console/uptime.ts
  • src/utils/console/__tests__/ls.test.ts
  • src/utils/console/tail.ts
  • src/utils/console/completion.ts
  • src/components/providers/confetti-provider.tsx
  • src/utils/console/head.ts
  • src/utils/console/__tests__/head.test.ts
  • src/utils/console/tree.ts
  • src/utils/console/__tests__/cat.test.ts
  • src/utils/console/__tests__/wc.test.ts
  • src/utils/console/__tests__/completion.test.ts
  • src/utils/console/uname.ts
  • src/utils/console/__tests__/clear.test.ts
  • src/types/secret-console.d.ts
  • src/utils/console/__tests__/cd.test.ts
  • src/lib/storage-keys.ts
  • src/utils/console/cat.ts
  • src/utils/console/__tests__/pwd.test.ts
  • src/utils/console/index.ts
  • src/utils/console/__tests__/test-utils.ts
  • src/utils/console/wc.ts
  • src/utils/console/__tests__/uptime.test.ts
  • src/utils/console/__tests__/tree.test.ts
  • src/utils/console/confetti.ts
  • src/utils/secret-console-vfs.ts
  • src/utils/console/clear.ts
  • src/utils/console/__tests__/uname.test.ts
  • src/lib/secret-console-files.ts
  • src/components/secret-console/secret-console.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

In TypeScript, store feature flag names in an enum with members written in UPPERCASE_WITH_UNDERSCORE and use a consistent naming convention

Files:

  • src/utils/console/__tests__/tail.test.ts
  • src/utils/console/uptime.ts
  • src/utils/console/__tests__/ls.test.ts
  • src/utils/console/tail.ts
  • src/utils/console/completion.ts
  • src/components/providers/confetti-provider.tsx
  • src/utils/console/head.ts
  • src/utils/console/__tests__/head.test.ts
  • src/utils/console/tree.ts
  • src/utils/console/__tests__/cat.test.ts
  • src/utils/console/__tests__/wc.test.ts
  • src/utils/console/__tests__/completion.test.ts
  • src/utils/console/uname.ts
  • src/utils/console/__tests__/clear.test.ts
  • src/types/secret-console.d.ts
  • src/utils/console/__tests__/cd.test.ts
  • src/lib/storage-keys.ts
  • src/utils/console/cat.ts
  • src/utils/console/__tests__/pwd.test.ts
  • src/utils/console/index.ts
  • src/utils/console/__tests__/test-utils.ts
  • src/utils/console/wc.ts
  • src/utils/console/__tests__/uptime.test.ts
  • src/utils/console/__tests__/tree.test.ts
  • src/utils/console/confetti.ts
  • src/utils/secret-console-vfs.ts
  • src/utils/console/clear.ts
  • src/utils/console/__tests__/uname.test.ts
  • src/lib/secret-console-files.ts
  • src/components/secret-console/secret-console.tsx
🧠 Learnings (1)
📚 Learning: 2025-10-03T00:48:27.729Z
Learnt from: kiliantyler
PR: kiliantyler/kil.dev#103
File: src/components/providers/confetti-provider.tsx:214-314
Timestamp: 2025-10-03T00:48:27.729Z
Learning: In src/components/providers/confetti-provider.tsx, the `triggerConfettiChaos` function intentionally creates an infinite confetti loop with no exit condition. This is a deliberate easter egg feature triggered after 20 clicks, and the resource usage is expected behavior. The warning toasts inform users that the only way to stop it is by reloading the page.

Applied to files:

  • src/components/providers/confetti-provider.tsx
🧬 Code graph analysis (22)
src/utils/console/__tests__/tail.test.ts (2)
src/utils/console/tail.ts (1)
  • tail (48-53)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/uptime.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/console/__tests__/ls.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/ls.ts (1)
  • ls (9-14)
src/utils/console/completion.ts (1)
src/utils/console/confetti.ts (1)
  • getConfettiSubcommands (6-8)
src/utils/console/__tests__/head.test.ts (2)
src/utils/console/head.ts (1)
  • head (47-52)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/tree.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/console/__tests__/cat.test.ts (1)
src/utils/console/cat.ts (1)
  • cat (26-31)
src/utils/console/__tests__/wc.test.ts (2)
src/utils/console/wc.ts (1)
  • wc (29-34)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/__tests__/completion.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/secret-console-vfs.ts (1)
  • normalizePath (8-29)
src/utils/console/__tests__/clear.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/clear.ts (1)
  • clear (7-13)
src/utils/console/__tests__/cd.test.ts (2)
src/utils/console/cd.ts (2)
  • cd (20-25)
  • formatCdNotDirectory (3-5)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/__tests__/pwd.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/pwd.ts (1)
  • pwd (7-12)
src/utils/console/index.ts (1)
src/types/secret-console.d.ts (1)
  • SecretConsoleCommand (12-35)
src/utils/console/__tests__/test-utils.ts (3)
src/utils/secret-console-vfs.ts (5)
  • normalizePath (8-29)
  • vfsList (49-62)
  • vfsRead (64-69)
  • vfsStat (71-83)
  • vfsResolve (36-47)
src/types/secret-console.d.ts (1)
  • SecretConsoleEnv (1-10)
src/lib/secret-console-files.ts (1)
  • SECRET_CONSOLE_VFS (9-561)
src/utils/console/__tests__/uptime.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/uptime.ts (1)
  • uptime (53-58)
src/utils/console/__tests__/tree.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/tree.ts (1)
  • tree (146-151)
src/utils/console/confetti.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/secret-console-vfs.ts (6)
src/types/secret-console.d.ts (2)
  • VfsNode (48-48)
  • VfsStat (50-55)
src/lib/storage-keys.ts (1)
  • LOCAL_STORAGE_KEYS (7-28)
src/utils/theme-runtime.ts (1)
  • getAvailableThemes (84-108)
src/utils/achievements.ts (1)
  • parseUnlockedStorage (68-76)
src/lib/achievements.ts (2)
  • ACHIEVEMENTS (6-159)
  • AchievementId (161-161)
src/lib/secret-console-commands.ts (1)
  • SECRET_CONSOLE_COMMANDS (3-3)
src/utils/console/clear.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/console/__tests__/uname.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/uname.ts (1)
  • uname (44-49)
src/lib/secret-console-files.ts (2)
src/types/secret-console.d.ts (1)
  • VfsNode (48-48)
src/utils/secret-console-vfs.ts (4)
  • binChildren (190-192)
  • getThemeCacheContent (93-116)
  • getUnlockedAchievementFiles (118-143)
  • getAchievementProgressContent (145-188)
src/components/secret-console/secret-console.tsx (4)
src/types/secret-console.d.ts (2)
  • VfsNode (48-48)
  • SecretConsoleEnv (1-10)
src/lib/secret-console-files.ts (1)
  • SECRET_CONSOLE_VFS (9-561)
src/lib/storage-keys.ts (1)
  • SESSION_STORAGE_KEYS (31-47)
src/utils/secret-console-vfs.ts (4)
  • vfsRead (64-69)
  • vfsList (49-62)
  • normalizePath (8-29)
  • vfsStat (71-83)
🪛 GitHub Actions: CI - Lighthouse
src/components/secret-console/secret-console.tsx

[error] 141-145: ESLint: unicorn/prefer-global-this — Prefer globalThis over window (lines 141-145).

🪛 GitHub Actions: Lint
src/components/secret-console/secret-console.tsx

[error] 141-141: ESLint: unicorn/prefer-global-this. Prefer globalThis over window.

🪛 GitHub Check: lint
src/components/secret-console/secret-console.tsx

[failure] 145-145:
Prefer globalThis over window


[failure] 144-144:
Prefer globalThis over window


[failure] 142-142:
Prefer globalThis over window


[failure] 141-141:
Prefer globalThis over window

🔇 Additional comments (29)
src/utils/console/__tests__/cd.test.ts (2)

8-10: LGTM: absolute path cd

Good coverage for absolute path; empty output and updated cwd assertions are correct.


32-44: LGTM: tilde expansion tests; confirm default cd semantics

The new tests for ~ and /… expansion look solid. One question: cd with no args currently lands on /home (per the other test). Typical shells resolve cd to the user’s home (, i.e., /home/kil here). If intentional, ignore; otherwise consider aligning cd [] with cd ~.

src/types/secret-console.d.ts (1)

3-3: Type surface aligns with richer VFS and console env

The additions (clearOutput, stat, functional children, VfsStat) look consistent with usage in VFS and tests. No issues found.

Also applies to: 7-7, 19-29, 37-55

src/utils/console/__tests__/pwd.test.ts (1)

9-9: LGTM: expectations match env initial cwd

Updated assertions to /home/kil align with createMockEnv’s default.

Also applies to: 15-15

src/utils/console/__tests__/clear.test.ts (1)

5-32: LGTM! Well-structured test coverage.

The test cases properly verify the clear command's core behavior: removing output and ignoring arguments. The use of createMockEnv and assertions on output length are appropriate.

src/utils/console/__tests__/uname.test.ts (1)

9-22: LGTM! Test expectations updated correctly.

The test expectations now properly reflect the new VFS-backed implementation where uname reads from /etc/os-release and /etc/hostname rather than using hardcoded values.

src/utils/console/index.ts (1)

5-46: LGTM! New commands properly registered.

The four new commands (clear, confetti, tree, uptime) are correctly imported and added to the command registry, maintaining consistency with existing command registration patterns.

src/components/providers/confetti-provider.tsx (1)

362-409: LGTM! Robust event handling with proper validation.

The event listener implementation correctly:

  • Validates that the event is a CustomEvent
  • Performs runtime type checking on event.detail structure
  • Logs warnings for unexpected types or invalid data
  • Includes all trigger callbacks in the effect dependencies
  • Properly cleans up the event listener
src/utils/console/clear.ts (1)

1-13: LGTM! Clean implementation.

The clear command implementation is concise and correct. The use of _args prefix properly indicates the parameter is intentionally unused, and the completion configuration appropriately restricts positional arguments. The cls alias provides good cross-platform familiarity.

src/utils/console/__tests__/cat.test.ts (1)

8-11: Good refactor to presence-based validation.

The shift from exact content matching to presence checks (using toContain) makes the test more resilient to non-breaking changes in the file content while still validating the essential requirements.

src/utils/console/__tests__/ls.test.ts (1)

9-25: Test improvements aligned with VFS expansion.

The updated assertions using toContain for specific directory entries make the tests more maintainable as the VFS structure evolves, while continuing to validate the core listing behavior.

src/utils/console/__tests__/tail.test.ts (1)

8-26: LGTM! Validation correctly balances specificity and flexibility.

The combination of presence checks and line count validation (using toBeLessThanOrEqual at Line 19) appropriately tests the -n flag behavior without over-constraining the output format.

src/utils/console/__tests__/wc.test.ts (1)

8-21: Correct validation of wc output structure.

The test correctly validates the standard wc output format (lines, words, bytes, filename) by splitting on spaces and checking for 4 parts, ensuring the command adheres to its contract.

src/utils/console/completion.ts (1)

413-413: Completion integration looks correct.

The confetti-subcommands mode is properly integrated into the completion flow, maintaining consistency with the existing achievement-subcommands pattern.

src/lib/storage-keys.ts (1)

42-46: Well-documented session storage keys.

The new console state keys follow the established naming convention and are appropriately scoped to sessionStorage for transient state that should reset on page reload. The inline documentation clearly explains the persistence behavior.

src/utils/console/__tests__/tree.test.ts (1)

1-92: Comprehensive test coverage for tree command.

The test suite thoroughly validates the tree command functionality:

  • Basic rendering and structure validation
  • Flag behavior (-L for depth, -d for directories-only)
  • Error handling for invalid paths and non-directory targets
  • Flag combinations

The depth validation approach at Line 44 (checking for absence of double indentation) is particularly clever, and the flexible regex patterns at Lines 33 and 55 handle both singular and plural forms gracefully.

src/utils/console/__tests__/completion.test.ts (2)

82-98: Test updates align with new VFS structure.

The test correctly verifies relative path completion from /home/kil/projects toward kil.dev/. The updated assertions properly check for prefix matching and substring inclusion.


100-116: Folder completion test properly validates new home directory.

The test correctly expects completion toward /home/kil/Documents/ or /home/kil/Downloads/ from the prefix /home/kil/Do. The assertions appropriately verify both the prefix and caret positioning.

src/utils/console/__tests__/test-utils.ts (2)

1-18: VFS integration properly implemented.

The mock environment correctly integrates with SECRET_CONSOLE_VFS and implements path resolution consistent with the real environment. The resolvePath helper properly handles absolute, tilde, and relative paths.


24-39: Environment methods correctly updated.

All VFS operations (list, read, stat, chdir) now use the centralized resolvePath helper and delegate to the corresponding VFS functions. The new clearOutput method properly clears the output array.

src/utils/console/tree.ts (3)

1-44: Argument parsing properly implemented.

The parseTreeArgs function correctly handles the -L flag for depth and -d flag for directories-only mode. Flag parsing correctly increments the index and validates numeric inputs.


46-103: Tree building logic is sound.

The recursive buildTree function properly:

  • Respects the depth limit
  • Filters children based on dirsOnly option
  • Sorts directories before files, then alphabetically
  • Tracks directory and file counts
  • Handles path construction for root and non-root directories (line 96)

105-151: Command execution and export are correct.

The executeTree function properly validates the target path, checks for directories, and formats the output with appropriate summary statistics. The completion configuration correctly specifies 'paths' for tab completion support.

src/components/secret-console/secret-console.tsx (6)

13-17: Entry type and prompt formatting properly implemented.

The updated Entry type includes the optional cwd field, and formatPrompt correctly replaces /home/kil with ~ for a cleaner prompt display.


21-90: Session storage initialization correctly implemented.

All state (entries, history, cwd, height) is properly initialized from sessionStorage with appropriate fallbacks and error handling. The MOTD is correctly loaded from the VFS when no saved entries exist.


111-138: Resize drag handlers are well-implemented.

The drag handlers properly track mouse movement and calculate height in viewport units with appropriate bounds (30-95 vh). The implementation follows React best practices with proper event handling.


183-216: State persistence properly implemented.

All effects correctly persist state to sessionStorage with appropriate error handling. This ensures the console maintains its state across interactions during a session.


222-248: Environment object correctly updated.

The env object properly implements:

  • The new clearOutput method
  • Path resolution with tilde expansion support
  • Integration with VFS functions for list, read, stat
  • Directory change handling with proper validation

The path resolution correctly handles absolute, tilde, and relative paths by checking prefixes and using normalizePath.


372-421: UI interactions properly implemented.

The component correctly:

  • Prevents input focus when interacting with the resize handle (lines 373-380)
  • Includes cwd-aware prompts in entry rendering (line 392) and input display (line 399)
  • Implements the resize handle with appropriate ARIA labels and visual feedback (lines 414-421)

Copy link
Copy Markdown
Contributor

@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: 2

🧹 Nitpick comments (5)
src/utils/console/confetti.ts (1)

3-8: Consider deriving the subcommands array from the type to maintain single source of truth.

The ConfettiType union and getConfettiSubcommands() array duplicate the same four values. If you add/remove a confetti type, you must update both locations.

Apply this pattern to derive the array from a const assertion:

-type ConfettiType = 'default' | 'corners' | 'top' | 'center'
+const CONFETTI_TYPES = ['default', 'corners', 'top', 'center'] as const
+type ConfettiType = (typeof CONFETTI_TYPES)[number]

 // Get available confetti subcommands for completion
 export function getConfettiSubcommands(): string[] {
-  return ['default', 'corners', 'top', 'center']
+  return [...CONFETTI_TYPES]
 }
src/utils/console/cat.ts (1)

13-17: Consider extracting the binary-file guard to reduce duplication.

This guard pattern appears in cat.ts, head.ts, tail.ts, and wc.ts. Extracting it to a helper would ensure consistency and simplify maintenance.

Example helper:

function checkBinaryFile(
  target: string,
  commandName: string,
  env: SecretConsoleEnv
): boolean {
  const stat = env.stat(target)
  if (stat && stat.kind === 'file' && stat.binary) {
    env.appendOutput(`${commandName}: ${target}: Is a binary file`)
    return true
  }
  return false
}

Usage in each command:

-  const stat = env.stat(target)
-  if (stat && stat.kind === 'file' && stat.binary) {
-    env.appendOutput(`cat: ${target}: Is a binary file`)
+  if (checkBinaryFile(target, 'cat', env)) {
     return
-  }
src/utils/console/__tests__/tail.test.ts (1)

43-53: Inconsistent file path usage in error tests.

Lines 43 and 53 still reference /home/README.md, while other tests use the updated VFS paths like /home/kil/Documents/bookmarks.md and /home/kil/.profile.

For consistency with the rest of the test suite, consider updating these paths as well, even though the tests focus on flag parsing errors rather than file reading.

Apply this diff to align with updated paths:

-    tail.execute(['-n', 'invalid', '/home/README.md'], env)
+    tail.execute(['-n', 'invalid', '/home/kil/.bashrc'], env)

And:

-    tail.execute(['-n', '0', '/home/README.md'], env)
+    tail.execute(['-n', '0', '/home/kil/.bashrc'], env)
src/components/secret-console/secret-console.tsx (2)

130-138: Persist height when resizing ends.

Height is saved on every mousemove while dragging, causing dozens of writes per frame. Persist only on drag end (or debounce) to avoid thrashing sessionStorage.


228-247: Repeated path resolution logic.

The path.startsWith('/') || path.startsWith('~') ? … pattern is duplicated for list/read/stat/chdir. Extract a helper (e.g., resolvePath(path, cwd)) for clarity and fewer mistakes if this logic changes later.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6493093 and a00c39a.

📒 Files selected for processing (30)
  • src/components/providers/confetti-provider.tsx (1 hunks)
  • src/components/secret-console/secret-console.tsx (8 hunks)
  • src/lib/secret-console-files.ts (1 hunks)
  • src/lib/storage-keys.ts (1 hunks)
  • src/types/secret-console.d.ts (3 hunks)
  • src/utils/console/__tests__/cat.test.ts (1 hunks)
  • src/utils/console/__tests__/cd.test.ts (2 hunks)
  • src/utils/console/__tests__/clear.test.ts (1 hunks)
  • src/utils/console/__tests__/completion.test.ts (4 hunks)
  • src/utils/console/__tests__/head.test.ts (3 hunks)
  • src/utils/console/__tests__/ls.test.ts (1 hunks)
  • src/utils/console/__tests__/pwd.test.ts (1 hunks)
  • src/utils/console/__tests__/tail.test.ts (1 hunks)
  • src/utils/console/__tests__/test-utils.ts (2 hunks)
  • src/utils/console/__tests__/tree.test.ts (1 hunks)
  • src/utils/console/__tests__/uname.test.ts (1 hunks)
  • src/utils/console/__tests__/uptime.test.ts (1 hunks)
  • src/utils/console/__tests__/wc.test.ts (1 hunks)
  • src/utils/console/cat.ts (1 hunks)
  • src/utils/console/clear.ts (1 hunks)
  • src/utils/console/completion.ts (3 hunks)
  • src/utils/console/confetti.ts (1 hunks)
  • src/utils/console/head.ts (1 hunks)
  • src/utils/console/index.ts (2 hunks)
  • src/utils/console/tail.ts (1 hunks)
  • src/utils/console/tree.ts (1 hunks)
  • src/utils/console/uname.ts (1 hunks)
  • src/utils/console/uptime.ts (1 hunks)
  • src/utils/console/wc.ts (1 hunks)
  • src/utils/secret-console-vfs.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx,cjs,mjs}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

**/*.{ts,tsx,js,jsx,cjs,mjs}: Never hardcode or hallucinate the PostHog API key; always read it from the value populated in the .env file
Create new feature flag names that are clear and descriptive
Gate flag-dependent code on a check that verifies the flag’s values are valid and expected
If a custom property for a person or event is referenced in two or more files or in two or more callsites within the same file, centralize the property name in an enum (TS) or const object (JS)

Files:

  • src/utils/console/__tests__/pwd.test.ts
  • src/utils/console/__tests__/cat.test.ts
  • src/utils/console/__tests__/uname.test.ts
  • src/utils/console/__tests__/uptime.test.ts
  • src/utils/console/tree.ts
  • src/utils/console/index.ts
  • src/utils/console/tail.ts
  • src/lib/storage-keys.ts
  • src/utils/console/__tests__/completion.test.ts
  • src/utils/console/__tests__/head.test.ts
  • src/components/providers/confetti-provider.tsx
  • src/utils/console/clear.ts
  • src/utils/console/confetti.ts
  • src/utils/console/__tests__/wc.test.ts
  • src/utils/console/__tests__/ls.test.ts
  • src/utils/console/uptime.ts
  • src/utils/console/__tests__/clear.test.ts
  • src/utils/console/cat.ts
  • src/types/secret-console.d.ts
  • src/utils/console/completion.ts
  • src/utils/console/wc.ts
  • src/utils/console/__tests__/tail.test.ts
  • src/utils/secret-console-vfs.ts
  • src/utils/console/head.ts
  • src/utils/console/__tests__/cd.test.ts
  • src/utils/console/__tests__/test-utils.ts
  • src/lib/secret-console-files.ts
  • src/utils/console/__tests__/tree.test.ts
  • src/utils/console/uname.ts
  • src/components/secret-console/secret-console.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

In TypeScript, store feature flag names in an enum with members written in UPPERCASE_WITH_UNDERSCORE and use a consistent naming convention

Files:

  • src/utils/console/__tests__/pwd.test.ts
  • src/utils/console/__tests__/cat.test.ts
  • src/utils/console/__tests__/uname.test.ts
  • src/utils/console/__tests__/uptime.test.ts
  • src/utils/console/tree.ts
  • src/utils/console/index.ts
  • src/utils/console/tail.ts
  • src/lib/storage-keys.ts
  • src/utils/console/__tests__/completion.test.ts
  • src/utils/console/__tests__/head.test.ts
  • src/components/providers/confetti-provider.tsx
  • src/utils/console/clear.ts
  • src/utils/console/confetti.ts
  • src/utils/console/__tests__/wc.test.ts
  • src/utils/console/__tests__/ls.test.ts
  • src/utils/console/uptime.ts
  • src/utils/console/__tests__/clear.test.ts
  • src/utils/console/cat.ts
  • src/types/secret-console.d.ts
  • src/utils/console/completion.ts
  • src/utils/console/wc.ts
  • src/utils/console/__tests__/tail.test.ts
  • src/utils/secret-console-vfs.ts
  • src/utils/console/head.ts
  • src/utils/console/__tests__/cd.test.ts
  • src/utils/console/__tests__/test-utils.ts
  • src/lib/secret-console-files.ts
  • src/utils/console/__tests__/tree.test.ts
  • src/utils/console/uname.ts
  • src/components/secret-console/secret-console.tsx
🧠 Learnings (1)
📚 Learning: 2025-10-03T00:48:27.729Z
Learnt from: kiliantyler
PR: kiliantyler/kil.dev#103
File: src/components/providers/confetti-provider.tsx:214-314
Timestamp: 2025-10-03T00:48:27.729Z
Learning: In src/components/providers/confetti-provider.tsx, the `triggerConfettiChaos` function intentionally creates an infinite confetti loop with no exit condition. This is a deliberate easter egg feature triggered after 20 clicks, and the resource usage is expected behavior. The warning toasts inform users that the only way to stop it is by reloading the page.

Applied to files:

  • src/components/providers/confetti-provider.tsx
🧬 Code graph analysis (22)
src/utils/console/__tests__/pwd.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/pwd.ts (1)
  • pwd (7-12)
src/utils/console/__tests__/cat.test.ts (1)
src/utils/console/cat.ts (1)
  • cat (26-31)
src/utils/console/__tests__/uname.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/uname.ts (1)
  • uname (44-49)
src/utils/console/__tests__/uptime.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/uptime.ts (1)
  • uptime (53-58)
src/utils/console/tree.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/console/index.ts (1)
src/types/secret-console.d.ts (1)
  • SecretConsoleCommand (12-35)
src/utils/console/__tests__/completion.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/secret-console-vfs.ts (1)
  • normalizePath (8-29)
src/utils/console/__tests__/head.test.ts (2)
src/utils/console/head.ts (1)
  • head (47-52)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/clear.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/console/confetti.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/console/__tests__/wc.test.ts (2)
src/utils/console/wc.ts (1)
  • wc (29-34)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/__tests__/ls.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/ls.ts (1)
  • ls (9-14)
src/utils/console/uptime.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/utils/console/__tests__/clear.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/clear.ts (1)
  • clear (7-13)
src/utils/console/completion.ts (1)
src/utils/console/confetti.ts (1)
  • getConfettiSubcommands (6-8)
src/utils/console/__tests__/tail.test.ts (2)
src/utils/console/tail.ts (1)
  • tail (48-53)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/secret-console-vfs.ts (6)
src/types/secret-console.d.ts (2)
  • VfsNode (48-48)
  • VfsStat (50-55)
src/lib/storage-keys.ts (1)
  • LOCAL_STORAGE_KEYS (7-28)
src/utils/theme-runtime.ts (1)
  • getAvailableThemes (84-108)
src/utils/achievements.ts (1)
  • parseUnlockedStorage (68-76)
src/lib/achievements.ts (2)
  • ACHIEVEMENTS (6-159)
  • AchievementId (161-161)
src/lib/secret-console-commands.ts (1)
  • SECRET_CONSOLE_COMMANDS (3-3)
src/utils/console/__tests__/cd.test.ts (2)
src/utils/console/cd.ts (2)
  • cd (20-25)
  • formatCdNotDirectory (3-5)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/__tests__/test-utils.ts (3)
src/utils/secret-console-vfs.ts (5)
  • normalizePath (8-29)
  • vfsList (49-62)
  • vfsRead (64-69)
  • vfsStat (71-83)
  • vfsResolve (36-47)
src/types/secret-console.d.ts (1)
  • SecretConsoleEnv (1-10)
src/lib/secret-console-files.ts (1)
  • SECRET_CONSOLE_VFS (9-561)
src/lib/secret-console-files.ts (2)
src/types/secret-console.d.ts (1)
  • VfsNode (48-48)
src/utils/secret-console-vfs.ts (4)
  • binChildren (190-192)
  • getThemeCacheContent (93-116)
  • getUnlockedAchievementFiles (118-143)
  • getAchievementProgressContent (145-188)
src/utils/console/__tests__/tree.test.ts (2)
src/utils/console/__tests__/test-utils.ts (1)
  • createMockEnv (5-62)
src/utils/console/tree.ts (1)
  • tree (146-151)
src/components/secret-console/secret-console.tsx (3)
src/types/secret-console.d.ts (2)
  • VfsNode (48-48)
  • SecretConsoleEnv (1-10)
src/lib/storage-keys.ts (1)
  • SESSION_STORAGE_KEYS (31-47)
src/utils/secret-console-vfs.ts (4)
  • vfsRead (64-69)
  • vfsList (49-62)
  • normalizePath (8-29)
  • vfsStat (71-83)
⏰ 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: lighthouse
🔇 Additional comments (22)
src/utils/console/confetti.ts (3)

11-17: LGTM!

The helper provides clear user guidance for available confetti types.


48-56: LGTM!

The command configuration is properly structured with appropriate completion settings.


19-46: Event name consistency confirmed The dispatched 'kd:trigger-confetti' CustomEvent in src/utils/console/confetti.ts matches the listener and removal in src/components/providers/confetti-provider.tsx.

src/utils/console/__tests__/pwd.test.ts (2)

9-9: LGTM!

Test expectation correctly updated to match the new default working directory /home/kil established in the test utilities.


15-15: LGTM!

Consistent with the first test—correctly expects /home/kil as the working directory.

src/utils/console/__tests__/cat.test.ts (1)

8-11: LGTM!

Test updated to read from the expanded VFS path /home/kil/.bashrc and validates expected content markers. The assertion pattern is appropriate for verifying multi-line output.

src/utils/console/tail.ts (1)

33-37: LGTM!

The binary-file guard correctly prevents attempting to read binary content as text. The error message is clear and follows Unix conventions.

src/utils/console/head.ts (1)

33-37: LGTM!

The binary-file guard is correctly implemented, matching the pattern used in tail.ts and other file-reading commands.

src/utils/console/__tests__/uname.test.ts (3)

9-9: LGTM!

Test expectation correctly updated to reflect the new uname implementation that reads OS metadata from the VFS.


16-16: LGTM!

The regex pattern correctly validates the full system info format with OS name, nodename, and version.


22-22: LGTM!

Consistent with the default behavior test—correctly expects kilOS as the system name.

src/utils/console/wc.ts (1)

13-17: LGTM!

The binary-file guard is correctly implemented. Note that this pattern is duplicated across cat.ts, head.ts, tail.ts, and wc.ts—see the refactor suggestion in the cat.ts review.

src/utils/console/__tests__/uptime.test.ts (1)

1-45: LGTM! Comprehensive test coverage for the uptime command.

The test suite appropriately covers:

  • Display formatting verification
  • Load average parsing from /proc/loadavg
  • Uptime duration formatting with time units
  • Graceful fallback when /proc/loadavg is unavailable

The assertions use appropriate matchers and the tests exercise both success and error paths.

src/utils/console/__tests__/cd.test.ts (1)

8-44: LGTM! Tests updated to reflect VFS changes and tilde expansion.

The test updates appropriately:

  • Adapt paths to the new VFS structure (/home/kil/Documents, /home/kil/.bashrc)
  • Add coverage for tilde expansion (~/home/kil, ~/Documents/home/kil/Documents)

The tilde expansion tests are valuable additions that verify shell-like path resolution behavior.

src/utils/console/__tests__/head.test.ts (1)

6-60: LGTM! Test updates improve maintainability.

The test updates appropriately:

  • Switch to alternative file paths that align with the expanded VFS
  • Use looser content assertions (presence checks vs exact string matches), improving maintainability against future content changes
  • Maintain comprehensive coverage of flag handling, error cases, and edge conditions

The -n flag behavior and error handling remain well-tested.

src/utils/console/index.ts (1)

5-47: LGTM! Command registry expansion is correct.

The new commands (clear, confetti, tree, uptime) are properly:

  • Imported from their respective modules
  • Registered in the command registry
  • Typed via the Readonly<typeof registry> pattern

The registry structure and initialization order are maintained correctly.

src/utils/console/__tests__/tail.test.ts (1)

8-39: LGTM! Test updates align with VFS changes.

The test updates appropriately:

  • Adapt to the new VFS structure with updated file paths
  • Use presence-based assertions instead of exact content matching
  • Maintain comprehensive coverage of default behavior, custom line counts, and error handling
src/utils/console/__tests__/clear.test.ts (1)

1-32: LGTM! Clear and focused tests for the clear command.

The test suite appropriately covers:

  • Basic clearing functionality (output length goes from 3 to 0)
  • Argument handling (arguments are ignored as expected)

The tests are simple, readable, and verify the command's core behavior correctly.

src/lib/storage-keys.ts (1)

42-46: LGTM! Session storage keys follow established conventions.

The new console state keys:

  • Follow the consistent kd_ naming prefix
  • Are appropriately placed in SESSION_STORAGE_KEYS (state persists during session, resets on page reload)
  • Are well-documented with inline comments
  • Align with the console persistence requirements described in the PR objectives
src/components/providers/confetti-provider.tsx (2)

362-409: Robust event handling with thorough validation.

The event listener implementation correctly:

  • Adds and cleans up the listener on mount/unmount
  • Validates event.detail structure before use (object with string type property)
  • Dispatches to the appropriate trigger functions based on type
  • Logs warnings for unexpected types to aid debugging

The dependencies array correctly includes all trigger functions referenced in the handler.


386-402: Console command intentionally supports only the four basic types
The confetti console command and its subcommands (default, corners, top, center) are deliberately limited to those four modes. The celebration and chaos triggers are exposed only via the React context hooks for programmatic/UI use, not via the console.

src/components/secret-console/secret-console.tsx (1)

183-219: Persisting after each mutation suffices.

Nice touch persisting entries, history, cwd, and height in sessionStorage with safe guards around storage failures. Looks solid.

Copy link
Copy Markdown
Contributor

@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: 0

♻️ Duplicate comments (1)
src/components/secret-console/secret-console.tsx (1)

140-150: Past review comment already addressed.

The code already uses globalThis.addEventListener and globalThis.removeEventListener as suggested in the previous review. The implementation is correct and follows the codebase style.

🧹 Nitpick comments (1)
src/components/secret-console/secret-console.tsx (1)

184-191: Consider capping entries array to prevent unbounded growth.

History is capped at 50 entries (line 360), but the entries array has no size limit. During a long session with extensive output, this could lead to large sessionStorage consumption and potential performance degradation when serializing/deserializing the array.

Consider adding a cap when persisting entries, similar to history:

   useEffect(() => {
     try {
-      sessionStorage.setItem(SESSION_STORAGE_KEYS.CONSOLE_ENTRIES, JSON.stringify(entries))
+      const cappedEntries = entries.length > 500 ? entries.slice(-500) : entries
+      sessionStorage.setItem(SESSION_STORAGE_KEYS.CONSOLE_ENTRIES, JSON.stringify(cappedEntries))
     } catch {
       // Ignore storage errors
     }
   }, [entries])

Alternatively, cap when adding entries rather than when persisting.

Also applies to: 358-361

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1245454 and ca6f6f5.

📒 Files selected for processing (2)
  • src/components/secret-console/secret-console.tsx (8 hunks)
  • src/utils/console/__tests__/uptime.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/console/tests/uptime.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx,cjs,mjs}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

**/*.{ts,tsx,js,jsx,cjs,mjs}: Never hardcode or hallucinate the PostHog API key; always read it from the value populated in the .env file
Create new feature flag names that are clear and descriptive
Gate flag-dependent code on a check that verifies the flag’s values are valid and expected
If a custom property for a person or event is referenced in two or more files or in two or more callsites within the same file, centralize the property name in an enum (TS) or const object (JS)

Files:

  • src/components/secret-console/secret-console.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

In TypeScript, store feature flag names in an enum with members written in UPPERCASE_WITH_UNDERSCORE and use a consistent naming convention

Files:

  • src/components/secret-console/secret-console.tsx
🧬 Code graph analysis (1)
src/components/secret-console/secret-console.tsx (4)
src/types/secret-console.d.ts (2)
  • VfsNode (48-48)
  • SecretConsoleEnv (1-10)
src/lib/secret-console-files.ts (1)
  • SECRET_CONSOLE_VFS (9-561)
src/lib/storage-keys.ts (1)
  • SESSION_STORAGE_KEYS (31-47)
src/utils/secret-console-vfs.ts (4)
  • vfsRead (64-69)
  • vfsList (49-62)
  • normalizePath (8-29)
  • vfsStat (71-83)
⏰ 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: lighthouse
🔇 Additional comments (1)
src/components/secret-console/secret-console.tsx (1)

23-91: Excellent implementation of console persistence and resize features.

The implementation demonstrates several strengths:

  • SSR-safe: All browser API access is properly guarded with globalThis.window checks
  • Error handling: Consistent try-catch blocks around sessionStorage operations with graceful fallbacks
  • Path resolution: Correctly handles absolute (/), tilde (~), and relative paths across all VFS operations
  • Drag mechanics: Math for vh-based height calculation is correct, with appropriate bounds [30, 95]
  • React patterns: Proper use of hooks, memoization, and dependency arrays

The code is well-organized, readable, and properly integrated with the expanded VFS system.

Also applies to: 112-150, 184-219, 229-251

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
6.3% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link
Copy Markdown
Contributor

@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: 2

🧹 Nitpick comments (6)
src/components/secret-console/secret-console.tsx (4)

60-75: Consider using clearConsoleSessionStorage for consistency.

Unlike the entries initialization which calls clearConsoleSessionStorage() on parse failure, this only removes the history key. For consistency and to prevent potential state inconsistencies, consider using the centralized clearing function here as well.

Apply this diff for consistency:

     } catch (error) {
-      // Clean up corrupted history state
       console.warn('Failed to parse console history from sessionStorage, clearing:', error)
-      sessionStorage.removeItem(SESSION_STORAGE_KEYS.CONSOLE_HISTORY)
+      clearConsoleSessionStorage()
     }

77-92: Consider using clearConsoleSessionStorage for consistency.

Same as with history initialization, consider using the centralized clearing function to maintain consistent recovery behavior across all console state.

Apply this diff:

     } catch (error) {
-      // Clean up corrupted cwd state
       console.warn('Failed to read console cwd from sessionStorage, clearing:', error)
-      sessionStorage.removeItem(SESSION_STORAGE_KEYS.CONSOLE_CWD)
+      clearConsoleSessionStorage()
     }

94-113: Consider using clearConsoleSessionStorage for consistency.

While the validation logic for height bounds is good, consider using the centralized clearing function on parse failure for consistency with the entries initialization.

Apply this diff:

     } catch (error) {
-      // Clean up corrupted height state
       console.warn('Failed to parse console height from sessionStorage, clearing:', error)
-      sessionStorage.removeItem(SESSION_STORAGE_KEYS.CONSOLE_HEIGHT)
+      clearConsoleSessionStorage()
     }

233-241: Remove unnecessary type cast.

The SESSION_STORAGE_KEYS.CONSOLE_HEIGHT is already typed as a string, so the explicit cast is unnecessary.

Apply this diff:

     try {
-      const key = SESSION_STORAGE_KEYS.CONSOLE_HEIGHT as string
-      sessionStorage.setItem(key, height.toString())
+      sessionStorage.setItem(SESSION_STORAGE_KEYS.CONSOLE_HEIGHT, height.toString())
     } catch {
src/utils/console/tree.ts (2)

35-41: Multiple non-flag arguments overwrite the path.

If a user passes multiple path arguments (e.g., tree foo bar), the last one silently overwrites previous values. Consider either:

  • Rejecting multiple paths with an error message, or
  • Documenting that the last path argument wins

Example fix to reject multiple paths:

   // Treat as path if it doesn't start with -
   if (!arg.startsWith('-')) {
+    if (path !== '.') {
+      // Path already set
+      return { path: '', options }  // Signal error to caller
+    }
     path = arg
   }

Then in executeTree, check for empty path and emit an error.


20-27: Consider allowing -L 0 to display only the root.

The Unix tree command accepts -L 0 to display only the root directory. The current check depth > 0 (line 22) silently ignores -L 0, keeping the default depth of 3. Consider either:

  • Allowing depth >= 0 and treating 0 as "root only", or
  • Explicitly rejecting invalid depth values with an error message

Example to allow -L 0:

-      if (!Number.isNaN(depth) && depth > 0) {
+      if (!Number.isNaN(depth) && depth >= 0) {
         options.maxDepth = depth
       }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca6f6f5 and 0dd252d.

📒 Files selected for processing (2)
  • src/components/secret-console/secret-console.tsx (8 hunks)
  • src/utils/console/tree.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx,cjs,mjs}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

**/*.{ts,tsx,js,jsx,cjs,mjs}: Never hardcode or hallucinate the PostHog API key; always read it from the value populated in the .env file
Create new feature flag names that are clear and descriptive
Gate flag-dependent code on a check that verifies the flag’s values are valid and expected
If a custom property for a person or event is referenced in two or more files or in two or more callsites within the same file, centralize the property name in an enum (TS) or const object (JS)

Files:

  • src/utils/console/tree.ts
  • src/components/secret-console/secret-console.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)

In TypeScript, store feature flag names in an enum with members written in UPPERCASE_WITH_UNDERSCORE and use a consistent naming convention

Files:

  • src/utils/console/tree.ts
  • src/components/secret-console/secret-console.tsx
🧬 Code graph analysis (2)
src/utils/console/tree.ts (1)
src/types/secret-console.d.ts (2)
  • SecretConsoleEnv (1-10)
  • SecretConsoleCommand (12-35)
src/components/secret-console/secret-console.tsx (3)
src/lib/storage-keys.ts (1)
  • SESSION_STORAGE_KEYS (31-47)
src/types/secret-console.d.ts (2)
  • VfsNode (48-48)
  • SecretConsoleEnv (1-10)
src/utils/secret-console-vfs.ts (4)
  • vfsRead (64-69)
  • vfsList (49-62)
  • normalizePath (8-29)
  • vfsStat (71-83)
⏰ 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: lighthouse
🔇 Additional comments (11)
src/components/secret-console/secret-console.tsx (8)

15-17: LGTM!

The tilde substitution logic correctly uses a positive lookahead to match /home/kil only when followed by / or at the end of the string, preventing false matches on paths like /home/kilroy.


19-31: Good recovery mechanism for corrupted state.

This helper function addresses the previous review concern about corrupted sessionStorage by providing a centralized way to clear all console-related keys when corruption is detected.


37-58: Excellent error handling for corrupted session data.

This implementation addresses the previous review concern by:

  • Clearing all corrupted console keys when JSON.parse fails
  • Logging warnings for debugging
  • Gracefully falling back to MOTD display

134-142: LGTM!

The drag start handler correctly prevents default browser behavior and captures the initial state for the resize operation.


144-156: LGTM!

The drag move calculation correctly converts pixel deltas to viewport height units and enforces the specified bounds [30vh, 95vh].


251-273: Excellent cwd-aware VFS integration.

The environment object properly handles absolute paths (/), tilde paths (~), and relative paths by checking prefixes and prepending cwd when needed. All operations consistently use normalizePath and the cached rootVfs reference.


397-405: Good UX pattern for preventing unwanted focus.

The click handlers correctly prevent input focus when interacting with the resize handle, using a clean data-attribute selector for target detection.


439-446: LGTM!

The resize handle includes proper accessibility labeling and clear visual affordances with hover states. The data attribute allows clean event handler logic.

src/utils/console/tree.ts (3)

1-6: LGTM! Clean structure and appropriate type definitions.

The imports, type definitions, and command export are well-structured. The completion configuration correctly specifies path completion and supported flags.

Also applies to: 146-151


105-126: Path resolution and validation logic looks correct.

The path resolution (line 109) properly handles the current directory, and the error handling for non-existent paths (lines 112-116) and non-directories (lines 118-121) provides clear user feedback.


73-77: Sorting logic correctly prioritizes directories.

The sort implementation properly orders directories before files and uses alphabetical sorting within each group, matching expected tree command behavior.

@kiliantyler kiliantyler merged commit 3c919d4 into main Oct 10, 2025
8 of 9 checks passed
@kiliantyler kiliantyler deleted the expand-vfs branch October 10, 2025 02:42
@coderabbitai coderabbitai bot mentioned this pull request Oct 10, 2025
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.

1 participant