JavaScript/TypeScript linter (ESLint wrapper) with great defaults
The XO programmatic API provides comprehensive linting functionality for JavaScript and TypeScript files through the main Xo class and convenient static methods.
Creates a new XO linting instance with specified options.
/**
* Creates a new XO linting instance
* @param linterOptions - Required linter configuration
* @param baseXoConfig - Optional XO-specific configuration
*/
constructor(linterOptions: LinterOptions, baseXoConfig?: XoConfigOptions);
interface LinterOptions {
/** Current working directory for relative paths */
cwd: string;
/** Write fixes to files automatically */
fix?: boolean;
/** Path to file being linted (for lintText) */
filePath?: string;
/** Show only errors, not warnings */
quiet?: boolean;
/** Auto-configure type-aware linting for TypeScript */
ts?: boolean;
/** Custom path to config file */
configPath?: string;
}
interface XoConfigOptions {
/** Use spaces for indentation (boolean, number, or string) */
space?: boolean | number | string;
/** Use semicolons at end of statements */
semicolon?: boolean;
/** Use Prettier formatting ('compat' for compatibility mode) */
prettier?: boolean | 'compat';
/** Enable React-specific linting rules */
react?: boolean;
/** Files to ignore (glob patterns) */
ignores?: string | string[];
}Usage Example:
import Xo from "xo";
const xo = new Xo(
{
cwd: process.cwd(),
fix: true,
quiet: false
},
{
space: 2,
semicolon: true,
react: true
}
);Lints files matching the provided glob patterns.
/**
* Lints files matching glob patterns
* @param globs - Glob patterns for files to lint (defaults to all supported files)
* @returns Promise resolving to lint results
*/
async lintFiles(globs?: string | string[]): Promise<XoLintResult>;Usage Example:
// Lint all supported files
const result = await xo.lintFiles();
// Lint specific patterns
const jsResult = await xo.lintFiles(["src/**/*.js", "test/**/*.ts"]);
// Check results
if (result.errorCount > 0) {
console.error(`Found ${result.errorCount} errors`);
// Access detailed results
result.results.forEach(fileResult => {
console.log(`${fileResult.filePath}: ${fileResult.messages.length} issues`);
});
}Lints provided text content with specified file path context.
/**
* Lints provided text content
* @param code - Source code text to lint
* @param options - Linting options including file path
* @returns Promise resolving to lint results
*/
async lintText(code: string, options: LintTextOptions): Promise<XoLintResult>;
interface LintTextOptions {
/** Path to file being linted (used for rule context) */
filePath: string;
/** Warn if the file would be ignored */
warnIgnored?: boolean;
}Usage Example:
const code = `
function hello() {
console.log("Hello world")
}
`;
const result = await xo.lintText(code, {
filePath: "example.js",
warnIgnored: false
});
console.log(`Errors: ${result.errorCount}, Warnings: ${result.warningCount}`);Gets the effective ESLint configuration for a specific file.
/**
* Calculates the effective ESLint configuration for a file
* @param filePath - Path to the file to get config for
* @returns Promise resolving to ESLint configuration
*/
async calculateConfigForFile(filePath: string): Promise<Linter.Config>;Usage Example:
const config = await xo.calculateConfigForFile("src/index.ts");
console.log("Active rules:", Object.keys(config.rules || {}));Loads an ESLint formatter by name for custom output formatting.
/**
* Loads an ESLint formatter for custom output
* @param name - Name of the formatter to load
* @returns Promise resolving to formatter instance
*/
async getFormatter(name: string): Promise<ESLint.Formatter>;Usage Example:
const formatter = await xo.getFormatter("json");
const result = await xo.lintFiles();
const formattedOutput = formatter.format(result.results);
console.log(formattedOutput);Initializes the internal ESLint instance with current configuration.
/**
* Initializes the ESLint instance (called automatically by lint methods)
* @param files - Optional list of files for TypeScript configuration
*/
async initEslint(files?: string[]): Promise<void>;Converts XO configuration to ESLint flat config format for direct ESLint usage.
/**
* Static helper to convert XO config to ESLint config for use in eslint.config.js
* @param flatXoConfig - Array of XO configuration items
* @param options - Additional options including Prettier configuration
* @returns ESLint flat configuration array
*/
static xoToEslintConfig(
flatXoConfig: XoConfigItem[],
options?: CreateConfigOptions
): Linter.Config[];
interface CreateConfigOptions {
/** Prettier options to merge with XO's defaults */
prettierOptions?: Options;
}Usage Example:
import { xoToEslintConfig } from "xo";
// Convert XO config to ESLint config
const eslintConfig = xoToEslintConfig([
{ space: 2, semicolon: true, react: true }
], {
prettierOptions: { semi: true, tabWidth: 2 }
});
// Use in eslint.config.js
export default eslintConfig;Convenience method for linting text without creating an XO instance.
/**
* Static convenience method for linting text
* @param code - Source code to lint
* @param options - Combined linter, XO config, and text options
* @returns Promise resolving to lint results
*/
static async lintText(
code: string,
options: LintTextOptions & LinterOptions & XoConfigOptions
): Promise<XoLintResult>;Usage Example:
const result = await Xo.lintText(`console.log("test")`, {
filePath: "test.js",
cwd: process.cwd(),
space: true,
semicolon: false
});Convenience method for linting files without creating an XO instance.
/**
* Static convenience method for linting files
* @param globs - Glob patterns for files to lint
* @param options - Combined linter and XO config options
* @returns Promise resolving to lint results
*/
static async lintFiles(
globs: string | undefined,
options: LinterOptions & XoConfigOptions
): Promise<XoLintResult>;Usage Example:
const result = await Xo.lintFiles("src/**/*.js", {
cwd: process.cwd(),
fix: true,
space: 2,
react: true
});Writes auto-fixes from lint results to disk.
/**
* Writes auto-fixes to disk
* @param results - Lint results containing fixes
*/
static async outputFixes(results: XoLintResult): Promise<void>;Usage Example:
const result = await xo.lintFiles();
if (result.fixableErrorCount > 0 || result.fixableWarningCount > 0) {
await Xo.outputFixes(result);
console.log("Auto-fixes applied");
}interface XoLintResult {
/** Total number of errors found */
errorCount: number;
/** Total number of warnings found */
warningCount: number;
/** Number of fixable errors */
fixableErrorCount: number;
/** Number of fixable warnings */
fixableWarningCount: number;
/** Array of ESLint results for each file */
results: ESLint.LintResult[];
/** Metadata about the rules that were executed */
rulesMeta: Record<string, Rule.RuleMetaData>;
}The XO class exposes several properties for advanced usage:
interface XoInstance {
/** Configuration options passed to constructor */
linterOptions: LinterOptions;
baseXoConfig: XoConfigOptions;
/** Path to ESLint cache directory */
cacheLocation: string;
/** Internal ESLint instance (available after initEslint) */
eslint?: ESLint;
/** Resolved XO configuration */
xoConfig?: XoConfigItem[];
/** Generated ESLint configuration */
eslintConfig?: Linter.Config[];
/** Path to flat config file if found */
flatConfigPath?: string;
/** Whether Prettier integration is enabled */
prettier?: boolean;
/** Resolved Prettier configuration */
prettierConfig?: prettier.Options;
/** Glob patterns for TypeScript files */
tsFilesGlob: string[];
/** Negative glob patterns for TypeScript overrides */
tsFilesIgnoresGlob: string[];
}Install with Tessl CLI
npx tessl i tessl/npm-xo