lathe-cli 1.0.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/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # Lathe
2
+
3
+ Claude Code を agent backend にした target/meta 二層 harness を、git branch + worktree で物理分離する CLI。
4
+
5
+ ## 想定するロール分離
6
+
7
+ | role | やること | 接点 |
8
+ |---|---|---|
9
+ | 開発者 | feature branch で vibe coding、PR を develop に出す | git / gh |
10
+ | target agent | PR を polish 実装に置き換える、commit して PR を更新 | plan HTML 出力、approval で停止 |
11
+ | overseer | plan HTML レビュー、PR レビュー、merge | claude UI + GitHub PR |
12
+ | meta operator | runs/ を読み harness/ を改善、PR を develop に出す | meta agent と対話 |
13
+
14
+ ## install
15
+
16
+ ```sh
17
+ npm install -g lathe-cli
18
+ ```
19
+
20
+ 依存:`git` 2.10+、`jq`、`claude` (Claude Code CLI)、`gh` (GitHub CLI、`lathe process` で必要)。`postinstall` で警告のみ出します(fail させません)。
21
+
22
+ ## init
23
+
24
+ 空のディレクトリで:
25
+
26
+ ```sh
27
+ mkdir myapp && cd myapp
28
+ lathe init
29
+ ```
30
+
31
+ これで以下ができます:
32
+
33
+ ```
34
+ myapp/
35
+ ├── .git/ 共有 bare repo
36
+ ├── main/ main worktree(あなたの app code)
37
+ ├── develop/ develop worktree(target が住む、target/.claude/ が sync で生成)
38
+ └── meta/ meta worktree(harness/ + meta agent + improvements/)
39
+ ```
40
+
41
+ 3 つの worktree は同じ bare repo を共有しているので、git で内容を相互伝搬できます。
42
+
43
+ ## 日常コマンド
44
+
45
+ ```sh
46
+ lathe target [args...] # cd develop/target && claude args
47
+ lathe meta [args...] # cd meta/meta && claude args
48
+ lathe sync # develop/bin/sync.sh 手動実行
49
+ lathe process <pr#> # PR pickup → tasks/<pr#>/ worktree 作成 → target 起動
50
+ lathe help # ヘルプ
51
+ ```
52
+
53
+ どの worktree や project root で実行しても、git の共通 dir から自動で正しい場所に移動します。
54
+
55
+ ## 標準ワークフロー
56
+
57
+ ```sh
58
+ cd myapp/main
59
+
60
+ # feature 切る(base は main / develop どちらでも好み)
61
+ git checkout -b feature/X main
62
+ # vibe coding(claude などで自由に)
63
+ git add . && git commit
64
+ git push -u origin feature/X
65
+ gh pr create --base develop --title "..." --body "..."
66
+
67
+ # overseer
68
+ lathe process <pr#>
69
+ # claude UI で「Read .lathe-task.md from the added directory and process it」を貼り付け
70
+ # orchestrator が plan → 承認 → coder/reviewer dispatch → commit/push → PR 更新
71
+ gh pr merge <pr#> # develop に merge
72
+
73
+ # meta operator(任意のタイミング)
74
+ cd myapp/meta
75
+ git fetch && git merge --no-edit develop # 最新 runs/ を取り込み
76
+ lathe meta
77
+ # meta agent が runs/ 読む → harness/ 編集 → improvements/<id>/ 記録 → commit
78
+ git push -u origin meta
79
+ gh pr create --base develop --head meta --title "harness: ..."
80
+ gh pr merge <meta pr#>
81
+ # develop に meta が merge されると post-merge hook が sync.sh 自動実行
82
+ # 次回 target session は更新後の harness で動く
83
+
84
+ # release
85
+ cd myapp/develop
86
+ git checkout main
87
+ git merge develop
88
+ git push origin main
89
+ ```
90
+
91
+ ## 設計の要点
92
+
93
+ - **branch / worktree でロール分離**:各 agent / role が物理的に別ディレクトリで動くので、CLAUDE.md / settings.json / hooks が混ざらない
94
+ - **harness は meta が編集し、sync で target/.claude/ に展開**:Claude Code 本体の `.claude/` sensitive-file guard を agent tool で突破できないため、meta は harness/ を編集(普通の dir、guard なし)→ develop で sync.sh が外部 shell から target/.claude/ を上書き、という回路で迂回
95
+ - **runs/ は develop で auto-commit**:target session の Stop hook が `git commit` するので、meta は `git merge develop` で読める。symlink や中央 store 不要
96
+ - **post-merge hook が auto-sync**:meta の harness 改善が develop に merge された瞬間に target/.claude/ が再生成される
97
+
98
+ ## 動作確認済み(v1)
99
+
100
+ - npm パッケージ無しでも `git clone` install で動作
101
+ - `lathe init` で bare repo + 3 worktree + post-merge hook 設置
102
+ - target session 実行、runs auto-commit on develop
103
+ - meta worktree が `git merge develop` で runs/ 読込
104
+ - meta が harness/CLAUDE.md 編集 → develop merge → post-merge hook → sync 自動 → target/CLAUDE.md 反映
105
+ - `lathe target` / `lathe meta` / `lathe sync` がどの worktree から実行しても正しい worktree を見つける
106
+
107
+ ## 既知の v1 制限
108
+
109
+ - meta → develop merge で meta/ + improvements/ overlay も develop に持ち込まれる(cherry-pick / 別 PR 機構で v2 解決)
110
+ - `lathe process` の prompt 渡しは手動ペースト(claude TUI が piped 初期 prompt を確実に取らないため)
111
+ - post-merge hook は local merge のみ発火、GitHub UI で merge した時は `git pull` 後に `lathe sync` 手動
112
+ - v1 は新 project 専用、既存 repo の自動 migration なし
113
+ - runs/ auto-commit は local commit のみ(remote push しない)。multi-machine 構成では別途 push 設計が必要
114
+
115
+ ## 設計詳細
116
+
117
+ target orchestrator の指示書: `template/develop/harness/CLAUDE.md`
118
+ meta agent の指示書: `template/meta-overlay/meta/CLAUDE.md`
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+ # Shared helpers for lathe subcommands. Sourced, not executed.
3
+
4
+ # Find the Lathe project root (the dir containing the bare repo .git).
5
+ # Works from inside any worktree (main/develop/meta/task-*) and from the
6
+ # project root itself.
7
+ lathe_project_root() {
8
+ local common_dir
9
+ if ! common_dir="$(git rev-parse --git-common-dir 2>/dev/null)"; then
10
+ return 1
11
+ fi
12
+ # Common dir is typically <project_root>/.git. Could be relative.
13
+ if [ "$common_dir" = "." ] || [ "$common_dir" = ".git" ]; then
14
+ common_dir="$(pwd)/.git"
15
+ elif [ "${common_dir#/}" = "$common_dir" ]; then
16
+ # relative path
17
+ common_dir="$(pwd)/$common_dir"
18
+ fi
19
+ (cd "$(dirname "$common_dir")" && pwd)
20
+ }
21
+
22
+ # Find a worktree path by branch name.
23
+ # Usage: lathe_wt_for_branch <branch>
24
+ # Echoes the worktree path on stdout, or empty string if not found.
25
+ lathe_wt_for_branch() {
26
+ local target_branch="$1"
27
+ local root path branch line
28
+ root="$(lathe_project_root)" || return 1
29
+ while IFS= read -r line; do
30
+ path="$(echo "$line" | awk '{print $1}')"
31
+ branch="$(echo "$line" | awk '{print $3}' | tr -d '[]')"
32
+ if [ "$branch" = "$target_branch" ]; then
33
+ echo "$path"
34
+ return 0
35
+ fi
36
+ done < <(git --git-dir="$root/.git" worktree list)
37
+ return 1
38
+ }
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bash
2
+ # Lathe runtime dependency check. Runs as npm postinstall.
3
+ # Non-fatal: prints warnings but always exits 0 so install completes.
4
+
5
+ missing_required=()
6
+ missing_optional=()
7
+
8
+ for cmd in git jq claude bash; do
9
+ command -v "$cmd" >/dev/null 2>&1 || missing_required+=("$cmd")
10
+ done
11
+
12
+ command -v gh >/dev/null 2>&1 || missing_optional+=("gh (only needed for 'lathe process')")
13
+
14
+ if [ "${#missing_required[@]}" -gt 0 ]; then
15
+ echo ""
16
+ echo "[lathe] required dependencies missing:"
17
+ for c in "${missing_required[@]}"; do echo " - $c"; done
18
+ echo "[lathe] install them before running 'lathe init'."
19
+ fi
20
+
21
+ if [ "${#missing_optional[@]}" -gt 0 ]; then
22
+ echo ""
23
+ echo "[lathe] optional dependencies missing:"
24
+ for c in "${missing_optional[@]}"; do echo " - $c"; done
25
+ fi
26
+
27
+ # Git worktree feature requires 2.10+; warn if older.
28
+ if command -v git >/dev/null 2>&1; then
29
+ GIT_VER="$(git --version | awk '{print $3}')"
30
+ GIT_MAJOR="${GIT_VER%%.*}"
31
+ GIT_REST="${GIT_VER#*.}"
32
+ GIT_MINOR="${GIT_REST%%.*}"
33
+ if [ "$GIT_MAJOR" -lt 2 ] 2>/dev/null \
34
+ || { [ "$GIT_MAJOR" = "2" ] && [ "$GIT_MINOR" -lt 10 ] 2>/dev/null; }; then
35
+ echo ""
36
+ echo "[lathe] git $GIT_VER detected. Lathe needs git 2.10+ for worktree hooks. Please upgrade."
37
+ fi
38
+ fi
39
+
40
+ echo ""
41
+ echo "[lathe] installed. Run 'lathe init' in an empty directory to start."
42
+ exit 0
package/bin/lathe ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+ # lathe — agent harness CLI dispatcher.
3
+ # Resolves LATHE_HOME from script location, then dispatches to lathe-<cmd>.
4
+
5
+ set -euo pipefail
6
+
7
+ # Resolve LATHE_HOME = the Lathe install root (parent of bin/).
8
+ SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
9
+ # Follow symlink if `lathe` was symlinked into PATH.
10
+ if [ -L "$SCRIPT_PATH" ]; then
11
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
12
+ case "$SCRIPT_PATH" in
13
+ /*) ;; # absolute, fine
14
+ *) SCRIPT_PATH="$(cd "$(dirname "$0")" && cd "$(dirname "$SCRIPT_PATH")" && pwd)/$(basename "$SCRIPT_PATH")" ;;
15
+ esac
16
+ fi
17
+ LATHE_HOME="$(cd "$(dirname "$SCRIPT_PATH")/.." && pwd)"
18
+ export LATHE_HOME
19
+
20
+ CMD="${1:-help}"
21
+ shift || true
22
+
23
+ case "$CMD" in
24
+ help|-h|--help|"")
25
+ cat <<EOF
26
+ lathe — agent harness CLI
27
+
28
+ Commands:
29
+ init Initialize Lathe in current git repo
30
+ (creates develop + meta branches, two worktrees)
31
+ process <pr#> Pick up a PR for target processing
32
+ (creates task worktree, launches target with PR context)
33
+ sync Re-sync harness/ -> target/.claude/ in develop worktree
34
+ target Launch target agent (cd develop worktree, claude)
35
+ meta Launch meta agent (cd meta worktree, claude)
36
+ status Show worktrees, recent runs, recent improvements
37
+ help This message
38
+
39
+ LATHE_HOME=$LATHE_HOME
40
+ EOF
41
+ exit 0
42
+ ;;
43
+ esac
44
+
45
+ SUB="$LATHE_HOME/bin/lathe-$CMD"
46
+ if [ ! -x "$SUB" ]; then
47
+ echo "lathe: unknown or unimplemented command: $CMD" >&2
48
+ echo "Try: lathe help" >&2
49
+ exit 1
50
+ fi
51
+ exec "$SUB" "$@"
package/bin/lathe-init ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env bash
2
+ # lathe init — initialize a Lathe project in the current directory.
3
+ #
4
+ # Layout produced (nested under cwd):
5
+ # ./
6
+ # ├── .git/ (bare repo, shared by all worktrees)
7
+ # ├── main/ (worktree on 'main' branch — your app code)
8
+ # ├── develop/ (worktree on 'develop' — target harness)
9
+ # └── meta/ (worktree on 'meta' — meta agent + improvements/)
10
+ #
11
+ # Requirements: cwd should be empty. Existing repos are not auto-migrated.
12
+
13
+ set -euo pipefail
14
+
15
+ : "${LATHE_HOME:?must be set by lathe dispatcher}"
16
+
17
+ PROJECT_ROOT="$(pwd)"
18
+ PROJECT_NAME="$(basename "$PROJECT_ROOT")"
19
+
20
+ # --- Validation ---
21
+ if [ -e "$PROJECT_ROOT/.git" ]; then
22
+ echo "lathe init: $PROJECT_ROOT/.git already exists. Aborting." >&2
23
+ exit 1
24
+ fi
25
+ for d in main develop meta; do
26
+ if [ -e "$PROJECT_ROOT/$d" ]; then
27
+ echo "lathe init: $PROJECT_ROOT/$d already exists. Aborting." >&2
28
+ exit 1
29
+ fi
30
+ done
31
+
32
+ # Warn (not error) if cwd has any other content.
33
+ EXTRA="$(ls -A "$PROJECT_ROOT" 2>/dev/null | grep -vE '^(\.|\.\.)$' || true)"
34
+ if [ -n "$EXTRA" ]; then
35
+ echo "Note: $PROJECT_ROOT is not empty. Existing files will remain at the project root and won't be in any worktree."
36
+ echo " (Lathe v1 doesn't auto-migrate existing repos. Move files into main/ manually if needed.)"
37
+ fi
38
+
39
+ GIT_DIR="$PROJECT_ROOT/.git"
40
+
41
+ echo "==> [1/5] Initializing bare repo at $GIT_DIR ..."
42
+ git init --bare --quiet "$GIT_DIR"
43
+
44
+ echo "==> [2/5] Creating main worktree with initial commit (template/main)..."
45
+ git --git-dir="$GIT_DIR" worktree add --quiet -b main "$PROJECT_ROOT/main" 2>/dev/null || {
46
+ # Empty bare repo: branch creation needs an existing commit. Make one via plumbing.
47
+ EMPTY_TREE="$(git --git-dir="$GIT_DIR" mktree </dev/null)"
48
+ INIT_COMMIT="$(printf 'lathe: empty initial\n' | git --git-dir="$GIT_DIR" commit-tree "$EMPTY_TREE")"
49
+ git --git-dir="$GIT_DIR" update-ref refs/heads/main "$INIT_COMMIT"
50
+ git --git-dir="$GIT_DIR" symbolic-ref HEAD refs/heads/main
51
+ git --git-dir="$GIT_DIR" worktree add --quiet "$PROJECT_ROOT/main" main
52
+ }
53
+ cp -R "$LATHE_HOME/template/main/." "$PROJECT_ROOT/main/"
54
+ # Replace placeholder in README
55
+ if [ -f "$PROJECT_ROOT/main/README.md" ]; then
56
+ sed -i.bak "s/{{project_name}}/$PROJECT_NAME/g" "$PROJECT_ROOT/main/README.md"
57
+ rm -f "$PROJECT_ROOT/main/README.md.bak"
58
+ fi
59
+ git -C "$PROJECT_ROOT/main" add -A
60
+ git -C "$PROJECT_ROOT/main" \
61
+ -c user.email="lathe@local" -c user.name="lathe" \
62
+ commit --quiet --allow-empty -m "lathe: init main"
63
+
64
+ echo "==> [3/5] Creating develop worktree from main (template/develop)..."
65
+ git --git-dir="$GIT_DIR" worktree add --quiet -b develop "$PROJECT_ROOT/develop" main
66
+ cp -R "$LATHE_HOME/template/develop/." "$PROJECT_ROOT/develop/"
67
+ "$PROJECT_ROOT/develop/bin/sync.sh"
68
+ mkdir -p "$PROJECT_ROOT/develop/runs" "$PROJECT_ROOT/develop/target/plans"
69
+ touch "$PROJECT_ROOT/develop/runs/.gitkeep" "$PROJECT_ROOT/develop/target/plans/.gitkeep"
70
+ git -C "$PROJECT_ROOT/develop" add -A
71
+ git -C "$PROJECT_ROOT/develop" \
72
+ -c user.email="lathe@local" -c user.name="lathe" \
73
+ commit --quiet -m "lathe: target harness on develop"
74
+
75
+ echo "==> [4/5] Creating meta worktree from develop (template/meta-overlay)..."
76
+ git --git-dir="$GIT_DIR" worktree add --quiet -b meta "$PROJECT_ROOT/meta" develop
77
+ cp -R "$LATHE_HOME/template/meta-overlay/." "$PROJECT_ROOT/meta/"
78
+ git -C "$PROJECT_ROOT/meta" add -A
79
+ git -C "$PROJECT_ROOT/meta" \
80
+ -c user.email="lathe@local" -c user.name="lathe" \
81
+ commit --quiet -m "lathe: meta agent on meta"
82
+
83
+ echo "==> [5/5] Installing post-merge hook (auto-sync on develop merges)..."
84
+ mkdir -p "$GIT_DIR/hooks"
85
+ cp "$LATHE_HOME/template/git-hooks/post-merge" "$GIT_DIR/hooks/post-merge"
86
+ chmod +x "$GIT_DIR/hooks/post-merge"
87
+
88
+ cat <<EOF
89
+
90
+ Lathe initialized at $PROJECT_ROOT/
91
+
92
+ main/ your app code (cd here to start working)
93
+ develop/ target harness (target launches from here)
94
+ meta/ meta agent (improvements/ live here)
95
+ .git/ shared bare repo
96
+
97
+ Next:
98
+ cd $PROJECT_ROOT/main
99
+ # vibe code; commit; PR a feature branch to develop
100
+ # then: lathe process <pr#>
101
+ EOF
package/bin/lathe-meta ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bash
2
+ # lathe meta — cd into meta worktree's meta/ and launch claude.
3
+
4
+ set -euo pipefail
5
+ : "${LATHE_HOME:?must be set by lathe dispatcher}"
6
+ source "$LATHE_HOME/bin/_lathe-lib.sh"
7
+
8
+ META_WT="$(lathe_wt_for_branch meta)" || {
9
+ echo "lathe meta: meta worktree not found. Run 'lathe init' first." >&2
10
+ exit 1
11
+ }
12
+
13
+ cd "$META_WT/meta"
14
+ exec claude "$@"
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env bash
2
+ # lathe process <pr#> — pick up a PR for target processing.
3
+ # 1. fetch PR head + body via gh
4
+ # 2. add a worktree of the PR's branch under <project>/tasks/<pr#>
5
+ # 3. write the task brief into that worktree as .lathe-task.md
6
+ # 4. cd into develop worktree's target/, launch claude with --add-dir <task-wt>
7
+ #
8
+ # Interactive launch: the user pastes a "read .lathe-task.md and process it"
9
+ # prompt into the resulting claude TUI. (Auto-injection of the initial prompt
10
+ # is unreliable in claude's interactive mode.)
11
+
12
+ set -euo pipefail
13
+ : "${LATHE_HOME:?must be set by lathe dispatcher}"
14
+ source "$LATHE_HOME/bin/_lathe-lib.sh"
15
+
16
+ PR="${1:-}"
17
+ if [ -z "$PR" ]; then
18
+ echo "Usage: lathe process <pr#>" >&2
19
+ exit 1
20
+ fi
21
+
22
+ command -v gh >/dev/null 2>&1 || {
23
+ echo "lathe process: gh (GitHub CLI) is required" >&2
24
+ exit 1
25
+ }
26
+
27
+ PROJECT_ROOT="$(lathe_project_root)" || {
28
+ echo "lathe process: not inside a Lathe project" >&2
29
+ exit 1
30
+ }
31
+ DEVELOP_WT="$(lathe_wt_for_branch develop)" || {
32
+ echo "lathe process: develop worktree not found" >&2
33
+ exit 1
34
+ }
35
+
36
+ echo "==> Fetching PR #$PR ..."
37
+ HEAD_REF="$(gh pr view "$PR" --json headRefName -q .headRefName)"
38
+ TITLE="$(gh pr view "$PR" --json title -q .title)"
39
+ BODY="$(gh pr view "$PR" --json body -q .body)"
40
+
41
+ git --git-dir="$PROJECT_ROOT/.git" fetch origin "$HEAD_REF" >/dev/null 2>&1 || true
42
+
43
+ mkdir -p "$PROJECT_ROOT/tasks"
44
+ TASK_WT="$PROJECT_ROOT/tasks/$PR"
45
+ if [ -e "$TASK_WT" ]; then
46
+ echo "lathe process: $TASK_WT already exists. Remove it or pick another PR." >&2
47
+ exit 1
48
+ fi
49
+
50
+ echo "==> Creating task worktree at $TASK_WT (branch: $HEAD_REF)..."
51
+ git --git-dir="$PROJECT_ROOT/.git" worktree add --quiet "$TASK_WT" "$HEAD_REF"
52
+
53
+ PROMPT_FILE="$TASK_WT/.lathe-task.md"
54
+ cat > "$PROMPT_FILE" <<EOF
55
+ # PR #$PR: $TITLE
56
+
57
+ You are processing pull request #$PR. The vibe-coded changes are in this worktree.
58
+
59
+ **Task description (PR body):**
60
+ $BODY
61
+
62
+ **Your job:**
63
+ 1. Read the existing changes in this worktree (the vibe-coded prototype)
64
+ 2. Plan a polished implementation (planning skill, plans/<run_id>.html)
65
+ 3. After approval, dispatch coder/reviewer to produce a clean implementation
66
+ 4. Coder commits and pushes to branch \`$HEAD_REF\` so the PR updates
67
+ 5. Do NOT delete the original vibe commits — your polish goes ON TOP
68
+
69
+ The task worktree is at: $TASK_WT
70
+ EOF
71
+
72
+ cat <<EOF
73
+
74
+ Task worktree ready.
75
+ Path: $TASK_WT
76
+ Branch: $HEAD_REF
77
+ Prompt file: $PROMPT_FILE
78
+
79
+ Launching target. Paste this into the claude TUI:
80
+
81
+ Read .lathe-task.md from the added directory ($TASK_WT) and process it.
82
+
83
+ Press Enter to launch claude (Ctrl-C to abort)...
84
+ EOF
85
+ read -r _
86
+
87
+ cd "$DEVELOP_WT/target"
88
+ exec claude --add-dir "$TASK_WT"
package/bin/lathe-sync ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+ # lathe sync — re-sync harness/ to target/.claude/ in the develop worktree.
3
+ # Useful after manual harness edits, or if post-merge hook didn't fire (e.g.,
4
+ # merge happened via GitHub UI).
5
+
6
+ set -euo pipefail
7
+ : "${LATHE_HOME:?must be set by lathe dispatcher}"
8
+ source "$LATHE_HOME/bin/_lathe-lib.sh"
9
+
10
+ DEVELOP_WT="$(lathe_wt_for_branch develop)" || {
11
+ echo "lathe sync: develop worktree not found. Run 'lathe init' first." >&2
12
+ exit 1
13
+ }
14
+
15
+ if [ ! -x "$DEVELOP_WT/bin/sync.sh" ]; then
16
+ echo "lathe sync: $DEVELOP_WT/bin/sync.sh missing or not executable" >&2
17
+ exit 1
18
+ fi
19
+
20
+ exec "$DEVELOP_WT/bin/sync.sh"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bash
2
+ # lathe target — cd into develop worktree's target/ and launch claude.
3
+
4
+ set -euo pipefail
5
+ : "${LATHE_HOME:?must be set by lathe dispatcher}"
6
+ source "$LATHE_HOME/bin/_lathe-lib.sh"
7
+
8
+ DEVELOP_WT="$(lathe_wt_for_branch develop)" || {
9
+ echo "lathe target: develop worktree not found. Run 'lathe init' first." >&2
10
+ exit 1
11
+ }
12
+
13
+ cd "$DEVELOP_WT/target"
14
+ exec claude "$@"
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "lathe-cli",
3
+ "version": "1.0.0",
4
+ "description": "Agent harness CLI: target/meta git worktrees driven by Claude Code",
5
+ "bin": {
6
+ "lathe": "./bin/lathe"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "template/",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "postinstall": "node -e \"try { require('child_process').execSync('./bin/check-deps.sh', { stdio: 'inherit' }) } catch(e) {}\""
16
+ },
17
+ "engines": {
18
+ "node": ">=16"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/yutaro0915/Lathe.git"
23
+ },
24
+ "keywords": [
25
+ "claude",
26
+ "agent",
27
+ "harness",
28
+ "git-worktree"
29
+ ],
30
+ "license": "MIT",
31
+ "os": [
32
+ "darwin",
33
+ "linux"
34
+ ]
35
+ }
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ # Sync harness/ (source of truth, editable by meta) into target/ (where
3
+ # Claude Code reads from, partly under .claude/ which Claude Code's
4
+ # sensitive-file guard blocks from in-tool edits).
5
+ #
6
+ # Run this whenever harness/ changes:
7
+ # - Manually after editing harness/ by hand
8
+ # - Automatically by meta-side hooks after meta improves harness/
9
+ # - On fresh clone before launching target the first time
10
+
11
+ set -euo pipefail
12
+
13
+ REPO="$(cd "$(dirname "$0")/.." && pwd)"
14
+ HARNESS="$REPO/harness"
15
+ TARGET="$REPO/target"
16
+
17
+ if [ ! -d "$HARNESS" ]; then
18
+ echo "sync-harness: $HARNESS does not exist" >&2
19
+ exit 1
20
+ fi
21
+
22
+ # Top-level files at target/ root.
23
+ mkdir -p "$TARGET"
24
+ cp -f "$HARNESS/CLAUDE.md" "$TARGET/CLAUDE.md"
25
+ cp -f "$HARNESS/plan_template.html" "$TARGET/plan_template.html"
26
+
27
+ # workflow/ (yaml templates).
28
+ mkdir -p "$TARGET/workflow"
29
+ rm -rf "$TARGET/workflow"/*
30
+ cp -R "$HARNESS/workflow/." "$TARGET/workflow/"
31
+
32
+ # hooks/ (shell scripts — executable bit must be preserved).
33
+ mkdir -p "$TARGET/hooks"
34
+ rm -rf "$TARGET/hooks"/*
35
+ cp -R "$HARNESS/hooks/." "$TARGET/hooks/"
36
+ chmod +x "$TARGET/hooks"/*.sh
37
+
38
+ # .claude/ — the path Claude Code reads at startup. Sensitive-file guard
39
+ # blocks tool-based edits here, but cp from outside the claude process
40
+ # is fine. We rebuild settings.json + skills/ + agents/.
41
+ mkdir -p "$TARGET/.claude/skills" "$TARGET/.claude/agents"
42
+ rm -rf "$TARGET/.claude/skills"/* "$TARGET/.claude/agents"/*
43
+ cp -f "$HARNESS/settings.json" "$TARGET/.claude/settings.json"
44
+ cp -R "$HARNESS/skills/." "$TARGET/.claude/skills/"
45
+ cp -R "$HARNESS/agents/." "$TARGET/.claude/agents/"
46
+
47
+ # plans/ is runtime, NOT from harness. Keep what's there.
48
+ mkdir -p "$TARGET/plans"
49
+
50
+ echo "sync-harness: target/ rebuilt from harness/"