Svelte CLI

repository·main·Indexed 19 days ago

https://github.com/sveltejs/cli

Official command-line tools for Svelte and SvelteKit development. Includes the `sv` CLI for scaffolding new projects via `sv create`, adding official and community integrations via `sv add`, and performing project diagnostics with `sv check`. Also provides `svelte-migrate` for upgrading codebases between Svelte and SvelteKit versions, and `@sveltejs/sv-utils` for building `sv` add-ons.

Tokens
52.2K
Snippets
203
Records
264
Agent score
66%

What's inside sveltejs-cli

  1. Overview of the Svelte CLI (sv)

    main
    The sveltejs/sveltejs/cli repository contains the official Svelte Command Line Interface tools. The primary tool is sv, which provides CLI capabilities for Svelte developers. For detailed information on starting a new application, refer to the SvelteKit documentation.
  2. What is included when adding Playwright via sv

    main

    When you run npx sv add playwright, the CLI performs the following automated setup tasks:

    • Scripts: Adds relevant testing scripts to your package.json.
    • Configuration: Generates a Playwright configuration file.
    • Git Integration: Updates your .gitignore to ensure Playwright artifacts are ignored.
    • Demo: Provides a sample demo test to help you get started immediately.
  3. What the Prettier add-on provides

    main

    When you run npx sv add prettier, the following changes are applied to your project:

    • package.json: New scripts are added to facilitate running Prettier.
    • Configuration files: .prettierignore and .prettierrc files are created in your project root.
    • ESLint integration: If you are already using ESLint, your ESLint configuration will be updated to work alongside Prettier.
  4. How Svelte CLI add-ons work

    main

    Svelte CLI add-ons are built using two primary packages that maintain a strict boundary of concerns:

    1. sv: The orchestration engine. It handles where and when actions occur. It manages file paths, workspace detection, dependency tracking, and file I/O.
    2. @sveltejs/sv-utils: The content toolkit. It handles what is done to content. It provides pure parsers, language tooling, and typed transforms. It has no knowledge of the file system or the workspace, making transforms highly testable and composable.

    An add-on is defined using defineAddon and typically implements options, setup, run, and nextSteps hooks.

    import { transforms } from '@sveltejs/sv-utils';
    import { defineAddon, defineAddonOptions } from 'sv';
    
    export default defineAddon({
    	id: 'addon-name',
    	shortDescription: 'a better description of what your addon does ;)',
    
    	options: defineAddonOptions()
    		.add('who', {
    			question: 'To whom should the addon say hello?',
    			type: 'string' // boolean | number | select | multiselect
    		})
    		.build(),
    
    	setup: ({ dependsOn, isKit, unsupported, addOption }) => {
    		if (!isKit) unsupported('Requires SvelteKit');
    		dependsOn('vitest');
    		// addOption('key', { question: '...', type: 'boolean', default: true });
    	},
    
    	run: ({ isKit, cancel, sv, options, file, language, directory }) => {
    		sv.file(
    			directory.kitRoutes + '/+page.svelte',
    			transforms.svelte(({ ast, svelte }) => {
    				svelte.addFragment(ast, `<p>Hello ${options.who}!</p>`);
    			})
    		);
    	},
    
    	nextSteps: ({ options }) => ['enjoy the add-on!']
    });
  5. Use transforms to modify files via AST

    main

    The transforms object provides parser-aware functions that allow you to modify files using their Abstract Syntax Tree (AST). These transforms are designed to be passed directly into sv.file(). The parser is automatically selected based on the transform type used, preventing accidental mis-parsing.

    Each transform provides a callback with injected utilities (like js, css, or svelte) to simplify AST manipulation.

    import { transforms } from '@sveltejs/sv-utils';
    
    // Example: Using a transform within sv.file
    sv.file(
    	path,
    	transforms.script(({ ast, js }) => {
    		js.imports.addDefault(ast, { as: 'foo', from: 'foo' });
    	})
    );
  6. Configure TypeScript and JavaScript checking with --tsconfig

    main

    By default, sv check traverses upwards from your project directory to find a tsconfig.json or jsconfig.json.

    • Use --tsconfig <path> to specify a specific configuration file. This enables type-checking for .js and .ts files based on the files/include/exclude patterns in that config.
    • Use --no-tsconfig to check only Svelte files in the current directory and below, ignoring .js/.ts files (they will not be type-checked).
    npx sv check --tsconfig ./tsconfig.app.json
  7. Traverse AST nodes with `zimmerframe`

    main

    The library exports a walk function (via the zimmerframe module) for traversing AST nodes using a visitor pattern.

    walk(node, state, visitors):

    • node: The starting node to traverse.
    • state: A user-defined state object passed through the traversal.
    • visitors: An object where keys are node type strings and values are Visitor functions.

    Each Visitor receives a context which provides:

    • next(): Move to the next node.
    • path: The current stack of nodes.
    • state: The current traversal state.
    • stop(): Terminate traversal.
    • visit(node): Manually visit a specific node.
  8. Use transforms standalone or in composition

    main

    Transforms are curried functions. You can use them in two ways:

    1. Standalone: Call the transform with a callback to get a function, then pass the file content to that function.
    2. Composition: Use sv.file with a content callback to mix curried transforms with raw string manipulations.
    // Standalone usage
    import { transforms } from '@sveltejs/sv-utils';
    
    const transform = transforms.script(({ ast, js }) => {
    	js.imports.addDefault(ast, { as: 'foo', from: 'foo' });
    });
    const result = transform('export default {}');
    
    // Composition
    import { sv } from '@sveltejs/sv-utils';
    
    sv.file(path, (content) => {
    	const transform = transforms.script(({ ast, js }) => {
    		js.imports.addDefault(ast, { as: 'foo', from: 'bar' });
    	});
    
    	content = transform(content); // Apply curried transform
    	content = content.replace('foo', 'baz'); // Raw string manipulation
    
    	return content;
    });
  9. Understand the difference between the Svelte plugin and individual tools

    main

    When adding Svelte AI tooling, you can choose between two delivery methods:

    The Svelte Plugin (delivery:plugin)

    This is the recommended approach. It bundles the MCP server, skills, and sub-agents into a single package that stays up to date. It is specifically available for Claude Code and OpenCode. For Claude Code, the plugin is enabled through a committed .claude/settings.json and installs automatically when you trust the workspace.

    Individual Tools (delivery:tools)

    Use this method if your client does not support the plugin or if you want to pick exactly which components to add. This includes:

    • An MCP configuration for local or remote setup.
    • A README for agents to assist in using the MCP server effectively.
    • Skills (for supported clients).
    • Sub-agents (for supported clients).
  10. What is included when adding ESLint

    main

    When you run npx sv add eslint, the CLI performs the following actions:

    • Package Installation: Installs relevant ESLint packages, including eslint-plugin-svelte.
    • Configuration: Creates an eslint.config.js file in your project.
    • Editor Integration: Updates .vscode/extensions.json to suggest relevant extensions.
    • Compatibility: If your project already uses TypeScript or prettier, the ESLint configuration is automatically adjusted to work with them.
  11. Abort a transform

    main

    To prevent a transform from applying changes, return false from the transform callback. The original file content will be returned unchanged.

    import { transforms } from '@sveltejs/sv-utils';
    
    sv.file(
    	'eslint.config.js',
    	transforms.script(({ ast, js }) => {
    		const { value: existing } = js.exports.createDefault(ast, { fallback: myConfig });
    		if (existing !== myConfig) {
    			// config already exists, don't touch it
    			return false;
    		}
    		// ... continue modifying ast
    	})
    );