@brainervirus/workit-claude-code 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +19 -0
- package/README.md +46 -0
- package/agents/implementer.md +26 -0
- package/agents/reviewer.md +23 -0
- package/agents/verifier.md +26 -0
- package/assets/templates/execution-contract.md +40 -0
- package/assets/templates/headers.md +3 -0
- package/assets/templates/hygiene/.editorconfig +8 -0
- package/assets/templates/hygiene/.gitattributes +3 -0
- package/assets/templates/hygiene/CHANGELOG.md +14 -0
- package/assets/templates/hygiene/CONTRIBUTING.md +3 -0
- package/assets/templates/hygiene/LICENSE +21 -0
- package/assets/templates/hygiene/README.md +3 -0
- package/assets/templates/issue-update.md +5 -0
- package/assets/templates/plan-template.md +27 -0
- package/assets/templates/spec-template.md +63 -0
- package/assets/templates/workit-contract.md +12 -0
- package/bin/workit +24 -0
- package/bin/workit-hook.mjs +51 -0
- package/dist/workit-hook.js +165 -0
- package/dist/workit.js +78195 -0
- package/hooks/hooks.json +68 -0
- package/package.json +48 -0
- package/skills/babysit/SKILL.md +46 -0
- package/skills/behavioral-tdd/SKILL.md +57 -0
- package/skills/blast-radius/SKILL.md +35 -0
- package/skills/challenge/SKILL.md +56 -0
- package/skills/debug/SKILL.md +48 -0
- package/skills/deslop/SKILL.md +40 -0
- package/skills/diagram/SKILL.md +36 -0
- package/skills/green-run/SKILL.md +33 -0
- package/skills/handoff/SKILL.md +46 -0
- package/skills/implement/SKILL.md +57 -0
- package/skills/mockup/SKILL.md +32 -0
- package/skills/plan/SKILL.md +54 -0
- package/skills/review/SKILL.md +64 -0
- package/skills/steer/SKILL.md +48 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "workit",
|
|
3
|
+
"displayName": "Workit",
|
|
4
|
+
"version": "2.6.0",
|
|
5
|
+
"description": "Workflow rails for agentic coding: task context on every session, branch policy on shell commands, and the workit method skills",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "BrainerVirus"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/BrainerVirus/workit#readme",
|
|
10
|
+
"repository": "https://github.com/BrainerVirus/workit",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"agentic-coding",
|
|
14
|
+
"branch-policy",
|
|
15
|
+
"skills",
|
|
16
|
+
"task-management",
|
|
17
|
+
"workflow"
|
|
18
|
+
]
|
|
19
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @brainervirus/workit-claude-code
|
|
2
|
+
|
|
3
|
+
[](https://github.com/BrainerVirus/workit/actions/workflows/ci.yml)
|
|
4
|
+
[](../../LICENSE)
|
|
5
|
+
|
|
6
|
+
Workit plugin for Claude Code: task context on session start and per turn,
|
|
7
|
+
branch policy on `git` shell commands, fourteen method skills (`/workit:<name>`),
|
|
8
|
+
and `verifier`, `reviewer` and `implementer` agents.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
Latest published (the repository root is the marketplace; its entry installs
|
|
13
|
+
this npm package):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
claude plugin marketplace add BrainerVirus/workit
|
|
17
|
+
claude plugin install workit@workit
|
|
18
|
+
claude plugin marketplace update workit && claude plugin update workit@workit # update
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Local pin to a checkout (hooks and `bin/workit` run the sources with Bun):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun install
|
|
25
|
+
bun packages/workit-claude-code/scripts/build.ts --skills-only
|
|
26
|
+
claude --plugin-dir "$PWD/packages/workit-claude-code"
|
|
27
|
+
# or, for every session:
|
|
28
|
+
export CLAUDE_CODE_PLUGIN_DIRS="$HOME/path/to/workit/packages/workit-claude-code"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`WORKIT_CLAUDE_RUNTIME=source|dist` forces one runtime;
|
|
32
|
+
`WORKIT_SHIM_TRACE=1 workit …` prints which `workit` entry ran.
|
|
33
|
+
|
|
34
|
+
## Layout
|
|
35
|
+
|
|
36
|
+
| Path | Purpose |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `.claude-plugin/plugin.json` | Manifest (version synced at release) |
|
|
39
|
+
| `hooks/hooks.json` | SessionStart (startup/resume/clear/compact/fork), UserPromptSubmit, PreToolUse (Bash/PowerShell `git *`), SubagentStart |
|
|
40
|
+
| `bin/workit-hook.mjs` | Hook launcher: source with Bun in a checkout, `dist/workit-hook.js` when installed; fails open (`{}` + one stderr line) when neither can run |
|
|
41
|
+
| `bin/workit` | `workit` on the Bash tool's PATH (same source/dist switch) |
|
|
42
|
+
| `agents/` | `verifier`, `reviewer` (read-only), `implementer` (`isolation: worktree`) |
|
|
43
|
+
| `skills/` | Generated by `scripts/build.ts` from `packages/workit-core/skills` (not committed) |
|
|
44
|
+
| `evals/` | Opt-in `claude plugin eval` suite (nightly / `eval` label, not a PR gate) |
|
|
45
|
+
|
|
46
|
+
Requires Node.js 24+ (installed plugin) or Bun (local pin).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implementer
|
|
3
|
+
description: Implements one scoped workit brief in an isolated git worktree and reports what changed and how it was verified. Use to delegate a well-defined slice (goal, scope, acceptance, verify, forbidden, report) so it can run in parallel with other work.
|
|
4
|
+
isolation: worktree
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a workit implementer working in your own git worktree.
|
|
8
|
+
|
|
9
|
+
Refuse to start without a complete brief. It must state: goal, scope (files
|
|
10
|
+
or areas you may touch), acceptance (observable outcomes), verify (exact
|
|
11
|
+
commands), forbidden (what you must not touch or do), and report (what to
|
|
12
|
+
hand back). If anything is missing, report which field is missing and stop.
|
|
13
|
+
|
|
14
|
+
1. Your worktree starts on a branch name chosen by Claude Code, which may not
|
|
15
|
+
satisfy the repository's branch policy. Before any commit, create or switch
|
|
16
|
+
to a policy-compliant branch (`workit` CLI branch setup when available,
|
|
17
|
+
otherwise `git switch -c <type>/<slug>`). A hook denies protected or
|
|
18
|
+
non-compliant branch names; follow the unblock hint it prints.
|
|
19
|
+
2. Stay inside the declared scope. Anything outside it goes in the report as
|
|
20
|
+
a follow-up, not into the diff.
|
|
21
|
+
3. Make the change in small, reviewable commits with conventional messages.
|
|
22
|
+
4. Run every verify command from the brief and keep the real exit codes.
|
|
23
|
+
5. Report: branch and head SHA, files changed, each verify command with its
|
|
24
|
+
exit code, acceptance items met or not, and any deviation from the brief.
|
|
25
|
+
|
|
26
|
+
Never push, open a PR, or merge unless the brief explicitly asks for it.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reviewer
|
|
3
|
+
description: Fresh-context code reviewer for a workit candidate. Reads the real diff and checks for correctness, regressions, security, and scope creep, then records findings with a severity and a ruling. Use for independent review of a branch or PR.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
disallowedTools: Write, Edit, NotebookEdit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the workit reviewer. Review the real candidate, not the author's
|
|
9
|
+
description of it.
|
|
10
|
+
|
|
11
|
+
1. Identify the candidate: `git rev-parse HEAD`, the base branch, and
|
|
12
|
+
`git diff <base>...HEAD`. For a PR, read its status and unresolved threads
|
|
13
|
+
with `gh`/`glab` (or `workit pr status` when the CLI offers it).
|
|
14
|
+
2. Read the task brief: goal, scope, forbidden areas, acceptance.
|
|
15
|
+
3. Examine the diff for correctness, regression risk, security or data
|
|
16
|
+
consequences, missing tests, and changes outside the declared scope.
|
|
17
|
+
Confirm claims by reading code and check output; never infer evidence.
|
|
18
|
+
4. Report each finding as: file:line, severity (blocker / major / minor /
|
|
19
|
+
nit), what is wrong, and the concrete fix. End with a ruling: approve,
|
|
20
|
+
approve with nits, or request changes.
|
|
21
|
+
|
|
22
|
+
Stay read-only: you may run read and test commands, never commits, pushes,
|
|
23
|
+
merges, or edits.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verifier
|
|
3
|
+
description: Independently verifies a workit candidate (a branch, commit, or PR) by running its real checks and reporting a pass/fail verdict with evidence. Use after an implementer finishes and before a merge, never on work this session authored.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
disallowedTools: Write, Edit, NotebookEdit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are the workit verifier. You did not write the candidate, and you must not
|
|
9
|
+
change it: you only observe and report.
|
|
10
|
+
|
|
11
|
+
1. Pin the candidate first: `git rev-parse HEAD` and `git status --short`. A
|
|
12
|
+
dirty tree or a moving HEAD is itself a finding.
|
|
13
|
+
2. Read the task brief (goal, scope, acceptance, verify commands). If the
|
|
14
|
+
repository has a `verify-<app>` script or skill, run it; otherwise run the
|
|
15
|
+
verify commands from the brief exactly as written. Never substitute an
|
|
16
|
+
easier command.
|
|
17
|
+
3. Run each check through the workit CLI when it is available (`workit
|
|
18
|
+
--help` lists the verbs), so the result is CLI-observed rather than
|
|
19
|
+
claimed. Capture the exit code and the failing output tail.
|
|
20
|
+
4. Check every acceptance item against observed behavior, not against the
|
|
21
|
+
author's summary.
|
|
22
|
+
5. Report: candidate SHA, each check with its exit code, each acceptance item
|
|
23
|
+
as met / not met / not verifiable, and an overall verdict (pass or fail).
|
|
24
|
+
When the CLI offers a verdict verb, record the verdict with it.
|
|
25
|
+
|
|
26
|
+
Do not fix anything you find. A failing check is a verdict, not a task.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Load resolved method skills through the host skill loader when policy selects them. Implement the existing plan; do not re-plan.
|
|
2
|
+
|
|
3
|
+
**Spec:** <SPEC_PATH>
|
|
4
|
+
**Plan:** <PLAN_PATH>
|
|
5
|
+
**Branch:** <BRANCH>
|
|
6
|
+
|
|
7
|
+
## Hard gates
|
|
8
|
+
|
|
9
|
+
- Inspect task state before acting. On OpenCode, Cursor, Codex, and Pi use the eight shared `workit_*` families (`workit_task`, `workit_policy`, `workit_evidence`, `workit_finding`, `workit_decision`, `workit_worker`, `workit_writer`, `workit_state`). On the CLI host use `workit <family> <action>` with the same actions (hyphenated on the CLI).
|
|
10
|
+
- Never use a worktree. Branch changes are in-place through the approved `git.branch_setup` external action (CLI: `workit action git.branch_setup --payload …`).
|
|
11
|
+
- Task metadata lives under `.workit/`; never edit it directly. Record progress, evidence, findings, decisions, and worker state only through the shared operations.
|
|
12
|
+
- Helpers cannot widen scope, record binding decisions, close or pause the task, assign further helpers, or resolve blockers for the lead.
|
|
13
|
+
- On Cursor, pass the active workspace as `workspace_root` on every repository-scoped call.
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
1. If there is no active or paused task, call `workit_task` with `action: "start"` then `workit_policy` with `action: "assess"` (CLI: `workit task start …` then `workit policy assess …`).
|
|
18
|
+
2. Load `workit-plan`, list tasks with `workit_task` `action: "list"`, and mirror visible todo state to the host UI.
|
|
19
|
+
3. When policy requires a feature branch, resolve it with read-only `context.read` and apply `git.branch_setup` only after native approval.
|
|
20
|
+
|
|
21
|
+
## Remaining-task loop
|
|
22
|
+
|
|
23
|
+
For each bounded plan task:
|
|
24
|
+
|
|
25
|
+
1. Mark the item in progress in the host todo UI and record boundary progress with `workit_task` `action: "progress"`.
|
|
26
|
+
2. Route by policy: assign bounded workers with `workit_worker` `action: "assign"` when delegation is available; otherwise implement inline. Acquire product-write ownership with `workit_writer` `action: "acquire"` before repository mutations; release it when done.
|
|
27
|
+
3. Record checks and artifacts with `workit_evidence` `action: "record"`. Record review concerns with `workit_finding` `action: "record"`; resolve or defer them with `finding.resolve`. Blocking findings may trigger at most **two** fix+re-review rounds per task; advisory taste/YAGNI items still use `finding.record` and never pause the loop by direct file edit.
|
|
28
|
+
4. Never advance while a foreign writer is active or blocking findings remain open for the current candidate.
|
|
29
|
+
|
|
30
|
+
## Final gate
|
|
31
|
+
|
|
32
|
+
Run repository verification (CLI: `workit doctor`; hosts: approved project verify when policy requires it). **Mandatory:** close the lead task with `workit_task` `action: "close"` (CLI: `workit task close --payload … [--confirm]`) once requirements are satisfied and verification passes — never finish while the task is still `active` or `paused`.
|
|
33
|
+
|
|
34
|
+
## Task order
|
|
35
|
+
|
|
36
|
+
<TASK_LIST>
|
|
37
|
+
|
|
38
|
+
## Quality gate
|
|
39
|
+
|
|
40
|
+
- Specs/plans follow `templates/spec-template.md` / `templates/plan-template.md`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) <YEAR> <HOLDER>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# <Feature> Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** Load `workit-implement` when policy selects implementation. Use bounded `workit_worker` delegation when the host supports it; otherwise execute inline within writer scope. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Spec:** `docs/<slug>/spec.md`
|
|
6
|
+
**Branch:** `feature/<slug>`
|
|
7
|
+
|
|
8
|
+
**Goal:** <one sentence>
|
|
9
|
+
|
|
10
|
+
## Global Constraints
|
|
11
|
+
|
|
12
|
+
- Each task lands exactly one contiguous non-empty commit range (`base..head`): fix rounds append commits to that range and never rewrite/amend an active review range; record the real base..head shas in task progress.
|
|
13
|
+
- The final task closes the lead Workit task with `workit_task` `action: "close"` (CLI: `workit task close --payload … [--confirm]`) once requirements are satisfied and repository verification passes — never finish while the task is still `active` or `paused`.
|
|
14
|
+
- <project-wide requirements, one line each>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
### Task N: <Component>
|
|
19
|
+
|
|
20
|
+
- [ ] **Step 1: <action>**
|
|
21
|
+
|
|
22
|
+
<!-- per-task criteria: how this task is verified -->
|
|
23
|
+
**Criteria:** <verifiable check>
|
|
24
|
+
|
|
25
|
+
| Status | Task |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| pending | N: <Component> |
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Spec: <feature>
|
|
2
|
+
|
|
3
|
+
**Branch:** `feature/<slug>`
|
|
4
|
+
|
|
5
|
+
**Change:** ADDED|MODIFIED|REMOVED — <one-sentence intent>. (Small work with
|
|
6
|
+
no durable agreement: `Spec: none (<reason>)`, no file.)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
<!-- Why does this exist? What problem does it solve? 1-3 sentences. -->
|
|
11
|
+
|
|
12
|
+
## Goals
|
|
13
|
+
|
|
14
|
+
- <!-- measurable, one per bullet -->
|
|
15
|
+
|
|
16
|
+
## Non-goals
|
|
17
|
+
|
|
18
|
+
- <!-- explicitly out of scope -->
|
|
19
|
+
|
|
20
|
+
## Architecture
|
|
21
|
+
|
|
22
|
+
<!-- May be `N/A (<reason>)` when the change has no flows or architecture. -->
|
|
23
|
+
<!-- Otherwise REQUIRED: render a mermaid diagram (workit-diagram skill). -->
|
|
24
|
+
```mermaid
|
|
25
|
+
flowchart TD
|
|
26
|
+
A[Start] --> B[Step]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
<!-- REQUIRED if this spec touches UI: render an ASCII wireframe (workit-mockup skill). -->
|
|
30
|
+
```text
|
|
31
|
+
┌──────────────┐
|
|
32
|
+
│ Header │
|
|
33
|
+
└──────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Data flow / contracts
|
|
37
|
+
|
|
38
|
+
<!-- REQUIRED when there is a glossary, scope comparison, or contracts: use markdown tables. -->
|
|
39
|
+
| Term | Meaning |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| <term> | <meaning> |
|
|
42
|
+
|
|
43
|
+
## Acceptance criteria
|
|
44
|
+
|
|
45
|
+
<!-- REQUIRED: enumerable, each verifiable. Numbered CA-01, CA-02, ... -->
|
|
46
|
+
<!-- Requirements use SHALL/MUST (one per bullet, observable, no HOW); each
|
|
47
|
+
carries at least one GIVEN/WHEN/THEN, including the most-regretted edge. -->
|
|
48
|
+
- CA-01 …
|
|
49
|
+
|
|
50
|
+
## Review checklist
|
|
51
|
+
|
|
52
|
+
<!-- Before implementation: intent matches; nothing extra; each requirement
|
|
53
|
+
testable with an exercising scenario; most-cared case covered;
|
|
54
|
+
tasks trace to requirements; you would sign if built exactly as written. -->
|
|
55
|
+
- [ ] …
|
|
56
|
+
|
|
57
|
+
## Decisions
|
|
58
|
+
|
|
59
|
+
- D-01 …
|
|
60
|
+
|
|
61
|
+
## Future work
|
|
62
|
+
|
|
63
|
+
- …
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Workit contract
|
|
2
|
+
|
|
3
|
+
Workit keeps one accountable lead and one shared task state. Inspect current
|
|
4
|
+
task state before acting; use only the shared operations for task, policy,
|
|
5
|
+
evidence, finding, decision, worker, writer, and state changes. Authority is
|
|
6
|
+
bounded by the requested scope, current revision, caller/session provenance, and
|
|
7
|
+
observed capabilities. Never claim host enforcement or evidence that the host
|
|
8
|
+
cannot provide. Preserve unresolved requirements, gaps, and uncertain workers.
|
|
9
|
+
|
|
10
|
+
Focused methods are loaded only when the resolved policy requires them. A method
|
|
11
|
+
must call the shared operations and must not create a second lifecycle, approval
|
|
12
|
+
chain, or task-state representation.
|
package/bin/workit
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# `workit` on the Claude Code Bash tool's PATH (Claude adds a plugin's bin/).
|
|
3
|
+
# Local pin: run the CLI from the monorepo sources with bun. Installed
|
|
4
|
+
# package: run the bundled dist/workit.js with node.
|
|
5
|
+
# WORKIT_CLAUDE_RUNTIME=source|dist forces one; WORKIT_SHIM_TRACE=1 prints
|
|
6
|
+
# the resolved entry on stderr.
|
|
7
|
+
set -e
|
|
8
|
+
here=$(dirname "$0")
|
|
9
|
+
root=$(cd "$here/.." && pwd)
|
|
10
|
+
main="$root/../workit-cli/src/main.ts"
|
|
11
|
+
entry=""
|
|
12
|
+
if [ "${WORKIT_CLAUDE_RUNTIME:-}" != "dist" ] && [ -f "$root/../workit-core/src/core.ts" ] && [ -f "$main" ]; then
|
|
13
|
+
entry="$main"
|
|
14
|
+
fi
|
|
15
|
+
if [ "${WORKIT_CLAUDE_RUNTIME:-}" = "source" ] && [ -z "$entry" ]; then
|
|
16
|
+
echo "workit: WORKIT_CLAUDE_RUNTIME=source but no monorepo CLI source next to $root" >&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
if [ -n "$entry" ]; then
|
|
20
|
+
[ "${WORKIT_SHIM_TRACE:-}" = "1" ] && echo "workit-shim: source $entry" >&2
|
|
21
|
+
exec bun "$entry" "$@"
|
|
22
|
+
fi
|
|
23
|
+
[ "${WORKIT_SHIM_TRACE:-}" = "1" ] && echo "workit-shim: dist $root/dist/workit.js" >&2
|
|
24
|
+
exec node "$root/dist/workit.js" "$@"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Claude Code hook launcher (hooks/hooks.json runs `node <this file>`, exec
|
|
3
|
+
// form, so no shell is involved on any OS). Two layouts:
|
|
4
|
+
// - local pin (`claude --plugin-dir <checkout>/packages/workit-claude-code`):
|
|
5
|
+
// the monorepo sources sit next to this package, so the TypeScript entry
|
|
6
|
+
// runs from source with bun: edits apply without a rebuild;
|
|
7
|
+
// - installed package (npm/marketplace): dist/workit-hook.js is imported.
|
|
8
|
+
// WORKIT_CLAUDE_RUNTIME=source|dist forces one.
|
|
9
|
+
// Fail-open: when the runtime cannot start (no bun for the pin, a missing or
|
|
10
|
+
// unloadable dist/), the launcher answers `{}` with exit 0 and one
|
|
11
|
+
// `[workit] Claude Code hook unavailable: …` line on stderr. Claude then
|
|
12
|
+
// proceeds as if no Workit hook were installed (no context, no branch
|
|
13
|
+
// policy): a broken hook must never brick the host.
|
|
14
|
+
import { spawnSync } from "node:child_process";
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
16
|
+
import path from "node:path";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
|
|
19
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
20
|
+
const source = path.join(root, "src", "run.ts");
|
|
21
|
+
const dist = path.join(root, "dist", "workit-hook.js");
|
|
22
|
+
const mode = process.env.WORKIT_CLAUDE_RUNTIME;
|
|
23
|
+
const fromSource =
|
|
24
|
+
mode === "source" ||
|
|
25
|
+
(mode !== "dist" &&
|
|
26
|
+
existsSync(source) &&
|
|
27
|
+
existsSync(path.join(root, "..", "workit-core", "src", "hooks", "index.ts")));
|
|
28
|
+
|
|
29
|
+
const failOpen = (reason) => {
|
|
30
|
+
process.stderr.write(`[workit] Claude Code hook unavailable: ${reason}\n`);
|
|
31
|
+
process.stdout.write("{}\n");
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (fromSource) {
|
|
35
|
+
const run = spawnSync(process.env.WORKIT_BUN ?? "bun", [source], {
|
|
36
|
+
stdio: "inherit",
|
|
37
|
+
windowsHide: true,
|
|
38
|
+
});
|
|
39
|
+
if (run.error) failOpen(`bun is required for the local pin (${run.error.message})`);
|
|
40
|
+
else process.exitCode = run.status ?? 0;
|
|
41
|
+
} else if (existsSync(dist)) {
|
|
42
|
+
let runClaudeHook;
|
|
43
|
+
try {
|
|
44
|
+
({ runClaudeHook } = await import(pathToFileURL(dist).href));
|
|
45
|
+
} catch (error) {
|
|
46
|
+
failOpen(`cannot load ${dist} (${error instanceof Error ? error.message : String(error)})`);
|
|
47
|
+
}
|
|
48
|
+
if (runClaudeHook) process.exitCode = await runClaudeHook(process.stdin, process.stdout);
|
|
49
|
+
} else {
|
|
50
|
+
failOpen(`${dist} is missing; run \`bun scripts/build.ts\` in ${root}`);
|
|
51
|
+
}
|