larkway 0.3.6
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/LICENSE +21 -0
- package/README.md +169 -0
- package/README.zh.md +169 -0
- package/bin/larkway +25 -0
- package/dist/cli/index.js +127643 -0
- package/dist/main.js +119397 -0
- package/dist/web/public/app.js +6071 -0
- package/dist/web/public/favicon.svg +6 -0
- package/dist/web/public/index.html +146 -0
- package/dist/web/public/style.css +4258 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chuck Wu (chuckwu0)
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Larkway
|
|
2
|
+
|
|
3
|
+
> Turn your Claude Code or Codex subscription into a Feishu (Lark) agent your whole team can @-mention.
|
|
4
|
+
|
|
5
|
+
[中文版](README.zh.md)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You @ the bot in a Feishu thread. It runs on your machine — reading your real codebase, executing commands, opening MRs — and posts the result back. You define what the agent knows and what it can do. Larkway just carries the messages.
|
|
10
|
+
|
|
11
|
+
**Current release: v0.3.6**
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Why
|
|
16
|
+
|
|
17
|
+
The engineers on your team know how a feature is actually implemented. Everyone else has to ask them. That friction compounds: a data analyst wondering whether a metric counts deleted records, a PM asking which API endpoint powers a chart, a QA engineer trying to reproduce a bug without context.
|
|
18
|
+
|
|
19
|
+
A generic AI assistant cannot answer these questions reliably — it has no access to your code. A bot that runs Claude Code or Codex against your real repository can.
|
|
20
|
+
|
|
21
|
+
Larkway makes that bot trivially installable and persistent: one `larkway start` on an always-on machine, one `@mention` in any Feishu thread, and your team has a self-serve answer to "how is this actually implemented."
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## How it works
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Feishu thread
|
|
29
|
+
│ @bot "how does the retention metric handle deleted users?"
|
|
30
|
+
│
|
|
31
|
+
▼ WebSocket long-connection (outbound only, no public endpoint needed)
|
|
32
|
+
larkway bridge
|
|
33
|
+
│ spawns subprocess ──► claude --resume <session_id> -p "<prompt>"
|
|
34
|
+
│ (or: codex ...)
|
|
35
|
+
│
|
|
36
|
+
▼ stream-json (NDJSON)
|
|
37
|
+
lark.card ◄── agent reads repo, runs bash, edits files,
|
|
38
|
+
│ throttled PATCH opens MR, starts dev preview
|
|
39
|
+
│
|
|
40
|
+
▼
|
|
41
|
+
Feishu thread
|
|
42
|
+
"retention.ts line 47: deleted_at IS NULL filter is applied before
|
|
43
|
+
the aggregation window. Deleted users are excluded."
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**What Larkway does** (and only this):
|
|
47
|
+
|
|
48
|
+
- Feishu long-connection subscriber (inbound events)
|
|
49
|
+
- Subprocess lifecycle: spawn, stream-json parse, session-ID persistence
|
|
50
|
+
- Feishu card: throttled real-time PATCH as the agent streams output
|
|
51
|
+
- Session KV: `thread_id → session_id` so follow-up messages resume context
|
|
52
|
+
- Idle GC: worktree housekeeping
|
|
53
|
+
|
|
54
|
+
**What Larkway does NOT do** — the agent decides everything else:
|
|
55
|
+
|
|
56
|
+
- No GitLab/GitHub API calls (the agent runs `glab`/`gh` itself)
|
|
57
|
+
- No worktree creation (the agent runs `git worktree add`)
|
|
58
|
+
- No dev server management (the agent starts it)
|
|
59
|
+
- No orchestration logic — the agent reads your `AGENTS.md` / `CLAUDE.md` / skills and plans its own steps
|
|
60
|
+
|
|
61
|
+
This boundary is intentional. Workflow changes go into your repository's agent guides, not into Larkway.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Quick start
|
|
66
|
+
|
|
67
|
+
> **Note:** npm publish is pending. Until then, install straight from the GitHub repo (the `prepack` build runs on install):
|
|
68
|
+
>
|
|
69
|
+
> ```bash
|
|
70
|
+
> npm i -g github:chuckwu0/larkway
|
|
71
|
+
> ```
|
|
72
|
+
>
|
|
73
|
+
> Once published: `npm i -g larkway`
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# 1. Check your environment
|
|
77
|
+
larkway doctor # lists missing dependencies; --fix auto-installs some
|
|
78
|
+
|
|
79
|
+
# 2. Register a Feishu app and configure your first bot
|
|
80
|
+
larkway init # CLI wizard: scan QR code → name the bot → pick a backend
|
|
81
|
+
|
|
82
|
+
# 3. Start the bridge
|
|
83
|
+
larkway start # long-running; runs in background, logs to ~/.larkway/logs/
|
|
84
|
+
|
|
85
|
+
# 4. Add the bot to a Feishu group
|
|
86
|
+
# Group settings → Bots → Add bot → pick yours → @-mention it
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Backends
|
|
92
|
+
|
|
93
|
+
| Backend | CLI | Auth | Billing |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| **Claude Code** | `claude` | Local subscription login (`~/.claude/.credentials.json`) | Your existing Claude subscription — no per-token charges |
|
|
96
|
+
| **Codex** | `codex` | `codex login` | Your existing Codex subscription — no per-token charges |
|
|
97
|
+
|
|
98
|
+
Larkway never injects `ANTHROPIC_API_KEY` or any other API key. The subprocess inherits your local login state. If you switch to API-key mode, that is a deliberate opt-in in `src/claude/runner.ts`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Defining a bot (three layers)
|
|
103
|
+
|
|
104
|
+
| Layer | What it is | Where it lives |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| **L1 permissions** | App credentials, repo path, allowed Feishu users/groups, token scopes | `~/.larkway/bots/<id>.yaml` |
|
|
107
|
+
| **L2 identity memory** | "Who I am, what I must not do, where to find the workflow" (thin) | `~/.larkway/bots/<id>.memory.md` |
|
|
108
|
+
| **L3 workflow** | State machine, gates, commands — the actual job | **Your business repo**: `AGENTS.md`, `CLAUDE.md`, `.agents/skills/`, `.claude/skills/` |
|
|
109
|
+
|
|
110
|
+
Secrets live only in `~/.larkway/.env` (mode 0600). Config and memory contain no secrets and are safe to share via the central config library.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Features
|
|
115
|
+
|
|
116
|
+
- **Multiple bots on one bridge** — a read-only Q&A bot and a write-capable engineering bot can share the same process, each with its own L1/L2/L3 definition
|
|
117
|
+
- **Web UI** — `larkway ui` opens a local management dashboard (127.0.0.1 + token); create bots, edit memory, watch live logs
|
|
118
|
+
- **Central config library** — `larkway promote <id>` pushes bot config (no secrets) to a shared git repository so teammates can `larkway sync` and discover bots; the library stores config, not deployment state
|
|
119
|
+
- **Session continuity** — every Feishu thread maps to a persistent `session_id`; the agent remembers what it did in prior turns
|
|
120
|
+
- **Agent Workspace** — per-thread git worktrees; the agent can run multiple threads concurrently without git conflicts
|
|
121
|
+
- **Codex runtime pre-checks** — `larkway doctor` validates Codex state directory writability before start
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Requirements
|
|
126
|
+
|
|
127
|
+
- **Node.js 20+ LTS**
|
|
128
|
+
- **A Claude Code or Codex subscription** with local CLI installed and logged in
|
|
129
|
+
- **`lark-cli`** — Feishu long-connection client and message utilities
|
|
130
|
+
- **`glab` + `git`** — for bots that open MRs (optional for read-only bots)
|
|
131
|
+
- **An always-on host machine** — the bridge must stay running to receive Feishu events; a laptop that sleeps will miss messages; a small server or desktop works well
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Commands
|
|
136
|
+
|
|
137
|
+
| Command | What it does |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `larkway` | Open web UI (recommended for first-time setup) |
|
|
140
|
+
| `larkway init` | CLI wizard: register Feishu app + configure first bot |
|
|
141
|
+
| `larkway doctor [--fix]` | Environment check; auto-fix where possible |
|
|
142
|
+
| `larkway start \| stop \| status \| logs` | Bridge lifecycle (`logs --follow` for streaming) |
|
|
143
|
+
| `larkway bot add \| list \| edit` | Manage bots |
|
|
144
|
+
| `larkway memory edit <id>` | Edit L2 identity memory |
|
|
145
|
+
| `larkway perms <id>` | Adjust L1 permissions |
|
|
146
|
+
| `larkway ui` | Start local web management UI |
|
|
147
|
+
| `larkway central set \| show \| unset` | Connect/disconnect central config library |
|
|
148
|
+
| `larkway promote <id>` | Push bot config (no secrets) to central library |
|
|
149
|
+
| `larkway sync` | Pull bot configs from central library |
|
|
150
|
+
| `larkway update` | Upgrade Larkway and restart bridge |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Documentation
|
|
155
|
+
|
|
156
|
+
| Topic | File |
|
|
157
|
+
|---|---|
|
|
158
|
+
| Architecture diagram + module I/O | [docs/architecture.md](docs/architecture.md) |
|
|
159
|
+
| Agent capability model (L0–L3) | [docs/agent-capability-model.md](docs/agent-capability-model.md) |
|
|
160
|
+
| Agent workspace runtime (v0.3) | [docs/agent-workspace.md](docs/agent-workspace.md) |
|
|
161
|
+
| Version history and semver mapping | [docs/versioning.md](docs/versioning.md) |
|
|
162
|
+
| Bridge ↔ Agent prompt contract | [docs/prompt-contract.md](docs/prompt-contract.md) |
|
|
163
|
+
| Bot config + memory templates | [bots-examples/](bots-examples/) |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Larkway
|
|
2
|
+
|
|
3
|
+
> 把你的 Claude Code 或 Codex 订阅变成全团队都能 @ 的飞书 Agent。
|
|
4
|
+
|
|
5
|
+
[English](README.md)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
你在飞书话题里 @ bot,它在你的机器上运行——读真实代码库、执行命令、开 MR——把结果贴回飞书。你定义 agent 知道什么、能做什么。Larkway 只负责传递消息。
|
|
10
|
+
|
|
11
|
+
**当前版本:v0.3.6**
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 背景
|
|
16
|
+
|
|
17
|
+
工程师知道某个功能是怎么实现的,其他人不知道,只能问。这个摩擦不断叠加:数据分析师想弄清楚某个指标有没有过滤已删除的记录,PM 想知道某个图表背后调的是哪个 API,QA 工程师在没有上下文的情况下试图复现一个 bug。
|
|
18
|
+
|
|
19
|
+
通用 AI 助手无法可靠地回答这些问题——它访问不到你的代码。而一个在你真实仓库里运行 Claude Code 或 Codex 的 bot 可以。
|
|
20
|
+
|
|
21
|
+
Larkway 让这个 bot 的安装和持久运行变得简单:在一台常开的机器上 `larkway start`,在任何飞书话题里 @-mention,团队就有了一个自助回答"这个到底是怎么实现的"的入口。
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 工作原理
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
飞书话题
|
|
29
|
+
│ @bot "留存指标是怎么处理已删除用户的?"
|
|
30
|
+
│
|
|
31
|
+
▼ WebSocket 长连接(纯出网,不需要公网端口)
|
|
32
|
+
larkway bridge
|
|
33
|
+
│ spawn 子进程 ──► claude --resume <session_id> -p "<prompt>"
|
|
34
|
+
│ (或:codex ...)
|
|
35
|
+
│
|
|
36
|
+
▼ stream-json (NDJSON)
|
|
37
|
+
lark.card ◄── agent 读仓库、跑 bash、改代码、
|
|
38
|
+
│ 节流 PATCH 开 MR、起 dev 预览
|
|
39
|
+
│
|
|
40
|
+
▼
|
|
41
|
+
飞书话题
|
|
42
|
+
"retention.ts 第 47 行:deleted_at IS NULL 过滤在聚合窗口之前
|
|
43
|
+
生效,已删除用户被排除在外。"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Larkway 做的事**(仅此而已):
|
|
47
|
+
|
|
48
|
+
- 飞书长连接订阅(接收入站事件)
|
|
49
|
+
- 子进程生命周期:spawn、stream-json 解析、session ID 持久化
|
|
50
|
+
- 飞书卡片:agent 流式输出时节流 PATCH 实时更新
|
|
51
|
+
- Session KV:`thread_id → session_id`,后续消息自动续接上下文
|
|
52
|
+
- 空闲 GC:worktree 清理
|
|
53
|
+
|
|
54
|
+
**Larkway 不做的事**——agent 自己决定:
|
|
55
|
+
|
|
56
|
+
- 不调 GitLab/GitHub API(agent 自己跑 `glab`/`gh`)
|
|
57
|
+
- 不建 worktree(agent 自己跑 `git worktree add`)
|
|
58
|
+
- 不管 dev server(agent 自己启动)
|
|
59
|
+
- 不做流程编排——agent 读你的 `AGENTS.md` / `CLAUDE.md` / skills,自主规划步骤
|
|
60
|
+
|
|
61
|
+
这个边界是刻意设计的。流程变化进你仓库的 agent guide,不进 Larkway。
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 快速上手
|
|
66
|
+
|
|
67
|
+
> **注意:** npm 包尚未发布。现阶段直接从 GitHub 仓库安装(`prepack` 会在安装时自动构建):
|
|
68
|
+
>
|
|
69
|
+
> ```bash
|
|
70
|
+
> npm i -g github:chuckwu0/larkway
|
|
71
|
+
> ```
|
|
72
|
+
>
|
|
73
|
+
> 发布后可直接:`npm i -g larkway`
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# 1. 检查环境
|
|
77
|
+
larkway doctor # 列出缺失的依赖;--fix 自动修复部分问题
|
|
78
|
+
|
|
79
|
+
# 2. 注册飞书 app + 配置第一个 bot
|
|
80
|
+
larkway init # CLI 向导:扫码 → 命名 bot → 选 backend
|
|
81
|
+
|
|
82
|
+
# 3. 启动 bridge
|
|
83
|
+
larkway start # 长驻进程,后台运行,日志写入 ~/.larkway/logs/
|
|
84
|
+
|
|
85
|
+
# 4. 把 bot 加到飞书群
|
|
86
|
+
# 群设置 → 群机器人 → 添加机器人 → 选你的 bot → @ 它提需求
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Backend 选择
|
|
92
|
+
|
|
93
|
+
| Backend | CLI | 鉴权方式 | 计费方式 |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| **Claude Code** | `claude` | 本地订阅登录态(`~/.claude/.credentials.json`) | 现有 Claude 订阅,不按 token 扣费 |
|
|
96
|
+
| **Codex** | `codex` | `codex login` | 现有 Codex 订阅,不按 token 扣费 |
|
|
97
|
+
|
|
98
|
+
Larkway 不注入 `ANTHROPIC_API_KEY` 或任何其他 API key。子进程继承你的本地登录态。如需切换到 API key 模式,需在 `src/claude/runner.ts` 显式开启。
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 定义一个 bot(三层)
|
|
103
|
+
|
|
104
|
+
| 层 | 是什么 | 放在哪 |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| **L1 权限** | App 凭据、repo 路径、允许的飞书用户/群、token scope | `~/.larkway/bots/<id>.yaml` |
|
|
107
|
+
| **L2 身份 memory** | "我是谁、禁止什么、工作流指针"(薄) | `~/.larkway/bots/<id>.memory.md` |
|
|
108
|
+
| **L3 工作流** | 状态机、gate、命令——实际的工作内容 | **业务 repo**:`AGENTS.md`、`CLAUDE.md`、`.agents/skills/`、`.claude/skills/` |
|
|
109
|
+
|
|
110
|
+
密钥只存在本机 `~/.larkway/.env`(权限 0600)。配置和 memory 不含密钥,可以安全地通过中心配置库共享。
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 功能
|
|
115
|
+
|
|
116
|
+
- **一个 bridge 跑多个 bot** —— 只读答疑 bot 和有写权限的工程 bot 可以共用同一个进程,各自有独立的 L1/L2/L3 定义
|
|
117
|
+
- **Web 管理面** —— `larkway ui` 打开本地管理后台(127.0.0.1 + token),可以建 bot、编辑 memory、查看实时日志
|
|
118
|
+
- **中心配置库** —— `larkway promote <id>` 把 bot 配置(不含密钥)推送到共享 git 仓库,队友可以 `larkway sync` 发现和复用;库只存配置,不存部署状态
|
|
119
|
+
- **Session 续接** —— 每个飞书话题映射到持久 `session_id`,agent 记得之前做了什么
|
|
120
|
+
- **Agent Workspace** —— 每个话题独立 git worktree,agent 并发处理多个话题不冲突
|
|
121
|
+
- **Codex 运行时预检** —— `larkway doctor` 在启动前验证 Codex 状态目录可写
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 前置要求
|
|
126
|
+
|
|
127
|
+
- **Node.js 20+ LTS**
|
|
128
|
+
- **Claude Code 或 Codex 订阅**,本地 CLI 已安装并登录
|
|
129
|
+
- **`lark-cli`** —— 飞书长连接客户端和消息工具
|
|
130
|
+
- **`glab` + `git`** —— 需要开 MR 的 bot 必须;只读 bot 可省
|
|
131
|
+
- **一台常开的机器** —— bridge 必须持续运行才能接收飞书事件;经常休眠的笔记本会漏消息,小服务器或台式机更合适
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 命令速查
|
|
136
|
+
|
|
137
|
+
| 命令 | 作用 |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `larkway` | 打开 Web 管理面(首次配置推荐) |
|
|
140
|
+
| `larkway init` | CLI 向导:注册飞书 app + 配置第一个 bot |
|
|
141
|
+
| `larkway doctor [--fix]` | 环境检查,自动修复部分问题 |
|
|
142
|
+
| `larkway start \| stop \| status \| logs` | Bridge 生命周期(`logs --follow` 实时流) |
|
|
143
|
+
| `larkway bot add \| list \| edit` | 管理 bot |
|
|
144
|
+
| `larkway memory edit <id>` | 编辑 L2 身份 memory |
|
|
145
|
+
| `larkway perms <id>` | 调整 L1 权限 |
|
|
146
|
+
| `larkway ui` | 启动本地 Web 管理面 |
|
|
147
|
+
| `larkway central set \| show \| unset` | 连接/断开中心配置库 |
|
|
148
|
+
| `larkway promote <id>` | 把 bot 配置(不含密钥)推送到中心库 |
|
|
149
|
+
| `larkway sync` | 从中心库拉 bot 配置 |
|
|
150
|
+
| `larkway update` | 升级 Larkway 并重启 bridge |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 文档
|
|
155
|
+
|
|
156
|
+
| 主题 | 文件 |
|
|
157
|
+
|---|---|
|
|
158
|
+
| 架构图 + 模块 I/O | [docs/architecture.md](docs/architecture.md) |
|
|
159
|
+
| Agent 能力模型(L0–L3) | [docs/agent-capability-model.md](docs/agent-capability-model.md) |
|
|
160
|
+
| Agent workspace 运行时(v0.3) | [docs/agent-workspace.md](docs/agent-workspace.md) |
|
|
161
|
+
| 版本历史与 semver 映射 | [docs/versioning.md](docs/versioning.md) |
|
|
162
|
+
| Bridge ↔ Agent Prompt 契约 | [docs/prompt-contract.md](docs/prompt-contract.md) |
|
|
163
|
+
| Bot 配置 + memory 模板 | [bots-examples/](bots-examples/) |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT
|
package/bin/larkway
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# larkway CLI shim — resolves the package root from this script's own location
|
|
3
|
+
# so it works whether invoked via `bin/larkway`, an absolute path, or a symlink
|
|
4
|
+
# on PATH (e.g. after `npm i -g`).
|
|
5
|
+
#
|
|
6
|
+
# Startup priority:
|
|
7
|
+
# 1. dist/cli/index.js exists → `node dist/cli/index.js` (installed package / post-build)
|
|
8
|
+
# 2. otherwise → `npx tsx src/cli/index.ts` (fresh clone dev mode, no build)
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
11
|
+
while [ -h "$SOURCE" ]; do
|
|
12
|
+
DIR="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)"
|
|
13
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
14
|
+
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
|
|
15
|
+
done
|
|
16
|
+
REPO_ROOT="$(cd -P "$(dirname "$SOURCE")/.." >/dev/null 2>&1 && pwd)"
|
|
17
|
+
|
|
18
|
+
DIST_ENTRY="$REPO_ROOT/dist/cli/index.js"
|
|
19
|
+
|
|
20
|
+
if [ -f "$DIST_ENTRY" ]; then
|
|
21
|
+
exec node "$DIST_ENTRY" "$@"
|
|
22
|
+
else
|
|
23
|
+
# Dev fallback: run TypeScript source directly via tsx.
|
|
24
|
+
exec npx tsx "$REPO_ROOT/src/cli/index.ts" "$@"
|
|
25
|
+
fi
|