Skip to content

feat: introduce Crisp commands for code simplicity auditing and management: - #247

Merged
yashdev9274 merged 1 commit into
mainfrom
supercode-cli
Jul 29, 2026
Merged

feat: introduce Crisp commands for code simplicity auditing and management:#247
yashdev9274 merged 1 commit into
mainfrom
supercode-cli

Conversation

@yashdev9274

@yashdev9274 yashdev9274 commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Description

  • Added commands: /crisp, /crisp-review, /crisp-audit, /crisp-debt, and /crisp-gain to manage and evaluate code simplicity.
  • Implemented functionality to review code against the Crisp simplicity ladder, audit for over-engineering patterns, and assess potential gains from applying Crisp principles.
  • Enhanced CLI with new configuration options for Crisp modes and integrated prompts for user guidance.
  • Updated workspace context to include Crisp principles in code reviews.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactor (no functional changes)

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

  • bun test passes
  • bun run typecheck passes
  • bun run lint passes (if applicable)

Checklist:

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works

Summary by CodeRabbit

  • New Features
    • Added Crisp controls, reviews, workspace audits, debt tracking, impact summaries, and help through new CLI commands.
    • Crisp modes now guide simplicity-focused coding in supported workflows.
    • Added Crisp review, audit, debt, and gain tools.
    • Added a new blog with category filtering, featured posts, article pages, and MDX content.
    • Added a dedicated Features marketing page.
  • Documentation
    • Added articles introducing Supercode Crisp and explaining Supercode’s development philosophy.
  • Navigation
    • Added Blog links to the site navigation and footer.

…ement:

- Added commands: /crisp, /crisp-review, /crisp-audit, /crisp-debt, and /crisp-gain to manage and evaluate code simplicity.
- Implemented functionality to review code against the Crisp simplicity ladder, audit for over-engineering patterns, and assess potential gains from applying Crisp principles.
- Enhanced CLI with new configuration options for Crisp modes and integrated prompts for user guidance.
- Updated workspace context to include Crisp principles in code reviews.
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
supercli Ready Ready Preview, Comment Jul 29, 2026 9:59am
supercli-client Ready Ready Preview, Comment Jul 29, 2026 9:59am
supercli-docs Ready Ready Preview, Comment Jul 29, 2026 9:59am

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f4938b11-c600-4814-93af-9dd3777fa3f3

📥 Commits

Reviewing files that changed from the base of the PR and between fe241d5 and 67f3a99.

⛔ Files ignored due to path filters (3)
  • apps/web/components/blog/public/supercode-crisp.png is excluded by !**/*.png
  • apps/web/public/supercode-crisp.png is excluded by !**/*.png
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (32)
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-debt.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-gain.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-help.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-review.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/index.ts
  • apps/supercode-cli/server/src/cli/crisp/config.ts
  • apps/supercode-cli/server/src/cli/crisp/index.ts
  • apps/supercode-cli/server/src/cli/crisp/prompt.ts
  • apps/supercode-cli/server/src/cli/workspace/context.ts
  • apps/supercode-cli/server/src/lib/cli-config.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-audit.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-debt.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-gain.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-review.ts
  • apps/supercode-cli/server/src/tools/registry.ts
  • apps/web/app/(pages)/blog/[slug]/page.tsx
  • apps/web/app/(pages)/blog/[slug]/post-client.tsx
  • apps/web/app/(pages)/blog/blog-client.tsx
  • apps/web/app/(pages)/blog/page.tsx
  • apps/web/app/(pages)/features/page.tsx
  • apps/web/components/blog/blog-card.tsx
  • apps/web/components/blog/featured-post.tsx
  • apps/web/components/blog/mdx-components.tsx
  • apps/web/components/homepage/footer.tsx
  • apps/web/components/homepage/navbar.tsx
  • apps/web/content/blog/introducing-supercode-crisp.mdx
  • apps/web/content/blog/why-we-built-supercode.mdx
  • apps/web/lib/blog.ts
  • apps/web/lib/utils.ts
  • apps/web/package.json
 _______________________________________
< Uniformly random comments incoming... >
 ---------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch supercode-cli

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.

@yashdev9274
yashdev9274 merged commit a6e03fc into main Jul 29, 2026
4 of 8 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🧹 Nitpick comments (9)
apps/web/app/(pages)/features/page.tsx (2)

199-199: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use cn() consistently for conditional classes. This preserves Tailwind conflict handling and follows the web-app class composition convention.

  • apps/web/app/(pages)/features/page.tsx#L199-L199: compose the base classes and optional className with cn().
  • apps/web/app/(pages)/features/page.tsx#L460-L462: compose the base icon classes and conditional rotation with cn().

As per coding guidelines, use cn() from @/lib/utils for conditional classes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(pages)/features/page.tsx at line 199, Update the container
class composition at apps/web/app/(pages)/features/page.tsx:199 to use cn() for
the base classes and optional className, and update the icon class composition
at apps/web/app/(pages)/features/page.tsx:460-462 to use cn() for its base
classes and conditional rotation; import cn from `@/lib/utils` if needed.

