9d2e740753
Audited the v0.0~v0.2 21-command surface against gh / kubectl / cargo /
npm / git / docker / flyctl / vercel / supabase / brew. WeKnora was
cherry-picking from multiple heritages, producing an inconsistent feel:
the kb subtree mixed gh verbs (create / delete / list) with a kubectl
verb (get); confirmation flag duplicated --force (docker/kubectl) with
global -y/--yes (gh/vercel/npm); the --agent flag stretched Stripe's
telemetry-tag pattern into a behavior-mode switch that no mainstream
CLI does.
ADR-3 picks gh as the primary north star. Documented deviations remain
for project-link (vercel/cargo), chat (openai-cli), context (kubectl-
light), and doctor (brew/flutter). The decision and its deviations are
documented self-contained in cli/AGENTS.md.
Surface changes:
- kb get → kb view (gh repo view convention); "get" kept as cobra Alias
for v0.0/v0.1 callers — see https://cli.github.com/manual/gh_repo_view.
- kb delete --force / doc delete --force removed in favor of the global
-y/--yes persistent flag (gh repo delete --yes convention). One
mechanism skips destructive prompts; ConfirmDestructive's parameter
renamed `force` → `yes` to match.
- --agent omnibus mode-switch removed. Stripe's DetectAIAgent (the
cited inspiration) only tags User-Agent for telemetry, never flips
behavior; gh / kubectl / aws / docker / flyctl all decline this kind
of flag. The 7-env auto-detect list is reduced to the two entries
Stripe also recognizes (CLAUDECODE, CURSOR_AGENT) — the other five
had no agent-documented source. ApplyAgentSugar / ShouldUseAgentMode
and the dead --no-interactive / --no-progress globals are deleted
entirely.
- DetectAIAgent and SetAgentHelp annotations are kept: env detection
now only triggers AGENT-targeted help text rendering (no behavior
change), matching Stripe's narrower scope.
Tests: 27 cli packages green (acceptance/contract still pins kb get
golden; the alias keeps it valid).
63 lines
1.8 KiB
Go
63 lines
1.8 KiB
Go
package agent
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// clearAgentEnv unsets every env var DetectAIAgent inspects, so a developer
|
|
// running these tests from inside Claude Code / Cursor doesn't see false
|
|
// positives.
|
|
func clearAgentEnv(t *testing.T) {
|
|
t.Helper()
|
|
for _, a := range aiAgentEnvs {
|
|
t.Setenv(a.env, "")
|
|
}
|
|
t.Setenv("WEKNORA_NO_AGENT_AUTODETECT", "")
|
|
t.Setenv("WEKNORA_AGENT", "")
|
|
}
|
|
|
|
func TestDetectAIAgent(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
set map[string]string
|
|
want AIAgentName
|
|
}{
|
|
{name: "empty env", set: nil, want: ""},
|
|
{name: "unrelated env", set: map[string]string{"PATH": "/usr/bin"}, want: ""},
|
|
{name: "claude code", set: map[string]string{"CLAUDECODE": "1"}, want: "claude-code"},
|
|
{name: "cursor", set: map[string]string{"CURSOR_AGENT": "yes"}, want: "cursor"},
|
|
// Other entries (codex / aider / continue / opencode / gemini-coder)
|
|
// were dropped in v0.2 ADR-3 — env names had no official agent docs.
|
|
// New entries should arrive with a documented source URL.
|
|
{
|
|
name: "first-match precedence",
|
|
set: map[string]string{"CLAUDECODE": "1", "CURSOR_AGENT": "1"},
|
|
want: "claude-code",
|
|
},
|
|
{name: "empty value treated as unset", set: map[string]string{"CLAUDECODE": ""}, want: ""},
|
|
{
|
|
name: "WEKNORA_NO_AGENT_AUTODETECT=1 suppresses detection",
|
|
set: map[string]string{"CLAUDECODE": "1", "WEKNORA_NO_AGENT_AUTODETECT": "1"},
|
|
want: "",
|
|
},
|
|
{
|
|
name: "WEKNORA_NO_AGENT_AUTODETECT=0 still allows detection",
|
|
set: map[string]string{"CLAUDECODE": "1", "WEKNORA_NO_AGENT_AUTODETECT": "0"},
|
|
want: "claude-code",
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
clearAgentEnv(t)
|
|
for k, v := range tc.set {
|
|
t.Setenv(k, v)
|
|
}
|
|
assert.Equal(t, tc.want, DetectAIAgent())
|
|
})
|
|
}
|
|
}
|
|
|