@zvk/git-kit
v0.1.3
Published
Node-oriented git ports, safe operation descriptors, formatters, and optional simple-git adapters for ZVK applications.
Downloads
349
Readme
@zvk/git-kit
Node-oriented git ports, safe operation descriptors, formatters, and optional simple-git adapters for ZVK applications.
@zvk/git-kit is for local-first developer tools that need shared git status,
log, diff, branch, stash, tag, and worktree behavior without moving project
lookup, authorization, UI copy, or persistence into a shared package.
Public imports
import type { GitClientPort, GitRepositoryRef } from "@zvk/git-kit";
import { summarizeGitStatus } from "@zvk/git-kit/formatters";
import { assertGitOperationApproved, describeGitReset } from "@zvk/git-kit/operations";
import type { GitOperationDescriptor } from "@zvk/git-kit/operations";
import { createSimpleGitClient } from "@zvk/git-kit/simple-git";
import { createFakeGitClient } from "@zvk/git-kit/test-utils";Use only the package root and exported subpaths:
@zvk/git-kit@zvk/git-kit/ports@zvk/git-kit/formatters@zvk/git-kit/operations@zvk/git-kit/simple-git@zvk/git-kit/test-utils
Package boundaries
The root package exposes structural git types, pure formatters, and operation
descriptors. It depends on @zvk/contracts and must not require simple-git.
See ../../docs/package-boundary-matrix.md for the package-family runtime
boundary matrix. This package is Node-oriented; the optional simple-git
adapter and test fakes stay on explicit subpaths.
@zvk/git-kit/simple-git is the optional Node adapter for apps that already want
simple-git execution. Keep concrete simple-git types behind that subpath.
@zvk/git-kit/test-utils provides deterministic fakes for app tests without
importing a test framework. Apps that need spies should wrap the fake with their
own Vitest or Jest helpers.
Applications own:
- repository root lookup and validation;
- auth, project membership, and destructive-operation policy;
- route names, MCP action names, and UI copy;
- git operation history, audit logs, and persistence;
- concrete queueing, locking, and long-running process behavior.
Repository roots and persistence
Inject repository roots from app-owned project state and pass only the structural
repository reference into @zvk/git-kit ports.
import type { GitClientPort, GitRepositoryRef } from "@zvk/git-kit";
type ProjectGitContext = {
readonly projectId: number;
readonly rootPath: string;
};
function toGitRepositoryRef(project: ProjectGitContext): GitRepositoryRef {
return { rootPath: project.rootPath };
}
export async function getProjectStatus(git: GitClientPort, project: ProjectGitContext) {
const repo = toGitRepositoryRef(project);
const snapshot = await git.status(repo);
await recordGitStatusSnapshot({
projectId: project.projectId,
branch: snapshot.currentBranch,
isClean: snapshot.isClean
});
return snapshot;
}Persist app facts, not package internals. Store project IDs, repository roots, operation names, descriptors, approvals, actor IDs, timestamps, and execution results in the application schema.
Safe operation descriptor flow
Mutating and destructive work must be described before it can be executed. The caller decides whether the descriptor is approved.
import { assertGitOperationApproved, describeGitReset } from "@zvk/git-kit/operations";
const descriptor = describeGitReset({ ref: "HEAD~1", mode: "hard" });
await recordRequestedGitOperation({
projectId,
actorId,
descriptor
});
assertGitOperationApproved(descriptor, approval.approved);Use the descriptor risk to route review:
read-only: safe for normal status, log, diff, branch-list, tag-list, and worktree-list requests.writes-working-tree: requires app policy because files or refs may change.rewrites-history: requires explicit approval and usually stronger UI/MCP confirmation.destructive: requires explicit approval, audit persistence, and a narrow execution path.
@zvk/git-kit classifies risk. The app decides who can approve, where approval
is stored, and how that approval is presented to users or MCP callers.
Optional simple-git adapter
Use the optional adapter when the app wants direct local git execution:
import { createSimpleGitClient } from "@zvk/git-kit/simple-git";
const git = createSimpleGitClient();
const status = await git.status({ rootPath: project.rootPath });Apps can inject a factory for tests or alternate simple-git wiring. Keep adapter construction at the app boundary so repository roots, locks, and policy checks remain visible to the application.
Tests and fakes
Use @zvk/git-kit/test-utils for framework-neutral fake git clients:
import { createFakeGitClient } from "@zvk/git-kit/test-utils";
const git = createFakeGitClient({
status: { currentBranch: "main", ahead: 0, behind: 0, files: [], isClean: true }
});Keep assertions in the app test framework. The package fake should provide deterministic responses, not product policy.
Promptliano migration sketch
Move shared git shape and safety logic into @zvk/git-kit, but keep Promptliano
ownership of product behavior:
- Routes load project context, validate repository access, call a
GitClientPort, and map results to existing HTTP response contracts. - Services wrap injected git ports and app repositories. They own project lookup, persistence, locking, and audit writes.
- MCP tools keep their action names and caller-facing copy in Promptliano. For
risky operations, return or persist a
GitOperationDescriptorfirst, then execute only after Promptliano records explicit approval. - Tests replace local git doubles with
@zvk/git-kit/test-utilsfakes while keeping Promptliano authorization and persistence assertions local.
Repo Skill
Use .codex/skills/use-zvk-git-kit/SKILL.md when maintaining this package.
See ../../docs/package-boundary-matrix.md for the browser-safe, adapter-only, Node-only, and test-only subpaths.
