Projects & Worktrees
A project is the primary checkout plus its detached git worktrees, and it is
the entry point for the chained resource API. Everything path-sensitive —
config, actions, services, dependencies — is reached through namespaces that act
on the active worktree unless you pass an explicit worktree.
Resolving projects
Section titled “Resolving projects”import { DenvigSDK } from '@denvig/sdk'
const denvig = new DenvigSDK({ client: 'my-app' })
// By identifier or pathconst project = await denvig.projects.retrieve('github:marcqualie/denvig')
// List every discovered project (each family rooted at its primary checkout)const projects = await denvig.projects.list({ withConfig: true })
// Detect from cwd without throwingconst { project: detected, projectPath, slug } = await denvig.projects.detect()Project properties
Section titled “Project properties”project.id // stable internal idproject.slug // e.g. github:marcqualie/denvigproject.name // configured name, or the slugproject.path // absolute path of the active checkoutproject.refs // known git refsproject.activeWorktree // the checkout this instance currently acts onproject.primaryWorktree // the primary ("main") checkoutWorktrees
Section titled “Worktrees”A project exposes all of its checkouts through the worktrees namespace.
// List every checkout (primary + sibling worktrees)const worktrees = project.worktrees.list()
// Retrieve a checkout by branch name ("main" = primary)const feature = project.worktrees.retrieve('feature/x')Worktree properties
Section titled “Worktree properties”const wt = project.activeWorktree
wt.name // worktree namewt.branch // branch the checkout is onwt.path // absolute path on diskwt.slug // project slugwt.id // stable idwt.isPrimary // true for the primary checkoutwt.config // resolved ProjectConfigSchema, with source pathswt.services // services declared in this checkout's configawait wt.actions // all runnable actions, keyed by nameawait wt.dependencies() // detected dependencies for this checkoutSelecting the active worktree
Section titled “Selecting the active worktree”selectWorktree switches which checkout subsequent worktree-sensitive operations
act on. It throws if the branch is unknown.
project.selectWorktree('feature/x')// project.activeWorktree is now the feature/x checkout
const action = await project.actions.retrieve('build') // runs in feature/xAlternatively, pass worktree to a single call without changing the active one:
const action = await project.actions.retrieve('build', { worktree: 'feature/x' })const service = await project.services.retrieve('api', { worktree: 'feature/x' })Project info & plugins
Section titled “Project info & plugins”// Summary including aggregate service statusconst info = await project.info()
// Available plugins and the actions each resolvesconst plugins = await project.plugins()Configuration
Section titled “Configuration”const config = await project.config.retrieve()console.log(config.sourcePaths) // files the config was loaded fromTeardown
Section titled “Teardown”Stop all of the active checkout’s services and remove them from launchctl:
await project.teardown({ removeLogs: true })Resource identifiers
Section titled “Resource identifiers”Denvig builds canonical IDs (and hashes) for resources, used internally for log paths and service names. You can construct them yourself:
project.resourceId({ resource: 'service/api' })// @marcqualie/denvig#root|service/api
project.resourceHash({ workspace: 'apps/web', resource: 'action/dev' })// { id: '…', hash: 'abc123…' }