Skip to content

switch to tsup for most packages ( ui using tsc ) with dev watch scripts - #2

Open
MKorolyova wants to merge 2 commits into
devfrom
HK-250
Open

switch to tsup for most packages ( ui using tsc ) with dev watch scripts#2
MKorolyova wants to merge 2 commits into
devfrom
HK-250

Conversation

@MKorolyova

@MKorolyova MKorolyova commented Aug 6, 2026

Copy link
Copy Markdown
  • Replace tsc/tsdown with tsup for consistent builds
  • Add dev scripts with --watch for live recompilation
  • Increase turbo concurrency to 14 for persistent tasks (according to amount of modules)

Summary by CodeRabbit

  • Refactor
    • Standardized package builds across the project for CommonJS, ESM, and TypeScript declarations.
    • Added watch-mode development workflows for faster local iteration.
    • Improved package entry points and CLI module exports for more consistent integration.
    • Updated build orchestration to cache generated output correctly and support concurrent development tasks.
    • Added automated test task coordination across packages.
    • Prevented generated build artifacts from being tracked in source control.

- Replace tsc/tsdown with tsup for consistent builds
- Add dev scripts with --watch for live recompilation
- Increase turbo concurrency to 14 for persistent tasks (according to amount of modules)
@linear-code

linear-code Bot commented Aug 6, 2026

Copy link
Copy Markdown

HK-250

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@MKorolyova, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c487875c-5c3d-4fe5-8945-0cfc3f856f6e

📥 Commits

Reviewing files that changed from the base of the PR and between 4e3451e and 0490472.

📒 Files selected for processing (1)
  • turbo.json
📝 Walkthrough

Walkthrough

Changes

Build standardization

