Repository navigation
feat: add statusline command for active LSP server display - #52
Conversation
Adds a new statusline command that returns active LSP server names as a deduplicated, sorted, comma-separated string for integration with Claude Code statusline.
Pull Request Review: Add statusline commandOverall AssessmentThis is a well-implemented feature that follows the codebase patterns and includes comprehensive tests. The code is clean and the functionality is straightforward. I have identified a few issues and suggestions for improvement. Critical Issues1. Inconsistent command implementation patternLocation: Issue: The statusline command doesn't follow the established pattern used by other commands (status, logs, stop). It directly calls Current implementation: export function registerStatuslineCommand(program: Command) {
program
.command('statusline')
.description('Show active LSP server names for statusline display')
.action(async () => {
try {
const result = await sendToExistingDaemon('statusline', []);
if (typeof result === 'string' && result.length > 0) {
process.stdout.write(result + '\n');
}
} catch {
// No daemon running — exit silently
}
});
}Expected pattern (see export function registerStatuslineCommand(program: Command) {
program
.command('statusline')
.description('Show active LSP server names for statusline display')
.action(async (_options, command) => {
const opts = command.optsWithGlobals();
assertConfigFileOptions(opts);
await runCommand('statusline', [], opts.configFile);
});
}Why this matters:
Code Quality Issues2. Silent failure may hide real errorsLocation: Issue: The empty catch block silently swallows all errors, not just "daemon not running" errors. This could hide legitimate issues like network errors, permission problems, or bugs. Current: } catch {
// No daemon running — exit silently
}Suggestion: If you intend to keep the direct } catch (error) {
// Only exit silently if daemon isn't running
// Other errors should be reported
if (error instanceof Error && error.message.includes('ENOENT')) {
// Daemon not running - exit silently as intended
return;
}
// Unexpected error - report it
process.stderr.write(`Error: ${error instanceof Error ? error.message : 'Unknown error'}\n`);
process.exit(1);
}However, if you switch to using 3. Missing explicit exit code handlingLocation: Issue: The command doesn't explicitly handle the exit code, relying on implicit behavior. The tests verify exit code 0, but the code doesn't guarantee this in all paths. Context: Looking at If keeping current implementation: try {
const result = await sendToExistingDaemon('statusline', []);
if (typeof result === 'string' && result.length > 0) {
process.stdout.write(result + '\n');
}
process.exit(0); // Explicit success
} catch (error) {
// ... error handling
}Best Practices & Minor Issues4. Test relies on timing assumptionsLocation: Issue: The test includes a 2-second sleep to "let servers initialize," which makes tests slower and fragile. // Give servers a moment to initialize
await new Promise((resolve) => setTimeout(resolve, 2000));Suggestion: Consider polling the status until servers are ready, or accept that the test validates whatever state the daemon is in. Since the servers should be initialized from a previous test run in the suite, this sleep may not even be necessary. // Alternative: Poll until ready or timeout
const maxWait = 5000;
const pollInterval = 100;
let elapsed = 0;
let result;
while (elapsed < maxWait) {
result = await runCommandWithArgs(['statusline']);
if (result.stdout.trim().length > 0) break;
await new Promise((resolve) => setTimeout(resolve, pollInterval));
elapsed += pollInterval;
}5. Test makes assumptions about repository contentLocation: Issue: The test assumes the repository will always have TypeScript and JSON files, which makes the test brittle. // This project has .ts, .json, .sh, .yaml files so these servers should be active
expect(servers.includes('typescript')).toBe(true);
expect(servers.includes('json')).toBe(true);Suggestion: Make the test more flexible: // Verify we got some servers (non-empty output)
expect(servers.length).toBeGreaterThan(0);
// Verify format is correct (comma-separated, sorted)
const sorted = [...servers].sort();
expect(servers.join(', ')).toBe(sorted.join(', '));Or keep the specific checks but add a comment explaining the dependency: // This test depends on the repository having .ts and .json files
// If the repo structure changes significantly, these assertions may need updating
expect(servers.includes('typescript')).toBe(true);
expect(servers.includes('json')).toBe(true);6. Inconsistent output formattingLocation: Issue: The statusline command returns a bare string (no newline), but Context: Looking at the
The statusline command follows this pattern, which is fine, but the daemon return value and command output handling could be better documented. Suggestion: Add a comment in the daemon handler explaining the output format: case 'statusline': {
const runningServers = getRunningServers();
const serverIDs = [...new Set(runningServers.map(s => s.serverID))].sort();
// Return comma-separated list (newline added by command handler)
return serverIDs.join(', ');
}Positive Observations✅ Good test coverage - Tests validate output format, sorting, deduplication, exit codes, and edge cases RecommendationsPriority 1 (Should Fix):
Priority 2 (Consider):
Priority 3 (Nice to Have):
Security & Performance✅ No security concerns - Read-only operation, no user input processed ConclusionThis is a solid implementation of a useful feature. The main concern is the architectural inconsistency with other commands. Once the command implementation is refactored to use Suggested Actions:
Let me know if you'd like me to provide a complete refactored version of the statusline command! |
Move statusline error handling logic from command action to runCommand to ensure consistent behavior across all commands and avoid daemon auto-start.
Code Review: Add statusline command for active LSP server displaySummaryThis PR adds a new ✅ Strengths
🔍 Code Quality Observationssrc/client.ts (lines 454-468)
src/daemon.ts (lines 206-210)
src/commands/statusline.ts
🐛 Potential Issues1. Missing configFile parameter (Minor bug) // Current implementation
export function registerStatuslineCommand(program: Command) {
program
.command('statusline')
.description('Show active LSP server names for statusline display')
.action(async () => {
await runCommand('statusline', []);
});
}Expected pattern (see export function registerStatuslineCommand(program: Command) {
program
.command('statusline')
.description('Show active LSP server names for statusline display')
.action(async (_options, command) => {
const opts = command.optsWithGlobals();
assertConfigFileOptions(opts);
await runCommand('statusline', [], opts.configFile);
});
}This matters because 🧪 Test Coveragetests/statusline.test.ts
Suggested additional test cases: test('should return empty output when no daemon is running', async () => {
// Stop daemon first
await runCommandWithArgs(['stop']);
const result = await runCommandWithArgs(['statusline']);
expect(result.exitCode).toBe(0);
expect(stripAnsi(result.stdout)).toBe('');
});
test('should deduplicate servers with same ID in different roots', async () => {
// This would require multiple projects with same server type
// The current test implicitly verifies this but could be explicit
});🔒 Security & Performance
📋 Recommendations
Overall AssessmentThis is a solid, well-implemented feature with good documentation. The main issue is the missing configFile parameter which should be fixed before merge to maintain consistency with the rest of the codebase and ensure correct behavior when using custom config files. Recommendation: Approve with minor changes requested |
Code Review: PR #52 - Add statusline commandOverall, this is a well-implemented feature with clean code and good test coverage. The implementation follows project conventions and integrates smoothly with the existing codebase. Below are my detailed findings: ✅ Strengths
🔍 Code Quality Analysissrc/commands/statusline.ts ✅
src/daemon.ts (lines 206-210) ✅
src/client.ts (lines 453-468) ✅
Minor observation: The error filtering logic at line 463 could benefit from a brief comment explaining why 'code' property is checked, but it's not critical. src/cli.ts (lines 17, 81) ✅
🧪 Test Coveragetests/statusline.test.tsStrengths:
Potential gaps:
🔒 Security Considerations
⚡ Performance Considerations
📝 Best Practices AlignmentChecked against CLAUDE.md:
🐛 Potential IssuesNone found - The implementation is solid. One minor consideration: The output format uses 📊 Summary
🎯 RecommendationAPPROVE - This PR is ready to merge. The suggested test additions are nice-to-haves, not blockers. The implementation is clean, correct, and follows all project conventions. The only actionable item would be adding tests for the edge cases mentioned above, but the current implementation handles them correctly, so this is optional. Great work! 🚀 |
Summary
Adds a new
statuslinecommand that outputs active LSP server names for integration with Claude Code's statusline display.The command returns server names as a deduplicated, sorted, comma-separated string, making it easy to surface active LSP information in status displays.
Changes
statuslinecommand: Returns comma-separated list of active LSP server IDsTechnical Details
The implementation:
getRunningServers()Output format is optimized for statusline consumption with minimal whitespace and predictable ordering.
Testing
Test coverage includes: