Project Files
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
lms-plugin-git-tools is an LM Studio plugin that exposes git operations to local LLMs. It is loaded by the LM Studio host via the named main export of src/index.ts, which registers a ToolsProvider that returns eight git tools.
| Command | Purpose |
|---|---|
npm run build | Compile TypeScript (src/ → dist/) |
npm run dev | Run inside LM Studio in dev mode (requires LM Studio running) |
npm run push | Publish/push the plugin to LM Studio |
npm run lint | ESLint — must pass with zero errors |
npm run lint:fix | Auto-fix lint issues |
npm run format / format:check | Prettier write / check |
npm run knip | Detect unused exports/dependencies |
There is no test runner configured.
The whole plugin is a thin, security-conscious wrapper around simple-git:
These are unusual and ESLint will fail the build if violated:
context.withToolsProvider(gitToolsProvider).ToolsProviderController to every tool factory. Each tool calls controller.getWorkingDirectory() lazily inside its implementation — the SDK only attaches a working directory when a tool is actually invoked from a chat, so reading it at provider-setup time fails with "This prediction process is not attached to a working directory." The working directory is the security boundary: every tool operates only on paths under it.resolveAndValidateRepoPath(repoName, workingDirectory). Every tool implementation MUST call this before touching the filesystem, passing in the freshly-resolved controller.getWorkingDirectory(). Paths that escape the working directory throw.formatGitError(operation, target, error). Tools wrap their simple-git calls in try/catch and route caught errors through this helper to produce consistent, model-readable error strings (per the SDK guidance to return recoverable errors as strings).create<Name>Tool(controller): Tool factory. Tools take a repoName (relative to the working directory), validate it (resolving the working directory inside implementation), then call simpleGit(repoPath).git_clone are read-only (status, diff, log, branch, show, ls_files, grep). No commit/push/branch/merge/checkout operations are exposed.git_clone is the only tool that writes to the filesystem; its destination is validated through resolveAndValidateRepoPath.simple-git spawns processes with discrete argument arrays — keep it that way.git_show enforces a 10 MB cap via cat-file -s before loading content; when adding new tools that read blobs, do the same.*-tool.ts and contain a single FunctionDeclaration named create<Something>Tool with an explicit Tool return type. Helpers, shared types, and providers live in themed sibling folders under src/ (currently src/path/ for filesystem-path concerns and src/git/ for git-output concerns) — never inside src/tools/.constants.ts and types.ts are banned. Co-locate declarations with the module that owns the behaviour.main export from src/index.ts.const requires JSDoc with @param/@returns. Top-level const literals additionally need @const {Type} and @default tags.any, no null (use undefined), strict-boolean-expressions on, consistent inline-type imports (import { type X } from ...).arrowParens: avoid, trailingComma: es5.no-await-in-loop is on — batch with Promise.all instead.createGitNewTool(controller: ToolsProviderController): Tool.implementation, call resolveAndValidateRepoPath(parameters.repoName, controller.getWorkingDirectory()) before any git call. Do NOT cache the working directory in the factory closure — it is only attached during a live prediction.tool({ name, description, parameters, implementation }) from @lmstudio/sdk with zod schemas for parameters.npm run lint && npm run build — the lint pipeline catches naming, JSDoc, and structural issues.