Source: Coding guidelines


290-290: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace repeated hardcoded colors with semantic tokens. Theme-aware text utilities should represent the same visual role in both headings.

  • apps/web/app/(pages)/features/page.tsx#L290-L290: replace text-[#A1A1AA] with the appropriate semantic text token.
  • apps/web/app/(pages)/features/page.tsx#L493-L493: use that same semantic token for the CTA heading.

As per coding guidelines, prefer semantic CSS variables over hardcoded values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(pages)/features/page.tsx at line 290, Replace the hardcoded
text color in the heading at apps/web/app/(pages)/features/page.tsx lines
290-290 with the appropriate semantic text token, and apply the same token to
the CTA heading at lines 493-493. Preserve the existing layout and styling while
ensuring both headings use theme-aware semantic utilities.

Source: Coding guidelines

apps/supercode-cli/server/src/cli/crisp/config.ts (1)

1-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Use Bun filesystem APIs for Crisp configuration.

This new server path reads configuration through Node fs; migrate the config API and its callers to async Bun filesystem operations instead. As per coding guidelines, “Prefer Bun.file over Node.js node:fs readFile/writeFile for file operations.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/supercode-cli/server/src/cli/crisp/config.ts` around lines 1 - 25,
Migrate getCrispModeSync and its callers to an asynchronous configuration API
using Bun.file for reading CONFIG_FILE, removing the Node fs dependency.
Preserve the existing JSON parsing, CRISP_MODES validation, and fallback
behavior while updating every caller to await the new async function.

Source: Coding guidelines

apps/web/components/blog/featured-post.tsx (2)

1-74: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use PascalCase component filenames.

  • apps/web/components/blog/featured-post.tsx#L1-L74: rename to a PascalCase component filename, such as FeaturedPost.tsx, and update imports.
  • apps/web/app/(pages)/blog/[slug]/post-client.tsx#L1-L101: rename to a PascalCase component filename, such as PostPage.tsx, and update the route import.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/blog/featured-post.tsx` around lines 1 - 74, Rename the
component file containing FeaturedPost to FeaturedPost.tsx and update every
import referencing it. Rename apps/web/app/(pages)/blog/[slug]/post-client.tsx
to PostPage.tsx and update the route import accordingly; no direct code changes
are required beyond these filename and import updates.

Source: Coding guidelines


8-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use type for these closed props contracts.

  • apps/web/components/blog/featured-post.tsx#L8-L10: replace interface FeaturedPostProps with a type.
  • apps/web/app/(pages)/blog/[slug]/post-client.tsx#L10-L13: replace interface PostPageProps with a type.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/blog/featured-post.tsx` around lines 8 - 10, Replace the
closed props-contract interfaces with type aliases in FeaturedPostProps at
apps/web/components/blog/featured-post.tsx lines 8-10 and PostPageProps at
apps/web/app/(pages)/blog/[slug]/post-client.tsx lines 10-13, preserving each
existing property definition and usage.

Source: Coding guidelines

apps/web/components/blog/mdx-components.tsx (1)

149-153: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the hardcoded code-block background token.

