# Install

For operators who want `@jhfnetboy/dsh-devloop` in a DeepSeek Harness profile. Maintainer cut/tag steps: [Deploy.md](./Deploy.md). What this version includes: [Release.md](./Release.md).

Pinned `#v0.6.11` commands and the Release tarball link need the GitHub Release created **after** the version bump is on `main` (see Deploy.md). Until that Release exists, install from current `main` (moving branch, not a pin):

```bash
dsh plugin --profile web add github:jhfnetboy/DevLoop
```

## Requirements

- Node `^22.19.0 || >=24.0.0` (Node 23 is not in the DSH engines range)
- pnpm (the copy `dsh plugin` forwards to; this repo pins `10.6.3`)
- DeepSeek Harness CLI (`npm i -g @deepseek-ai/dsh`, or `pnpm dsh` from a harness checkout)
- A profile you already boot (`dsh web`, or another named profile)

## One install, not two

This one package is everything: the loop and the `/devloop/` dashboard route,
and — automatically, on a profile that renders a Harness chrome (a browser tab
or DSH Desktop) — a sidebar button that opens the dashboard. Nothing to opt
into and nothing to skip: a headless profile never composes a client bundle at
all, so there is no second package and no decision to make either way.

If a profile still has the standalone `dsh-devloop-ui` package from before this
was folded in, remove it (`dsh plugin --profile web remove dsh-devloop-ui`):
both register into the same `sidebar.footer.action` slot, so leaving both
installed shows two DevLoop buttons rather than conflicting.

## GitHub git spec (runs `prepare`)

After `v0.6.11` exists, pin the tag:

Quote the spec: zsh treats `#` as a glob (`no matches found`).

```bash
dsh plugin --profile web add 'github:jhfnetboy/DevLoop#v0.6.11'
```

Git installs fetch source, not `lib/`. This package’s `prepare` script runs `pnpm build`. pnpm ≥10 will not run that until you allow the package to run scripts.

On pnpm 10.1–10.25, `strictDepBuilds` is often unset: **`pnpm add` can exit 0 and only print `Ignored build scripts: @jhfnetboy/dsh-devloop`**. That is not a successful plugin install. DSH will then load a checkout with no `lib/` and fail on restart. Approve the build whenever pnpm reports an ignored (or blocked) build for this package, even after a successful `add`. Then run a **fresh** `dsh plugin ... add` (same spec). Do not use `pnpm rebuild`: this package only has `prepare`, and `src/` is not in the installed tree, so rebuild cannot produce `lib/`.

**Use the key and field name pnpm printed** — do not assume a single YAML shape.

Typical profile file: `~/.dsh/profiles/web/pnpm-workspace.yaml`.

pnpm 10.1–10.25:

```yaml
onlyBuiltDependencies:
  - @jhfnetboy/dsh-devloop
```

pnpm ≥10.26:

```yaml
allowBuilds:
  "@jhfnetboy/dsh-devloop": true
```

You can also approve from the profile directory:

```bash
pnpm --dir ~/.dsh/profiles/web approve-builds
```

Allow `@jhfnetboy/dsh-devloop` when prompted, then re-run the same `dsh plugin --profile web add ...` so pnpm fetches the git package with `prepare` allowed. Do not use `pnpm rebuild`. Treat that allowance as permission to execute this package’s install-time scripts on your machine.

Restart the profile (`dsh web`) and confirm the layer:

```bash
dsh --profile web --dump-config | grep -A2 devloop
```

You should see a `# == @jhfnetboy/dsh-devloop` layer and an inserted row `id: devloop`.

## GitHub Release tarball (no `prepare`)

After the [v0.6.11 Release](https://github.com/jhfnetboy/DevLoop/releases/tag/v0.6.11) exists, download `jhfnetboy-dsh-devloop-0.6.11.tgz`, then:

```bash
dsh plugin --profile web add ./jhfnetboy-dsh-devloop-0.6.11.tgz
```

The tarball already contains `lib/`, so pnpm does not need a build allowance.

## npm registry

Published. The npm tarball already contains `lib/`, so there is no git `prepare` and no build approval:

```bash
dsh plugin --profile web add @jhfnetboy/dsh-devloop@0.6.11
```

## Local checkout

```bash
git clone https://github.com/jhfnetboy/DevLoop.git
cd DevLoop
git checkout v0.6.11   # or main, until the tag exists
pnpm install
pnpm test
pnpm build
dsh plugin --profile web add /absolute/path/to/DevLoop
```

From this checkout, the Goal template is `templates/GOAL.md`.

## Config

Optional overrides in `~/.dsh/profiles/web/cordis.patch.yml`:

```yaml
- id: devloop
  config:
    root: /path/to/your/project
    tickIntervalMs: 2000
    agentBackend: routed
    plannerRoute: { tier: T3, backend: codex, model: gpt-5.4 }
    reviewerRoute: { tier: T3, backend: claude, model: opus }
    budget:
      maxCostUsdPerDay: 20
      taskTimeoutMinutes: 45
      taskLifetimeMinutes: 135
```

`agentBackend` defaults to `noop` (no spawn). `routed` selects plan/review routes independently and workers from `routing.T0`–`T3`. Fixed `dsh` / `claude` / `codex` modes remain available.

To reuse installed Harness providers rather than spawning their CLIs directly:

```yaml
plannerRoute: { tier: T3, backend: "subagent:codex", model: gpt-5.4 }
reviewerRoute: { tier: T3, backend: "subagent:claude-code", model: opus }
```

The profile must load Harness `agents`, an agent-loop, `subagents`, and both named providers. Provider configuration is authoritative for the actual model; keep the route's descriptive `model` value consistent. DevLoop creates a temporary idle parent Agent at the exact worktree cwd and disposes both parent and child after the one-shot run.

## Arm a project

The plugin is idle until the target workspace contains `.devloop/GOAL.md` (a regular file, not a symlink). A bare `.devloop/` directory does not arm it.

After a GitHub or tarball install:

```bash
mkdir -p /path/to/your/project/.devloop
cp ~/.dsh/profiles/web/node_modules/@jhfnetboy/dsh-devloop/templates/GOAL.md \
  /path/to/your/project/.devloop/GOAL.md
```

Or fetch the template without a clone (use `main` instead of `v0.6.11` until the tag exists):

```bash
mkdir -p /path/to/your/project/.devloop
curl -fsSL https://raw.githubusercontent.com/jhfnetboy/DevLoop/v0.6.11/templates/GOAL.md \
  -o /path/to/your/project/.devloop/GOAL.md
```

Edit `GOAL.md`, then start DSH from that project (or set `config.root`). Each tick writes `.devloop/STATE.json`, appends `.devloop/EVENTS.jsonl`, and updates `PROGRESS.md`.

Backends must finish with the exact machine envelope included in their prompt. Valid plans create tasks; completed implementations are path-checked and host-committed; reviews must echo that exact commit SHA. `PASS` / `PASS_WITH_NOTES` enables the next mechanical merge. It does not push. If STATE shows `supervisor.reason: merge_wedged`, stop the plugin and run `git merge --abort` if needed. Version 0.3 has no supported command to clear this terminal hold; do not hand-edit `STATE.json`.

## Uninstall

```bash
dsh plugin --profile web remove @jhfnetboy/dsh-devloop
```
