Skip to main content

VCS Integration Guide

Smithers has first-class support for Git and Jujutsu (jj) version control.

Git Commits

Create commits with the Commit component:
import { Commit } from "smithers-orchestrator";

<Commit
  message="feat: Add user authentication"
  all  // Stage all changes
  notes={{ smithers: true, prompt: "Add auth" }}
  onFinished={(result) => {
    console.log(`Committed: ${result.commitHash}`);
  }}
/>

Auto-Generated Messages

Let Claude generate the commit message:
<Commit autoGenerate all />

Selective Commits

Commit specific files:
<Commit
  message="fix: Update config"
  files={["config.json", "settings.ts"]}
/>

Git Notes

Store metadata in git notes:
<Commit
  message="feat: New feature"
  notes={{
    smithers: true,
    executionId: executionId,
    prompt: "Implement the new feature",
    model: "sonnet",
  }}
/>
Read notes:
git notes show HEAD

Code Review

Review changes before committing:
import { useQueryValue } from "smithers-orchestrator/reactive-sqlite";

function ReviewAndCommit() {
  const { db, reactiveDb } = useSmithers();

  const phase = useQueryValue<string>(
    reactiveDb,
    "SELECT value FROM state WHERE key = 'phase'"
  ) ?? "implement";

  const setPhase = (newPhase: string) => {
    db.state.set("phase", newPhase);
  };

  return (
    <SmithersProvider db={db} executionId={executionId} maxIterations={5}>
      <If condition={phase === "implement"}>
        <Claude
          allowedTools={["Edit", "Write"]}
          onFinished={() => setPhase("review")}
        >
          Implement the feature.
        </Claude>
      </If>

      <If condition={phase === "review"}>
        <Review
          target={{ type: "diff", ref: "main" }}
          criteria={[
            "No security vulnerabilities",
            "Tests included",
          ]}
          onFinished={(review) => {
            if (review.approved) {
              setPhase("commit");
            } else {
              setPhase("implement");
            }
          }}
        />
      </If>

      <If condition={phase === "commit"}>
        <Commit
          autoGenerate
          all
          onFinished={() => setPhase("done")}
        />
      </If>
    </SmithersProvider>
  );
}

Snapshots (Jujutsu)

For jj users, create snapshots:
// Before risky operations
await db.vcs.logSnapshot({
  snapshotId: await jjSnapshot(),
  description: "Before refactoring",
  timestamp: new Date(),
});

// Perform work...

// Rollback if needed
const snapshots = await db.vcs.getSnapshots(1);
await jjRestore(snapshots[0].snapshotId);

Database Tracking

All VCS operations are logged to the database:
// Log a commit
await db.vcs.logCommit({
  hash: "abc123",
  message: "feat: Add feature",
  author: "claude",
  timestamp: new Date(),
  filesChanged: 5,
  insertions: 100,
  deletions: 20,
  vcsType: "git",
});

// Query commits
const commits = await db.vcs.getCommits(10);

Review Tracking

// Log a review
await db.vcs.logReview({
  reviewId: "r1",
  target: "abc123",
  approved: false,
  summary: "Issues found",
  issues: [
    { severity: "high", file: "auth.ts", description: "..." }
  ],
});

// Get blocking reviews
const blocking = await db.vcs.getBlockingReviews();

Complete Workflow

import { useQueryValue } from "smithers-orchestrator/reactive-sqlite";

function FeatureWorkflow() {
  const { db, reactiveDb } = useSmithers();

  const phase = useQueryValue<string>(
    reactiveDb,
    "SELECT value FROM state WHERE key = 'phase'"
  ) ?? "implement";

  const setPhase = (newPhase: string) => {
    db.state.set("phase", newPhase);
  };

  return (
    <SmithersProvider db={db} executionId={executionId} maxIterations={10} snapshotBeforeStart>
      <If condition={phase === "implement"}>
        <Phase name="Implementation">
          <Step name="implement">
            <Claude
              allowedTools={["Edit", "Write"]}
              onFinished={() => setPhase("test")}
            >
              Implement the feature.
            </Claude>
          </Step>
        </Phase>
      </If>

      <If condition={phase === "test"}>
        <Phase name="Testing">
          <Step name="test">
            <Claude
              allowedTools={["Bash"]}
              onFinished={(result) => {
                if (result.output.includes("PASS")) {
                  setPhase("review");
                } else {
                  setPhase("implement");
                }
              }}
            >
              Run the tests.
            </Claude>
          </Step>
        </Phase>
      </If>

      <If condition={phase === "review"}>
        <Phase name="Review">
          <Step name="review">
            <Review
              target={{ type: "diff", ref: "main" }}
              criteria={["No security issues", "Tests pass"]}
              onFinished={(review) => {
                if (review.approved) {
                  setPhase("commit");
                } else {
                  setPhase("implement");
                }
              }}
            />
          </Step>
        </Phase>
      </If>

      <If condition={phase === "commit"}>
        <Phase name="Commit">
          <Step name="commit">
            <Commit
              autoGenerate
              all
              notes={{ smithers: true }}
              onFinished={() => setPhase("done")}
            />
          </Step>
        </Phase>
      </If>
    </SmithersProvider>
  );
}