Layer / File(s) Summary
Package build pipelines
package.json, packages/*/package.json, packages/*/.gitignore
Package builds use tsup for CommonJS, ESM, and declaration output. Development scripts add watch mode. Generated dist directories are ignored.
Package entrypoint and multi-entry wiring
packages/auth-better-auth/package.json, packages/cli/package.json, packages/config/package.json, packages/plugin-notifications-email/package.json
Package exports now reference built files, add the CLI subpath, or define ESM module entries. Selected packages add server-only and configure multiple build entries.
Turbo task orchestration
turbo.json
Turbo build outputs now use dist/**. Persistent development and cached test tasks depend on upstream builds.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: joshuasilva414

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: switching most packages to tsup, retaining tsc for UI, and adding development watch scripts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch HK-250

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.

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

🧹 Nitpick comments (2)
packages/ui/package.json (1)

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

Remove the unused tsup dependency from packages/ui/package.json.

@hackkit/ui runs tsc for build, dev, and typecheck, and no UI package script invokes tsup. Keep tsc and remove tsup from devDependencies.

🤖 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 `@packages/ui/package.json` at line 54, Remove the unused tsup entry from the
devDependencies in packages/ui/package.json, while preserving the existing
tsc-based build, dev, and typecheck scripts and all other dependencies.
packages/cli/package.json (1)

38-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Reconfirm the build-tool choice before standardizing on tsup.

The upstream tsup repository currently states that tsup is no longer actively maintained and recommends tsdown. This PR reverses the existing tsdown choice across multiple packages. Verify the reversal before merging and document the supported build-tool and TypeScript versions. (github.com)

  • packages/cli/package.json#L38-L38: Reconfirm replacing tsdown with tsup.
  • packages/blob-s3/package.json#L28-L28: Reconfirm adding tsup as the package build tool.
  • packages/config/package.json#L30-L30: Reconfirm adding tsup after removing the previous Node type dependency.
  • packages/core/package.json#L27-L27: Reconfirm adding tsup to the shared build standard.
  • packages/db-drizzle/package.json#L43-L43: Reconfirm adding tsup for the multi-entry build.
  • packages/next/package.json#L33-L36: Reconfirm adding tsup while removing the previous build dependency.
  • packages/plugin-discord/package.json#L50-L50: Reconfirm adding tsup to the package build.
🤖 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 `@packages/cli/package.json` at line 38, Reconfirm the supported build-tool
choice and TypeScript versions before standardizing on tsup, then document the
decision. Review the tsup dependency changes in packages/cli/package.json
(38-38), packages/blob-s3/package.json (28-28), packages/config/package.json
(30-30), packages/core/package.json (27-27), packages/db-drizzle/package.json
(43-43), packages/next/package.json (33-36), and
packages/plugin-discord/package.json (50-50); update each affected package
consistently if tsdown remains the supported choice, or retain tsup only with
documented version support and rationale.

Source: MCP tools

🤖 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 `@packages/cli/package.json`:
- Around line 14-19: Add require export targets to the "." and "./cli" entries
in packages/cli/package.json, pointing to the emitted CommonJS files with their
actual CJS extensions. Preserve the existing types and import targets while
making both package entry points available to require consumers.

In `@packages/next/package.json`:
- Around line 33-36: Restore Node type declarations for
packages/cli/package.json at line 38 and packages/config/package.json at line 30
by adding `@types/node` directly to both packages or configuring a shared tsconfig
they extend with Node types; packages/next/package.json at lines 33-36 and
packages/blob-s3/package.json at line 28 require no direct change.

In `@packages/plugin-notifications-email/package.json`:
- Around line 11-12: Update the package export map’s "." entry so import
resolves to the generated ESM runtime file under dist instead of src/index.ts,
and retain or add a require/default mapping to the generated CJS file unless the
package is explicitly ESM-only.

In `@turbo.json`:
- Line 72: Move the concurrency setting from the tasks.dev scope to the root
turbo.json configuration, or remove it there and add --concurrency=14 to the
root dev script if the limit is intended only for dev execution.
- Around line 67-68: Update the outputs configuration for the apps/web build
task to include the Next.js `.next/**` artifact alongside the existing `dist/**`
pattern, excluding only internal cache files if the repository’s conventions
require it, so cached builds restore the files needed by `next start`.

---

Nitpick comments:
In `@packages/cli/package.json`:
- Line 38: Reconfirm the supported build-tool choice and TypeScript versions
before standardizing on tsup, then document the decision. Review the tsup
dependency changes in packages/cli/package.json (38-38),
packages/blob-s3/package.json (28-28), packages/config/package.json (30-30),
packages/core/package.json (27-27), packages/db-drizzle/package.json (43-43),
packages/next/package.json (33-36), and packages/plugin-discord/package.json
(50-50); update each affected package consistently if tsdown remains the
supported choice, or retain tsup only with documented version support and
rationale.

In `@packages/ui/package.json`:
- Line 54: Remove the unused tsup entry from the devDependencies in
packages/ui/package.json, while preserving the existing tsc-based build, dev,
and typecheck scripts and all other dependencies.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 62ad6908-9fda-4f2e-9647-1463c44d59d8

📥 Commits

Reviewing files that changed from the base of the PR and between 1c1b0ad and 4e3451e.

⛔ Files ignored due to path filters (9)
  • packages/blob-local/dist/index.d.ts is excluded by !**/dist/**
  • packages/blob-local/dist/index.d.ts.map is excluded by !**/dist/**, !**/*.map
  • packages/blob-local/dist/index.js is excluded by !**/dist/**
  • packages/blob-local/dist/index.js.map is excluded by !**/dist/**, !**/*.map
  • packages/blob-s3/dist/index.d.ts is excluded by !**/dist/**
  • packages/blob-s3/dist/index.d.ts.map is excluded by !**/dist/**, !**/*.map
  • packages/blob-s3/dist/index.js is excluded by !**/dist/**
  • packages/blob-s3/dist/index.js.map is excluded by !**/dist/**, !**/*.map
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (19)
  • package.json
  • packages/auth-better-auth/package.json
  • packages/blob-local/.gitignore
  • packages/blob-local/package.json
  • packages/blob-s3/.gitignore
  • packages/blob-s3/package.json
  • packages/cli/package.json
  • packages/config/package.json
  • packages/core/package.json
  • packages/db-drizzle/.gitignore
  • packages/db-drizzle/package.json
  • packages/next/package.json
  • packages/plugin-discord/.gitignore
  • packages/plugin-discord/package.json
  • packages/plugin-notifications-email/.gitignore
  • packages/plugin-notifications-email/package.json
  • packages/plugin-teams/package.json
  • packages/ui/package.json
  • turbo.json