Use an existing semantic color token, or add a dedicated code-surface variable, instead of bg-[#0a0a0a] so the component follows the site theme contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/blog/mdx-components.tsx` around lines 149 - 153, Update
the className in the pre code-block component to remove the hardcoded
bg-[`#0a0a0a`] value and use an existing semantic background token, or the
established dedicated code-surface variable if one exists. Preserve the
remaining styling and className composition unchanged.

Source: Coding guidelines

apps/web/lib/blog.ts (1)

1-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Separate import groups consistently.

  • apps/web/lib/blog.ts#L1-L5: separate Node built-ins, external packages, and relative imports with blank lines.
  • apps/web/components/blog/featured-post.tsx#L3-L6: separate Next, external, and alias imports with blank lines.
  • apps/web/components/blog/mdx-components.tsx#L1-L2: place the Next import before external imports and separate groups.
  • apps/web/app/(pages)/blog/[slug]/page.tsx#L1-L6: separate Next, external, alias, and relative imports with blank lines.
  • apps/web/app/(pages)/blog/[slug]/post-client.tsx#L3-L8: place Next before external imports and separate import groups.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/blog.ts` around lines 1 - 5, Organize imports into consistently
separated groups: in apps/web/lib/blog.ts lines 1-5, group Node built-ins,
external packages, and relative imports; in
apps/web/components/blog/featured-post.tsx lines 3-6, group Next, external, and
alias imports; in apps/web/components/blog/mdx-components.tsx lines 1-2, place
Next imports before external imports with blank lines; in
apps/web/app/(pages)/blog/[slug]/page.tsx lines 1-6, group Next, external,
alias, and relative imports; and in
apps/web/app/(pages)/blog/[slug]/post-client.tsx lines 3-8, place Next imports
before external imports and separate each group.

Source: Coding guidelines

apps/web/app/(pages)/blog/blog-client.tsx (2)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename new component files to PascalCase.

  • apps/web/app/(pages)/blog/blog-client.tsx#L1-L1: rename the file to a PascalCase component filename such as BlogPage.tsx and update imports.
  • apps/web/components/blog/blog-card.tsx#L1-L1: rename the file to BlogCard.tsx and update imports.

As per coding guidelines, TypeScript/TSX component filenames must use PascalCase.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(pages)/blog/blog-client.tsx at line 1, Rename
apps/web/app/(pages)/blog/blog-client.tsx to a PascalCase component filename
such as BlogPage.tsx and update all imports; rename
apps/web/components/blog/blog-card.tsx to BlogCard.tsx and update all imports
referencing it.

Source: Coding guidelines


3-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Separate dependency groups in the new web imports.

The new files omit the required blank lines between external libraries, internal aliases, and relative imports.

  • apps/web/app/(pages)/blog/blog-client.tsx#L3-L9: separate external library imports from @/... imports.
  • apps/web/app/(pages)/blog/page.tsx#L1-L2: separate @/... imports from the relative ./blog-client import.
  • apps/web/components/blog/blog-card.tsx#L3-L6: separate external library imports from @/... imports.

As per coding guidelines, web imports require React/Next → external libraries → internal aliases → relative imports, with blank lines between groups.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(pages)/blog/blog-client.tsx around lines 3 - 9, Separate
imports into the required groups with blank lines: in
apps/web/app/(pages)/blog/blog-client.tsx lines 3-9, place external libraries
before internal `@/` aliases; in apps/web/app/(pages)/blog/page.tsx lines 1-2,
separate `@/` imports from the relative ./blog-client import; and in
apps/web/components/blog/blog-card.tsx lines 3-6, separate external libraries
from `@/` imports. Preserve the React/Next → external libraries → internal aliases
→ relative imports order.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts`:
- Around line 2-14: Replace execSync in crispAuditCommand with execFileSync,
passing the fd options as fixed argument entries and using process.cwd() through
the cwd option instead of interpolating it into a shell command. Preserve the
existing file extensions, exclusions, depth limit, and UTF-8 output behavior.

In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-debt.ts`:
- Around line 11-18: Update the scan in the command’s marker-counting loop to
include the intended workspace comment file types, including files using # and
-- comments, rather than limiting ripgrep to the current TypeScript and
JavaScript filters. For each matching result line, iterate all occurrences with
matchAll using the global Crisp-marker pattern, and increment tagCounts for
every captured rung instead of only the first match.

In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-help.ts`:
- Around line 38-42: Update the configuration guidance in the Crisp help command
to document the supported ~/.config/supercode/cli-config.json file and its
crispMode field, replacing the unsupported CRISP_DEFAULT_MODE and crisp.json
examples. Do not implement new configuration inputs; keep the help text aligned
with the existing config implementation.

In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-review.ts`:
- Around line 12-14: Update the diff assembly in the crisp-review command so it
includes both staged and unstaged output rather than selecting only the staged
result. Preserve each command’s captured content and combine them in order,
including empty results safely.

In `@apps/supercode-cli/server/src/cli/workspace/context.ts`:
- Around line 219-228: Update pushCrispSection to resolve the Crisp mode through
the shared CrispMode integration or an exported resolver from
src/cli/crisp/index.ts, rather than reading cli-config.json#crispMode directly.
Ensure it honors CRISP_DEFAULT_MODE and ~/.config/supercode/crisp.json, and
replace the current fs.readFileSync usage with the available Bun filesystem API
while preserving the existing valid-mode filtering and prompt behavior.

In `@apps/web/app/`(pages)/blog/blog-client.tsx:
- Around line 18-20: Update BlogPage to use its featured prop and render the
FeaturedPost component for the supplied featured posts. Ensure posts marked
featured from page.tsx are visibly presented while preserving the existing
category filtering and regular post rendering.

In `@apps/web/app/`(pages)/features/page.tsx:
- Line 270: Add the matching top anchor to the page’s main element by setting
id="top" on the <main> returned by the page component. Preserve its existing
classes and structure so Footer’s href="`#top`" link scrolls to the page start.
- Around line 452-466: Add aria-expanded={isOpen} to the FAQ toggle button in
the FAQ rendering block so assistive technology receives the current expansion
state; if the answer content has assigned IDs, also connect the button with a
matching aria-controls value.
- Around line 3-7: Update the imports in the features page to explicitly import
type ReactNode from React, group the React/Next imports together with Link, and
preserve the existing component imports in their appropriate group. Replace any
React.ReactNode usage with the locally imported ReactNode type.

In `@apps/web/components/blog/mdx-components.tsx`:
- Around line 4-6: In the MDX components module, remove the local cn helper and
import the shared cn from `@/lib/utils`. Update existing usages to use that
imported helper, preserving current class composition while enabling clsx and
tailwind-merge behavior.

In `@apps/web/lib/blog.ts`:
- Around line 75-76: Update the BlogPage rendering flow to consume the
collection returned by getFeaturedPosts(), ensuring featured posts render
through the existing FeaturedPost component; alternatively, remove
getFeaturedPosts() and its unused featured contract if featured rendering is not
intended. Keep the behavior consistent with the chosen contract.
- Around line 47-52: Validate the route-derived slug in getPostBySlug before
constructing or reading filePath, rejecting absolute paths and traversal
segments that could escape BLOG_DIR. Ensure the resolved candidate remains
contained within BLOG_DIR, returning null for invalid slugs while preserving
normal valid-slug lookup behavior.

In `@apps/web/lib/utils.ts`:
- Around line 26-31: Update formatDate to specify the UTC timezone in its
toLocaleDateString options, preserving the existing en-US locale and
year/month/day formatting so date-only values render consistently across server
and client time zones.

---

Nitpick comments:
In `@apps/supercode-cli/server/src/cli/crisp/config.ts`:
- Around line 1-25: Migrate getCrispModeSync and its callers to an asynchronous
configuration API using Bun.file for reading CONFIG_FILE, removing the Node fs
dependency. Preserve the existing JSON parsing, CRISP_MODES validation, and
fallback behavior while updating every caller to await the new async function.

In `@apps/web/app/`(pages)/blog/blog-client.tsx:
- Line 1: Rename apps/web/app/(pages)/blog/blog-client.tsx to a PascalCase
component filename such as BlogPage.tsx and update all imports; rename
apps/web/components/blog/blog-card.tsx to BlogCard.tsx and update all imports
referencing it.
- Around line 3-9: Separate imports into the required groups with blank lines:
in apps/web/app/(pages)/blog/blog-client.tsx lines 3-9, place external libraries
before internal `@/` aliases; in apps/web/app/(pages)/blog/page.tsx lines 1-2,
separate `@/` imports from the relative ./blog-client import; and in
apps/web/components/blog/blog-card.tsx lines 3-6, separate external libraries
from `@/` imports. Preserve the React/Next → external libraries → internal aliases
→ relative imports order.

In `@apps/web/app/`(pages)/features/page.tsx:
- Line 199: Update the container class composition at
apps/web/app/(pages)/features/page.tsx:199 to use cn() for the base classes and
optional className, and update the icon class composition at
apps/web/app/(pages)/features/page.tsx:460-462 to use cn() for its base classes
and conditional rotation; import cn from `@/lib/utils` if needed.
- Line 290: Replace the hardcoded text color in the heading at
apps/web/app/(pages)/features/page.tsx lines 290-290 with the appropriate
semantic text token, and apply the same token to the CTA heading at lines
493-493. Preserve the existing layout and styling while ensuring both headings
use theme-aware semantic utilities.

In `@apps/web/components/blog/featured-post.tsx`:
- Around line 1-74: Rename the component file containing FeaturedPost to
FeaturedPost.tsx and update every import referencing it. Rename
apps/web/app/(pages)/blog/[slug]/post-client.tsx to PostPage.tsx and update the
route import accordingly; no direct code changes are required beyond these
filename and import updates.
- Around line 8-10: Replace the closed props-contract interfaces with type
aliases in FeaturedPostProps at apps/web/components/blog/featured-post.tsx lines
8-10 and PostPageProps at apps/web/app/(pages)/blog/[slug]/post-client.tsx lines
10-13, preserving each existing property definition and usage.

In `@apps/web/components/blog/mdx-components.tsx`:
- Around line 149-153: Update the className in the pre code-block component to
remove the hardcoded bg-[`#0a0a0a`] value and use an existing semantic background
token, or the established dedicated code-surface variable if one exists.
Preserve the remaining styling and className composition unchanged.

In `@apps/web/lib/blog.ts`:
- Around line 1-5: Organize imports into consistently separated groups: in
apps/web/lib/blog.ts lines 1-5, group Node built-ins, external packages, and
relative imports; in apps/web/components/blog/featured-post.tsx lines 3-6, group
Next, external, and alias imports; in
apps/web/components/blog/mdx-components.tsx lines 1-2, place Next imports before
external imports with blank lines; in apps/web/app/(pages)/blog/[slug]/page.tsx
lines 1-6, group Next, external, alias, and relative imports; and in
apps/web/app/(pages)/blog/[slug]/post-client.tsx lines 3-8, place Next imports
before external imports and separate each group.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f4938b11-c600-4814-93af-9dd3777fa3f3

📥 Commits

Reviewing files that changed from the base of the PR and between fe241d5 and 67f3a99.

⛔ Files ignored due to path filters (3)
  • apps/web/components/blog/public/supercode-crisp.png is excluded by !**/*.png
  • apps/web/public/supercode-crisp.png is excluded by !**/*.png
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (32)
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-debt.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-gain.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-help.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-review.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/crisp.ts
  • apps/supercode-cli/server/src/cli/commands/slashCommands/index.ts
  • apps/supercode-cli/server/src/cli/crisp/config.ts
  • apps/supercode-cli/server/src/cli/crisp/index.ts
  • apps/supercode-cli/server/src/cli/crisp/prompt.ts
  • apps/supercode-cli/server/src/cli/workspace/context.ts
  • apps/supercode-cli/server/src/lib/cli-config.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-audit.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-debt.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-gain.ts
  • apps/supercode-cli/server/src/tools/definitions/crisp-review.ts
  • apps/supercode-cli/server/src/tools/registry.ts
  • apps/web/app/(pages)/blog/[slug]/page.tsx
  • apps/web/app/(pages)/blog/[slug]/post-client.tsx
  • apps/web/app/(pages)/blog/blog-client.tsx
  • apps/web/app/(pages)/blog/page.tsx
  • apps/web/app/(pages)/features/page.tsx
  • apps/web/components/blog/blog-card.tsx
  • apps/web/components/blog/featured-post.tsx
  • apps/web/components/blog/mdx-components.tsx
  • apps/web/components/homepage/footer.tsx
  • apps/web/components/homepage/navbar.tsx
  • apps/web/content/blog/introducing-supercode-crisp.mdx
  • apps/web/content/blog/why-we-built-supercode.mdx
  • apps/web/lib/blog.ts
  • apps/web/lib/utils.ts
  • apps/web/package.json

Comment on lines +2 to +14
import { execSync } from "node:child_process"
import { theme, frame } from "src/cli/utils/tui.ts"
import { getCrispModeSync } from "src/cli/crisp/index.ts"
import type { SlashCommandResult } from "./index.ts"

export async function crispAuditCommand(argsStr: string): Promise<SlashCommandResult> {
const mode = getCrispModeSync()
const focus = argsStr.trim() || "all"
const modeLabel = mode === "off" ? "full" : mode

let fileList = ""
try {
fileList = execSync(`fd -e ts -e tsx -e js -e jsx --exclude node_modules --exclude dist --exclude .git --max-depth 6 . ${process.cwd()}`, { encoding: "utf-8" })

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | grep -F 'apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts' || true

echo "== file excerpt =="
if [ -f apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts ]; then
  wc -l apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts
  cat -n apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts
fi

echo "== child_process imports/usages in server TypeScript =="
rg -n "exec(Sync|File)(Sync)?|child_process" apps/supercode-cli/server -g '*.ts' -g '*.tsx' -g '*.js' || true

echo "== deterministic shell behavior probe =="
node - <<'JS'
const { execSync, execFileSync } = require("node:child_process")
const dir = "/tmp/crisp-audit-probe; printf 'shell injection executed' > /tmp/crisp-audit-probe-payload.txt"
const safeDir = "/tmp/crisp-audit-probe-safe"
try {
  execSync(`date +%s > ${dir}/payload.txt`, { stdio: "ignore", encoding: "utf8" })
  console.log("execSync: payload exists", require("node:fs").existsSync(`${dir}/payload.txt`))
} catch (e) {
  console.log("execSync_error", e.message.trim().split("\n")[0])
}
try {
  execFileSync("date", ["+%s"], { cwd: dir, encoding: "utf8" })
  console.log("execFileSync: payload_exists=", require("node:fs").existsSync(`${dir}/payload.txt`))
} catch (e) {
  console.log("execFileSync_error", e.message.trim().split("\n")[0])
}
require("node:fs").rmSync("/tmp/crisp-audit-probe", { recursive: true, force: true })
require("node:fs").rmSync("/tmp/crisp-audit-probe-safe", { recursive: true, force: true })
JS

Repository: yashdev9274/supercli

Length of output: 5729


🌐 Web query:

Node.js child_process execSync shell command execution default shell template string path whitespace documentation

💡 Result:

The Node.js child_process.execSync function executes a command inside a shell [1][2]. Because it operates via a shell, it interprets the provided command string as a set of arguments, where spaces typically act as delimiters [3][4]. Key technical details include: 1. Shell Execution and Whitespace: When you pass a command string containing whitespace to execSync, the underlying shell (e.g., /bin/sh or cmd.exe) parses those spaces as separators between the executable and its arguments [3][4]. To include paths containing whitespace, you must wrap the path in double quotes within the command string to ensure the shell interprets the entire path as a single argument [3][4]. 2. Default Shell: By default, execSync executes commands using '/bin/sh' on Unix-like systems and process.env.ComSpec (usually cmd.exe) on Windows [2][5]. This default behavior can be overridden using the shell option in the options object [2][6]. 3. Security Warning: Because execSync processes the command string directly through a shell, it is vulnerable to shell injection [2][5]. Node.js documentation explicitly warns against passing unsanitized user input to this function, as shell metacharacters (e.g., |, &,;, $) can be used to execute arbitrary commands [2][4]. 4. Recommended Alternatives: For scenarios involving paths with spaces or when user input is involved, it is generally safer and cleaner to use child_process.execFileSync or child_process.spawnSync [7][3]. These methods allow you to pass the executable and its arguments as separate array elements, which avoids shell interpretation entirely and eliminates the need for manual quoting or escaping of paths [7][3].

Citations:


Avoid shell interpolation of the workspace path.

execSync runs through a shell, and process.cwd() is interpolated into the command string. A workspace path with spaces breaks the scan, and shell metacharacters in the path can execute commands. Use execFileSync with fixed fd arguments and the cwd option.

🧰 Tools
🪛 OpenGrep (1.26.0)

[ERROR] 14-14: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-audit.ts`
around lines 2 - 14, Replace execSync in crispAuditCommand with execFileSync,
passing the fd options as fixed argument entries and using process.cwd() through
the cwd option instead of interpolating it into a shell command. Preserve the
existing file extensions, exclusions, depth limit, and UTF-8 output behavior.

Source: Linters/SAST tools

Comment on lines +11 to +18
rawMatches = execSync("rg -n '\\[crisp:\\d+\\]' --type ts --type tsx --type js --type jsx -g '!node_modules' -g '!dist'", { encoding: "utf-8" })
const matches = rawMatches.split("\n").filter(Boolean)
for (const m of matches) {
const tag = m.match(/\[crisp:(\d+)\]/)
if (tag) {
const rung = tag[1]!
tagCounts[rung] = (tagCounts[rung] ?? 0) + 1
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scan and count every Crisp marker.

The type filters exclude the # and -- comment styles this command claims to detect, and match() counts only the first [crisp:N] on a line. This can report a false-clean or undercounted workspace ledger. Scan the intended workspace file set and iterate matchAll(/\[crisp:(\d+)\]/g) for each result line.

Also applies to: 24-24

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-debt.ts`
around lines 11 - 18, Update the scan in the command’s marker-counting loop to
include the intended workspace comment file types, including files using # and
-- comments, rather than limiting ripgrep to the current TypeScript and
JavaScript filters. For each matching result line, iterate all occurrences with
matchAll using the global Crisp-marker pattern, and increment tagCounts for
every captured rung instead of only the first match.

Comment on lines +38 to +42
chalk.hex(theme.amber).bold("Configure default"),
chalk.hex(theme.muted)("Environment variable (highest priority):"),
` ${chalk.hex(theme.greenDim)("export CRISP_DEFAULT_MODE=ultra")}`,
chalk.hex(theme.muted)("Config file (~/.config/supercode/crisp.json):"),
` ${chalk.hex(theme.greenDim)('{"defaultMode": "lite"}')}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Document the configuration mechanism that actually exists.

Neither CRISP_DEFAULT_MODE nor ~/.config/supercode/crisp.json is read by the supplied config implementation. Users following this help cannot configure Crisp. Either implement those inputs or document ~/.config/supercode/cli-config.json with its crispMode field.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-help.ts`
around lines 38 - 42, Update the configuration guidance in the Crisp help
command to document the supported ~/.config/supercode/cli-config.json file and
its crispMode field, replacing the unsupported CRISP_DEFAULT_MODE and crisp.json
examples. Do not implement new configuration inputs; keep the help text aligned
with the existing config implementation.

Comment on lines +12 to +14
const staged = execSync("git diff --cached", { encoding: "utf-8" })
const unstaged = execSync("git diff", { encoding: "utf-8" })
diff = staged || unstaged

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include both staged and unstaged changes in the review.

When both diffs exist, staged || unstaged discards the unstaged diff, so /crisp-review misses part of the working tree.

Proposed fix
-    diff = staged || unstaged
+    diff = [staged, unstaged].filter(Boolean).join("\n")
📝 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 staged = execSync("git diff --cached", { encoding: "utf-8" })
const unstaged = execSync("git diff", { encoding: "utf-8" })
diff = staged || unstaged
const staged = execSync("git diff --cached", { encoding: "utf-8" })
const unstaged = execSync("git diff", { encoding: "utf-8" })
diff = [staged, unstaged].filter(Boolean).join("\n")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-review.ts`
around lines 12 - 14, Update the diff assembly in the crisp-review command so it
includes both staged and unstaged output rather than selecting only the staged
result. Preserve each command’s captured content and combine them in order,
including empty results safely.

Comment on lines +219 to +228
function pushCrispSection(lines: string[]): void {
const configPath = path.join(os.homedir(), ".config", "supercode", "cli-config.json")
let mode: string = "off"
try {
const data = fs.readFileSync(configPath, "utf-8")
const config = JSON.parse(data)
if (["off", "lite", "full", "ultra"].includes(config.crispMode)) {
mode = config.crispMode
}
} catch {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Tracked files around crisp/context:"
git ls-files | rg 'apps/supercode-cli/server/src/cli/(workspace/context.ts|.*crisp.*|.*help.*crisp.*|.*crisp.*help.*)|apps/supercode-cli/server/src' | rg -n 'crisp|context' || true

echo
echo "context.ts outline:"
ast-grep outline apps/supercode-cli/server/src/cli/workspace/context.ts --view compact || true

echo
echo "Relevant context.ts lines:"
sed -n '180,260p' apps/supercode-cli/server/src/cli/workspace/context.ts

echo
echo "Search Crisp config references:"
rg -n "crispMode|CRISP_DEFAULT_MODE|crisp\.json|cli-config\.json|pushCrispSection|Crisp" apps/supercode-cli/server/src -S || true

Repository: yashdev9274/supercli

Length of output: 13836


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "cli-config file:"
sed -n '1,120p' apps/supercode-cli/server/src/lib/cli-config.ts

echo
echo "crisp config/index:"
sed -n '1,120p' apps/supercode-cli/server/src/cli/crisp/config.ts
echo
sed -n '1,20p' apps/supercode-cli/server/src/cli/crisp/index.ts

echo
echo "crisp-help relevant lines:"
sed -n '1,90p' apps/supercode-cli/server/src/cli/commands/slashCommands/crisp-help.ts

echo
echo "context.ts top imports and prompt/ladder call sites:"
sed -n '1,55p' apps/supercode-cli/server/src/cli/workspace/context.ts
rg -n "buildPrompt|function buildPrompt|export function buildPrompt|crispLadderPrompt|pushCrispSection" apps/supercode-cli/server/src/cli/workspace/context.ts -S
sed -n '140,195p' apps/supercode-cli/server/src/cli/workspace/context.ts
sed -n '260,320p' apps/supercode-cli/server/src/cli/workspace/context.ts

echo
echo "Search for CRISP_DEFAULT_MODE outside crisp/help:"
rg -n "CRISP_DEFAULT_MODE|~/.config/supercode/crisp\.json|minimize_ladder|crisp\.json" apps/supercode-cli/server/src -S || true

Repository: yashdev9274/supercli

Length of output: 18507


Use the shared Crisp mode source when injecting the prompt.

crisp-help.ts documents CRISP_DEFAULT_MODE / ~/.config/supercode/crisp.json, but pushCrispSection() reads only cli-config.json#crispMode. A user can set the documented default and still omit Crisp from this system prompt. Reuse src/cli/crisp/index.ts’s CrispMode integration here or export a shared resolver, and use the available Bun filesystem APIs for the file read.

🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 222-222: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(configPath, "utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/supercode-cli/server/src/cli/workspace/context.ts` around lines 219 -
228, Update pushCrispSection to resolve the Crisp mode through the shared
CrispMode integration or an exported resolver from src/cli/crisp/index.ts,
rather than reading cli-config.json#crispMode directly. Ensure it honors
CRISP_DEFAULT_MODE and ~/.config/supercode/crisp.json, and replace the current
fs.readFileSync usage with the available Bun filesystem API while preserving the
existing valid-mode filtering and prompt behavior.

Source: Coding guidelines

Comment on lines +452 to +466
<button
onClick={() => setExpandedFaq(isOpen ? null : i)}
className="w-full flex items-center justify-between gap-4 px-5 py-4 text-left transition-all duration-200 active:scale-[0.99]"
>
<span className="text-[14px] font-medium text-foreground font-mono">
{item.q}
</span>
<span
className={`text-muted-foreground text-lg transition-transform duration-200 shrink-0 ${
isOpen ? "rotate-45" : ""
}`}
>
+
</span>
</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Expose FAQ expansion state to assistive technology.

The button toggles content visually but does not provide aria-expanded. Add aria-expanded={isOpen} (and an aria-controls target if assigning answer IDs).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(pages)/features/page.tsx around lines 452 - 466, Add
aria-expanded={isOpen} to the FAQ toggle button in the FAQ rendering block so
assistive technology receives the current expansion state; if the answer content
has assigned IDs, also connect the button with a matching aria-controls value.

Comment on lines +4 to +6
function cn(...classes: (string | undefined | false)[]) {
return classes.filter(Boolean).join(" ")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use the shared cn helper.

The local helper bypasses the required clsx + tailwind-merge behavior, so MDX-provided classes can conflict with base styles. Import cn from @/lib/utils and remove this helper.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/blog/mdx-components.tsx` around lines 4 - 6, In the MDX
components module, remove the local cn helper and import the shared cn from
`@/lib/utils`. Update existing usages to use that imported helper, preserving
current class composition while enabling clsx and tailwind-merge behavior.

Source: Coding guidelines

Comment thread apps/web/lib/blog.ts
Comment on lines +47 to +52
export function getPostBySlug(slug: string): BlogPost | null {
ensureBlogDir()
const filePath = path.join(BLOG_DIR, `${slug}.mdx`)

if (!fs.existsSync(filePath)) {
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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Contain slug lookups within the blog directory.

slug is route-derived and is joined into a filesystem path without validation. Traversal segments can resolve to readable .mdx files outside content/blog, which are then compiled and returned by the public post route.

Proposed fix
 export function getPostBySlug(slug: string): BlogPost | null {
   ensureBlogDir()
-  const filePath = path.join(BLOG_DIR, `${slug}.mdx`)
+  const filePath = path.resolve(BLOG_DIR, `${slug}.mdx`)
+  const relativePath = path.relative(BLOG_DIR, filePath)
+
+  if (
+    relativePath.startsWith(`..${path.sep}`) ||
+    path.isAbsolute(relativePath)
+  ) {
+    return null
+  }

   if (!fs.existsSync(filePath)) {
📝 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
export function getPostBySlug(slug: string): BlogPost | null {
ensureBlogDir()
const filePath = path.join(BLOG_DIR, `${slug}.mdx`)
if (!fs.existsSync(filePath)) {
return null
export function getPostBySlug(slug: string): BlogPost | null {
ensureBlogDir()
const filePath = path.resolve(BLOG_DIR, `${slug}.mdx`)
const relativePath = path.relative(BLOG_DIR, filePath)
if (
relativePath.startsWith(`..${path.sep}`) ||
path.isAbsolute(relativePath)
) {
return null
}
if (!fs.existsSync(filePath)) {
return null
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/blog.ts` around lines 47 - 52, Validate the route-derived slug
in getPostBySlug before constructing or reading filePath, rejecting absolute
paths and traversal segments that could escape BLOG_DIR. Ensure the resolved
candidate remains contained within BLOG_DIR, returning null for invalid slugs
while preserving normal valid-slug lookup behavior.

Source: Linters/SAST tools

Comment thread apps/web/lib/blog.ts
Comment on lines +75 to +76
export function getFeaturedPosts(): BlogPostMeta[] {
return getAllPosts().filter((p) => p.featured)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the featured flag affect the listing.

getFeaturedPosts() is passed into BlogPage, but the supplied BlogPage implementation never reads featured; FeaturedPost is therefore never rendered. Either render the featured collection or remove the unused feature contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/blog.ts` around lines 75 - 76, Update the BlogPage rendering
flow to consume the collection returned by getFeaturedPosts(), ensuring featured
posts render through the existing FeaturedPost component; alternatively, remove
getFeaturedPosts() and its unused featured contract if featured rendering is not
intended. Keep the behavior consistent with the chosen contract.

Comment thread apps/web/lib/utils.ts
Comment on lines +26 to +31
export function formatDate(dateString: string): string {
return new Date(dateString).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate file =="
git ls-files | grep -F 'apps/web/lib/utils.ts' || true

echo "== Inspect utils excerpt =="
if [ -f apps/web/lib/utils.ts ]; then
  sed -n '1,60p' apps/web/lib/utils.ts | cat -n
fi

echo "== Find formatDate usages =="
rg -n "formatDate\(" apps/web || true

echo "== Check environment / next config hints =="
for f in package.json apps/web/package.json next.config.* apps/web/next.config.*; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    sed -n '1,160p' "$f" | grep -Ei '(date|next|environment|tz|timezone)' || true
  fi
done

echo "== Behavioral probe if Node available =="
node - <<'JS'
try {
  const TZs = ["America/New_York", "America/Los_Angeles", "UTC"];
  for (const tz of TZs) {
    process.env.TZ = tz;
    const d = new Date("2025-07-29");
    const local = d.toLocaleDateString("en-US", {
      year: "numeric",
      month: "long",
      day: "numeric",
    });
    const utc = d.toLocaleDateString("en-US", {
      year: "numeric",
      month: "long",
      day: "numeric",
      timeZone: "UTC",
    });
    console.log(`${tz}: Date(${JSON.stringify("2025-07-29")}) => local=${JSON.stringify(local)} utc=${JSON.stringify(utc)} iso=${d.toISOString()}`);
  }
} catch (e) {
  console.error(e && e.stack ? e.stack : e.message);
  process.exit(1);
}
JS

Repository: yashdev9274/supercli

Length of output: 2500


Format calendar dates in UTC.

Date-only values like "2025-07-29" parse at UTC midnight, so clients in U.S. time zones can render them as July 28. Set the locale timezone to UTC for Server Components/client UI to keep server/client rendering consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/utils.ts` around lines 26 - 31, Update formatDate to specify the
UTC timezone in its toLocaleDateString options, preserving the existing en-US
locale and year/month/day formatting so date-only values render consistently
across server and client time zones.

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