Loading...
Loading...
MUST be used whenever reviewing a Dune app for code quality, maintainability, or clean code issues — before a PR review, after a feature is complete, or when the user asks for a code review. Do NOT skip linting steps. Triggers: code quality, code review, clean code, refactor, maintainability, technical debt, any type, naming, dead code, duplication, DRY, single responsibility, component size, lint, linting, TypeScript strict, dependency injection, file structure.
npx skill4agent add cognitedata/dune-skills code-qualitypnpm run lintpnpm exec tsc --noEmitanyanygrep -rn --include="*.ts" --include="*.tsx" -E ": any|as any|<any>" src/| Instead of | Use |
|---|---|
| |
| |
| The SDK's own response types (import from |
| |
| Proper type narrowing or explicit overloaded function signature |
anysrc/any.tsxnode -e "const fs=require('fs'),path=require('path');function walk(d){return fs.readdirSync(d,{withFileTypes:true}).flatMap(e=>{const p=path.join(d,e.name);return e.isDirectory()?walk(p):p.endsWith('.tsx')?[p]:[]})}walk('src').map(p=>({p,l:fs.readFileSync(p,'utf8').split('\n').length})).sort((a,b)=>b.l-a.l).forEach(({l,p})=>console.log(l,p))"useAssetData# Find repeated fetch patterns
grep -rn --include="*.ts" --include="*.tsx" -E "sdk\.(assets|timeseries|events|files)\.(list|retrieve)" src/
# Find repeated formatting functions
grep -rn --include="*.ts" --include="*.tsx" -E "toLocaleDateString|toLocaleString|new Date\(" src/
# Find repeated className strings longer than 40 chars
grep -rn --include="*.tsx" -E 'className="[^"]{40,}"' src/src/utils/src/hooks/useCogniteClient()grep -rn --include="*.ts" --include="*.tsx" -E "new CogniteClient|createCogniteClient" src/// GOOD — client comes from context
export function useMyData() {
const sdk = useCogniteClient(); // from Dune auth context
// ...
}
// BAD — direct construction inside a hook or component
const sdk = new CogniteClient({ project: "my-project", ... });execute| Artifact | Convention | Examples |
|---|---|---|
| Files & directories | | |
| React components | | |
| Variables, functions, hooks | | |
| Constants (module-level) | | |
| TypeScript types & interfaces | | |
| Boolean variables | Auxiliary verb prefix | |
# TSX components not in PascalCase (filename starts with lowercase)
node -e "const fs=require('fs'),path=require('path');function walk(d){return fs.readdirSync(d,{withFileTypes:true}).flatMap(e=>{const p=path.join(d,e.name);return e.isDirectory()?walk(p):p.endsWith('.tsx')?[p]:[]})}walk('src').filter(p=>/^[a-z]/.test(path.basename(p))).forEach(p=>console.log(p))"
# Hook files not prefixed with "use"
node -e "const fs=require('fs');fs.readdirSync('src/hooks').filter(f=>f.endsWith('.ts')&&!f.startsWith('use')).forEach(f=>console.log('src/hooks/'+f))"# Find commented-out code blocks (3+ consecutive commented lines)
Get-ChildItem -Recurse -Include "*.ts","*.tsx" src | ForEach-Object {
$file = $_; $lines = Get-Content $file.FullName
$count = 0; $startLine = 0
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^\s*//') {
if ($count -eq 0) { $startLine = $i + 1 }
$count++
} else {
if ($count -ge 3) { "$($file.FullName):$startLine — $count consecutive comment lines" }
$count = 0
}
}
if ($count -ge 3) { "$($file.FullName):$startLine — $count consecutive comment lines" }
}
# Find console.log/debug statements
grep -rn --include="*.tsx" --include="*.ts" -E "console\.(log|debug|warn|error|info)" src/
# Find TODO/FIXME/HACK comments
grep -rn --include="*.tsx" --include="*.ts" -E "(TODO|FIXME|HACK|XXX):" src/console.logconsole.debugconsole.errorTODOFIXMEsrc/
├── components/ # Shared presentational components
│ └── <name>/
│ ├── <name>.tsx
│ └── index.ts # re-exports the public API
├── hooks/ # Custom hooks (each file = one hook)
├── utils/ # Pure utility functions (no React)
├── contexts/ # React context providers
├── pages/ or views/ # Route-level components
└── types/ # Shared TypeScript typesutils/types/index.ts| Category | File | Line | Issue | Recommendation |
|---|---|---|---|---|
| TypeScript | | 18 | | Import and use |
| Size | | — | 340 lines, mixes fetch and render logic | Extract |
| DRY | | 45, 62 | Identical date formatter | Extract to |
| Naming | | — | File name does not start with | Rename to |
| Dead code | | 88 | | Remove |
any