Comment thread packages/cli/package.json
Comment on lines +14 to 19
"import": "./dist/index.js"
},
"./cli": {
"types": "./dist/cli.d.ts",
"import": "./dist/cli.js"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate package.json files =="
fd -a '^package\.json$' . | sed 's#^\./##' | head -50

echo
echo "== packages/cli/package.json =="
if [ -f packages/cli/package.json ]; then
  cat -n packages/cli/package.json | sed -n '1,80p'
fi

echo
echo "== package manager/type mentions =="
rg -n '"type"\s*:\s*"module"|\.cjs|\.js"$|types|"exports"|tsup|format:' -S --glob 'package.json' --glob 'tsup.config.*' --glob '*.ts' . | head -200

echo
echo "== dist files if present =="
if [ -d packages/cli/dist ]; then
  find packages/cli/dist -maxdepth 2 -type f | sort
else
  echo "packages/cli/dist not present"
fi

echo
echo "== package.json exports/type semantic probe =="
python3 - <<'PY'
import json, pathlib
p=pathlib.Path('packages/cli/package.json')
data=json.loads(p.read_text())
exports=data.get('exports')
fields=data.get('type')
print({
    'packages/cli/package.json': {
        'type': fields,
        'exports': exports,
    }
})
# Check whether . and ./cli exports define require.
def has_require(value):
    if isinstance(value, str): return value.endswith(('.cjs','.js','.mjs'))
    if isinstance(value, dict): return 'require' in value
    if isinstance(value, list): return any(has_require(x) for x in value)
    return False
print('exports_has_require_root_require', has_require(exports.get('.')))
print('exports_has_require_cli_require', has_require(exports.get('./cli')))
PY

Repository: acmutsa/HackKitPlugin

Length of output: 17532


🌐 Web query:

tsup cjs output file extension default cjs esm format cjs extension .cjs

💡 Result:

By default, tsup uses the.js extension for all output files, regardless of whether the format is CommonJS (cjs) or ESM (esm) [1][2]. It does not automatically use.cjs or.mjs extensions [1][2]. To output files with the.cjs extension for CommonJS builds, you must explicitly configure the outExtension option in your tsup configuration file [1][2]. Example configuration (tsup.config.ts): import { defineConfig } from 'tsup'; export default defineConfig({ format: ['esm', 'cjs'], outExtension({ format }) { return { js: format === 'cjs'? '.cjs': '.mjs', }; }, }); When this configuration is applied, tsup will generate.cjs files for CommonJS outputs and.mjs files for ESM outputs [2][3]. Alternatively, if you prefer not to use these extensions, you can use the --legacy-output flag to place different formats into separate directories [1][4].

Citations:


Add require entries for the CJS outputs.

packages/cli/package.json builds cjs and esm outputs, but the "packageSideEffects" metadata uses "type": "module" and exports["."]/exports["./cli"].import, while exports["."].types does not provide a runtime fallback. This makes the CommonJS outputs unavailable to require importers. Add require export targets matching the emitted CJS file extensions.

🤖 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 `@packages/cli/package.json` around lines 14 - 19, Add require export targets
to the "." and "./cli" entries in packages/cli/package.json, pointing to the
emitted CommonJS files with their actual CJS extensions. Preserve the existing
types and import targets while making both package entry points available to
require consumers.

Source: MCP tools

Comment on lines 33 to +36
"next": "14.2.35",
"typescript": "5.5.3",
"vitest": "^3.2.4"
"vitest": "^3.2.4",
"tsup": "^8.5.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

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

for package_dir in packages/blob-s3 packages/cli packages/config packages/next; do
  echo "== ${package_dir} =="
  fd -t f -e ts -e tsx . "${package_dir}" \
    -x rg -n -e '\b(process|Buffer|NodeJS|__dirname|__filename)\b' -e 'node:' {} || true
  fd -t f -i 'tsconfig*.json' "${package_dir}" \
    -x rg -n -C 2 '"types"|"typeRoots"|"lib"' {} || true
done

Repository: acmutsa/HackKitPlugin

Length of output: 2461


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== package names and scripts =="
for p in packages/blob-s3 packages/cli packages/config packages/next; do
  if [ -f "${p}/package.json" ]; then
    echo "-- ${p}/package.json --"
    python3 - <<'PY' "${p}/package.json"
import json, sys
p=sys.argv[1]
data=json.load(open(p))
print("name:", data.get("name"))
print("scripts:", data.get("scripts"))
print("dependencies.tsup:", data.get("dependencies",{}).get("tsup"))
print("devDependencies.tsup:", data.get("devDependencies",{}).get("tsup"))
PY
  fi
done

echo
echo "== root config and package files =="
rg -n -C 2 '"packages"|"type|moduleResolution|"`@types/node`|"tsup"|"tsconfig"' -S . -g 'package.json' -g 'tsconfig*.json' -g 'pnpm-lock.yaml' -g 'yarn.lock' -g 'package-lock.json' | head -n 240

echo
echo "== tsconfig explicit include / node references =="
for p in packages/blob-s3 packages/cli packages/config packages/next; do
  fd -t f -i 'tsconfig*.json' "${p}" -x sh -c '
    file="$1"
    echo "-- $file --"
    sed -n "1,120p" "$file"
  ' sh {}
done

Repository: acmutsa/HackKitPlugin

Length of output: 17218


Restore Node type declarations for packages/cli and packages/config.

These two packages import Node built-ins and use process, but their local tsconfig.json files do not include @types/node, and they do not reference a workspace config that provides it. Add @types/node directly to these packages, or add a shared tsconfig that both packages extend and that types Node APIs.

📍 Affects 4 files
  • packages/next/package.json#L33-L36 (this comment)
  • packages/blob-s3/package.json#L28-L28
  • packages/cli/package.json#L38-L38
  • packages/config/package.json#L30-L30
🤖 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 `@packages/next/package.json` around lines 33 - 36, Restore Node type
declarations for packages/cli/package.json at line 38 and
packages/config/package.json at line 30 by adding `@types/node` directly to both
packages or configuring a shared tsconfig they extend with Node types;
packages/next/package.json at lines 33-36 and packages/blob-s3/package.json at
line 28 require no direct change.

Comment on lines +11 to 12
"import": "./src/index.ts"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python - <<'PY'
import json
from pathlib import Path

package = json.loads(
    Path("packages/plugin-notifications-email/package.json").read_text()
)
root = package.get("exports", {}).get(".", {})
print(json.dumps(root, indent=2))

if root.get("import", "").startswith("./src/"):
    print("Import export points to source TypeScript")
if "require" not in root and "default" not in root:
    print("No CommonJS fallback is exported")
PY

Repository: acmutsa/HackKitPlugin

Length of output: 299


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "## package.json"
cat -n packages/plugin-notifications-email/package.json

echo
echo "## relevant files"
git ls-files packages/plugin-notifications-email | sed -n '1,120p'

echo
echo "## tsup/package config snippets"
for f in tsconfig.json workspace.json turbo.json package.json pnpm-workspace.yaml; do
  if [ -f "$f" ]; then
    echo "--- $f"
    sed -n '1,220p' "$f"
  fi
done

Repository: acmutsa/HackKitPlugin

Length of output: 5254


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path

pkg = json.loads(Path("packages/plugin-notifications-email/package.json").read_text())
print(pkg["scripts"]["build"])

root = pkg.get("exports", {}).get(".", {})
print("exports .:", root)
print("main:", pkg.get("main"))
print("requires require/default/export:", "require" in root or "default" in root or root.get("export", "").startswith("./src/"))
PY

Repository: acmutsa/HackKitPlugin

Length of output: 331


Map package exports to the built dist files.

The build outputs CJS and ESM files to dist, but exports["."] import points at ./src/index.ts. Consumers resolving this package can get TypeScript source instead of runnable JavaScript. Point import at the generated runtime entry, and keep a require or default export for the CJS output unless this package is intended to be ESM-only.

🤖 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 `@packages/plugin-notifications-email/package.json` around lines 11 - 12,
Update the package export map’s "." entry so import resolves to the generated
ESM runtime file under dist instead of src/index.ts, and retain or add a
require/default mapping to the generated CJS file unless the package is
explicitly ESM-only.

Comment thread turbo.json
Comment on lines +67 to +68
"outputs": ["dist/**"],
"cache": true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | sed -n '1,120p'

echo
echo "turbo.json:"
if [ -f turbo.json ]; then
  nl -ba turbo.json | sed -n '1,140p'
else
  fd -a '^turbo\.json$' . | sed -n '1,20p'
fi

echo
echo "apps/web/package.json:"
if [ -f apps/web/package.json ]; then
  nl -ba apps/web/package.json | sed -n '1,80p'
elif [ -f apps/web/package-json ]; then
  nl -ba apps/web/package-json | sed -n '1,80p'
else
  fd -a '^package\.json$' apps . 2>/dev/null | sort | sed -n '1,80p'
fi

echo
echo "Search web/build/start scripts and next build:"
rg -n '"scripts"|"next build"|"next start"|turbo|outputs|tasks' -S . -g 'package.json' -g 'turbo.json' | sed -n '1,200p'

Repository: acmutsa/HackKitPlugin

Length of output: 4806


🌐 Web query:

next build produces .next artifact output directory documentation

💡 Result:

The.next directory is the default output folder generated by the next build command in a Next.js project [1][2]. It contains the compiled, optimized production build of your application, including server-side code, client-side chunks, static assets, and build cache [3][4][1]. Key points regarding the.next directory: - Purpose: It houses everything required to run the application in production via next start [3][4]. Because it is a build artifact, it should never be edited manually and should always be included in your.gitignore file [1]. - Customization: You can change the default output directory from.next to a custom name (e.g., build) by modifying the distDir option in your next.config.js (or next.config.ts) file [5][6][7]. // next.config.js module.exports = { distDir: 'build', } - Restrictions: The custom directory specified in distDir must remain within your project's root directory; paths like../build are invalid [5][8][6][2]. - Static Exports: If you are using a static export (output: 'export'), the default output directory is out, which is distinct from the.next folder used for standard server-side rendering or API-based deployments [9][7][2]. Documentation regarding the internal structure of the.next directory is often considered an implementation detail, as Next.js manages these files automatically [4][1]. Typical contents include a server/ directory for server-side logic, a static/ directory for browser-compatible assets (JS, CSS, images), and a cache/ directory to optimize subsequent builds [3][4][1].

Citations:


🌐 Web query:

Turborepo cache outputs restore outputs documentation

💡 Result:

In Turborepo, the restoration of task outputs is handled automatically by the system whenever a cache hit occurs [1][2]. Users do not need to manually trigger a restore process; instead, they must correctly configure the outputs key in their turbo.json file to define which files or directories should be cached [3][4][1]. Key requirements for caching and restoring outputs: 1. Define outputs: You must explicitly list the files or directories (using glob patterns) that a task produces in the outputs field of the corresponding task in turbo.json [3][4]. If this key is omitted or left as an empty array, Turborepo will not cache or restore any file outputs for that task [4][2][5]. 2. Automatic Restoration: When a task is executed, Turborepo calculates a hash (fingerprint) of the task's inputs [1][2]. If this hash matches a previously cached execution, Turborepo performs a cache hit [1][2]. Upon a cache hit, it automatically extracts the archived outputs from the local cache (or downloads/extracts them from a remote cache) and places them back into their original locations [1][2][6]. 3. Logs: In addition to file outputs, Turborepo always caches and replays task logs (stdout/stderr) during a cache hit [1][2]. 4. Optimization: If the required outputs are already present in the workspace and haven't changed, Turborepo may skip the restoration (extraction) step to save time, as the files are effectively already in place [7]. If you find that a task reports a "Full Turbo" cache hit but the expected output files are missing, it is almost always because the outputs key was not configured or was configured incorrectly [1][5]. For shared environments, Remote Caching can be enabled to allow these artifacts to be shared across a team or CI/CD pipeline, extending the benefits of automatic cache restoration beyond a single local machine [1][8][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "turbo.json:"
awk '{printf "%6d\t%s\n", NR, $0}' turbo.json | sed -n '1,180p'

echo
echo "apps/web/package.json:"
awk '{printf "%6d\t%s\n", NR, $0}' apps/web/package.json | sed -n '1,120p'

echo
echo "next config distDir:"
for f in apps/web/next.config.js apps/web/next.config.mjs apps/web/next.config.ts apps/web/next.config.cjs; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    awk '{printf "%6d\t%s\n", NR, $0}' "$f" | sed -n '1,160p'
  fi
done

echo
echo "Build outputs in package scripts:"
python3 - <<'PY'
import json
from pathlib import Path
p=Path('apps/web/package.json')
data=json.loads(p.read_text())
for k,v in data.get('dependencies',{}).items():
    if 'next' in k.lower():
        print(f"next dependency {k}: {v}")
PY

Repository: acmutsa/HackKitPlugin

Length of output: 6112


Include the Next.js build artifact in Turborepo outputs.

apps/web runs next build, and the default distDir is .next, not apps/web/dist. Since turbo.json only caches dist/**, the web build cache will not restore .next/. Include .next/** (excluding internal cache files if needed) so next start receives the production artifact after a cache hit.

Suggested fix
-			"outputs": ["dist/**"],
+			"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
📝 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
"outputs": ["dist/**"],
"cache": true
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
"cache": true
🤖 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 `@turbo.json` around lines 67 - 68, Update the outputs configuration for the
apps/web build task to include the Next.js `.next/**` artifact alongside the
existing `dist/**` pattern, excluding only internal cache files if the
repository’s conventions require it, so cached builds restore the files needed
by `next start`.

Source: MCP tools

Comment thread turbo.json Outdated
},
"dev": {
"dependsOn": ["^build"],
"concurrency": 14,

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:

#!/usr/bin/env bash
set -euo pipefail

python - <<'PY'
import json
import re
from pathlib import Path

root = json.loads(Path("package.json").read_text())
turbo = json.loads(Path("turbo.json").read_text())

spec = (
    root.get("devDependencies", {}).get("turbo")
    or root.get("dependencies", {}).get("turbo")
)
print(f"declared turbo version: {spec!r}")

dev_task = turbo.get("tasks", {}).get("dev", {})
if "concurrency" in dev_task:
    raise SystemExit("tasks.dev.concurrency is incorrectly nested")

dev_script = root.get("scripts", {}).get("dev", "")
root_value = turbo.get("concurrency")
root_configured = root_value in (14, "14")
script_configured = bool(re.search(r"--concurrency(?:=|\s+)14\b", dev_script))

if not (root_configured or script_configured):
    raise SystemExit("configure concurrency=14 at the root or in the dev script")

print("concurrency has a supported scope")
PY

Repository: acmutsa/HackKitPlugin

Length of output: 236


🌐 Web query:

Turborepo turbo.json configuration concurrency option tasks concurrency not supported

💡 Result:

As of August 6, 2026, Turborepo fully supports the concurrency option within the turbo.json configuration file [1][2]. You can set the global concurrency limit by adding a concurrency key to your turbo.json file [1][2]. The value can be an integer (e.g., "1" for serial execution) or a percentage (e.g., "50%" of available logical processors) [1][3]. Example configuration: json { "concurrency": "5" } Important points regarding this functionality: - Global Scope: This configuration applies globally to task execution [2]. - Per-Task Limitation: Turborepo does not currently support configuring concurrency on a per-task basis within the tasks object; the concurrency option is a global setting [4]. - Precedence: If you encounter issues, note that CLI arguments (--concurrency) typically take precedence over environment variables (TURBO_CONCURRENCY), which take precedence over values defined in turbo.json [4]. - Troubleshooting: If you previously encountered errors suggesting this option was not supported, ensure you are using a recent version of Turborepo, as support for this configuration was added in earlier versions (e.g., around v2.5) [5]. Ensure your turbo.json is correctly structured, and if using IDE support, verify that your $schema points to the latest version to avoid false linting errors [5].

Citations:


Move concurrency to a supported scope.

tasks.dev.concurrency is not a valid Turbo task option. Turborepo only supports concurrency as a global turbo.json option.

Use "concurrency": 14 at the root if the limit applies to all task execution. Use --concurrency=14 in the root dev script if the limit should apply only to dev.

🤖 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 `@turbo.json` at line 72, Move the concurrency setting from the tasks.dev scope
to the root turbo.json configuration, or remove it there and add
--concurrency=14 to the root dev script if the limit is intended only for dev
execution.

Source: MCP tools

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