mirror of
https://github.com/larksuite/cli.git
synced 2026-07-05 15:47:54 +08:00
Users who install or upgrade lark-cli via make install, go install, or
direct binary download end up with a binary but no AI agent skills,
degrading agent UX. This PR adds a startup-time skills version drift
notice (injected into JSON envelope _notice.skills, mirroring the
existing _notice.update pattern) and unifies lark-cli update's skills
sync across all three branches (npm / manual / already-latest) with
stamp-based dedup, so any explicit update invocation keeps skills in
sync regardless of how the binary was installed.
Changes:
- new internal/skillscheck package: notice (StaleNotice + atomic
pending), stamp (~/.lark-cli/skills.stamp), skip (CI / DEV /
non-release / LARKSUITE_CLI_NO_SKILLS_NOTIFIER opt-out), check
(synchronous Init)
- cmd/root.go: rename setupUpdateNotice -> setupNotices, compose
output.PendingNotice returning {update?, skills?}; capture
build.Version locally before spawning the async update goroutine
- cmd/update/update.go: add runSkillsAndStamp helper with stamp-based
dedup; rewire the three branches through shared applySkillsResult /
emitSkillsTextHints helpers; add skills_status block to --check JSON
output as a pure report (no side effects)
- internal/update: export IsRelease(version) bool / IsCIEnv() bool
for cross-package reuse; refresh UpdateInfo.Message to append
', run: lark-cli update' so both notices recommend the same fix
- AGENTS.md: add Notification Opt-Outs section documenting
LARKSUITE_CLI_NO_UPDATE_NOTIFIER and LARKSUITE_CLI_NO_SKILLS_NOTIFIER
- internal/binding/types.go: bump default exec-provider timeout from
5s to 10s (out-of-scope flake fix for TestResolveExecRef_JSONResponse
under heavy parallel test load)
120 lines
5.2 KiB
Markdown
120 lines
5.2 KiB
Markdown
# AGENTS.md
|
|
|
|
## Goal (pick one per PR)
|
|
|
|
- Make CLI better: improve UX, error messages, help text, flags, and output clarity.
|
|
- Improve reliability: fix bugs, edge cases, and regressions with tests.
|
|
- Improve developer velocity: simplify code paths, reduce complexity, keep behavior explicit.
|
|
- Improve quality gates: strengthen tests/lint/checks without adding heavy process.
|
|
|
|
## Build & Test
|
|
|
|
```bash
|
|
make build # Build (runs fetch_meta first)
|
|
make unit-test # Required before PR (runs with -race)
|
|
make test # Full: vet + unit + integration
|
|
```
|
|
|
|
## Notification Opt-Outs
|
|
|
|
`lark-cli` emits two notice types into JSON envelope `_notice` to nudge AI agents toward fixes:
|
|
|
|
- `_notice.update` — a newer binary is available on npm
|
|
- `_notice.skills` — locally installed skills are out of sync with the running binary
|
|
|
|
To suppress them in non-CI scripts (CI envs are auto-skipped):
|
|
|
|
| Env var | Effect |
|
|
|---------|--------|
|
|
| `LARKSUITE_CLI_NO_UPDATE_NOTIFIER=1` | Suppress `_notice.update` |
|
|
| `LARKSUITE_CLI_NO_SKILLS_NOTIFIER=1` | Suppress `_notice.skills` |
|
|
|
|
Both notices recommend the same fix command: `lark-cli update`. The skills notice's `current` field is `""` when skills have never been synced (cold start) and a version string when synced for an older binary (drift).
|
|
|
|
## Pre-PR Checks (match CI gates)
|
|
|
|
1. `make unit-test`
|
|
2. `go vet ./...`
|
|
3. `gofmt -l .` — must produce no output
|
|
4. `go mod tidy` — must not change `go.mod`/`go.sum`
|
|
5. `go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 run --new-from-rev=origin/main`
|
|
6. If dependencies changed: `go run github.com/google/go-licenses/v2@v2.0.1 check ./... --disallowed_types=forbidden,restricted,reciprocal,unknown`
|
|
|
|
## Commit & PR
|
|
|
|
- Conventional Commits in English: `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `chore:`, `ci:`
|
|
- PR title in the same format. Fill `.github/pull_request_template.md` completely.
|
|
- Never commit secrets, tokens, or internal sensitive data.
|
|
|
|
## Source Layout
|
|
|
|
| Path | What it does |
|
|
|------|-------------|
|
|
| `cmd/root.go` | Entry point, command registration, strict mode pruning |
|
|
| `cmd/profile/` | Multi-profile management (add/list/use/rename/remove) |
|
|
| `cmd/config/` | Config init, show, strict-mode |
|
|
| `cmd/service/` | Auto-registered API commands from embedded metadata |
|
|
| `shortcuts/common/runner.go` | Shortcut execution pipeline, Flag.Input (@file/stdin) resolution |
|
|
| `shortcuts/` | Domain-specific shortcut implementations |
|
|
| `internal/cmdutil/factory.go` | Factory pattern — identity resolution, credential, config |
|
|
| `internal/cmdutil/factory_default.go` | Production factory wiring |
|
|
| `internal/credential/` | Credential provider chain (extension → default) |
|
|
| `extension/credential/` | Plugin-facing credential interfaces and env provider |
|
|
| `internal/client/client.go` | APIClient: DoSDKRequest, DoStream |
|
|
| `internal/core/config.go` | Multi-profile config loading/saving |
|
|
| `internal/vfs/` | Filesystem abstraction (use `vfs.*` instead of `os.*`) |
|
|
| `internal/validate/path.go` | Path safety validation |
|
|
|
|
## Who Uses This CLI
|
|
|
|
This CLI's primary consumers include AI agents (Claude Code, Cursor, Gemini CLI). Your code is read by machines — error messages, output format, and flag design all directly affect agent success rates.
|
|
|
|
The one rule to internalize: **every error message you write will be parsed by an AI to decide its next action.** Make errors structured, actionable, and specific.
|
|
|
|
## Code Conventions
|
|
|
|
### Structured errors in commands
|
|
|
|
`RunE` functions must return `output.Errorf` / `output.ErrWithHint` — never bare `fmt.Errorf`. AI agents parse stderr as JSON; bare errors break this contract.
|
|
|
|
### stdout is data, stderr is everything else
|
|
|
|
Program output (JSON envelopes) goes to stdout. Progress, warnings, hints go to stderr. Mixing them corrupts pipe chains.
|
|
|
|
### Use `vfs.*` instead of `os.*`
|
|
|
|
All filesystem access goes through `internal/vfs`. This enables test mocking.
|
|
|
|
### Validate paths before reading
|
|
|
|
CLI arguments are untrusted (they come from AI agents). Call `validate.SafeInputPath` before any file I/O.
|
|
|
|
### Tests
|
|
|
|
- Every behavior change needs a test alongside the change.
|
|
- `cmdutil.TestFactory(t, config)` for test factories.
|
|
- `t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())` to isolate config state.
|
|
|
|
### E2E Testing
|
|
|
|
**Dry-run E2E (required for every shortcut change)**
|
|
- Validates request structure without calling real APIs
|
|
- Place in `tests/cli_e2e/dryrun/` or the corresponding domain directory
|
|
- Set env vars `LARKSUITE_CLI_APP_ID`/`APP_SECRET`/`BRAND`, use `--dry-run`, assert method/URL/params
|
|
- No secrets needed — runs on fork PRs
|
|
- Explore correct params with `lark-cli <domain> --help` and `lark-cli schema` first
|
|
|
|
**Live E2E (required for new flows or behavior changes)**
|
|
- Validates real API round-trips
|
|
- Place in `tests/cli_e2e/<domain>/`
|
|
- Must be self-contained: create -> use -> cleanup
|
|
- Needs bot credentials (CI secrets, skipped on fork PRs)
|
|
- Reference: `tests/cli_e2e/task/task_status_workflow_test.go`
|
|
|
|
| Change | Dry-run E2E | Live E2E |
|
|
|--------|:-----------:|:--------:|
|
|
| New shortcut | Required | Required |
|
|
| Modify shortcut flags/params | Required | If behavior changes |
|
|
| Shortcut bug fix | Required | If regression risk |
|
|
| Internal refactor (no shortcut impact) | Not needed | Not needed |
|