ai-agent-detect 0.0.1 → 0.2.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 +73 -12
- package/agents/aider/index.js +15 -0
- package/agents/amp/index.js +11 -0
- package/agents/antigravity/index.js +11 -0
- package/agents/augment/index.js +11 -0
- package/agents/claude-code/index.js +24 -0
- package/agents/cline/index.js +12 -0
- package/agents/codex/index.js +19 -0
- package/agents/continue/index.js +11 -0
- package/agents/cowork/index.js +16 -0
- package/agents/crush/index.js +11 -0
- package/agents/cursor/index.js +19 -0
- package/agents/devin/index.js +12 -0
- package/agents/gemini-cli/index.js +11 -0
- package/agents/github-copilot/index.js +20 -0
- package/agents/goose/index.js +14 -0
- package/agents/grok/index.js +13 -0
- package/agents/index.js +54 -0
- package/agents/junie/index.js +14 -0
- package/agents/kilo/index.js +17 -0
- package/agents/kiro/index.js +12 -0
- package/agents/opencode/index.js +16 -0
- package/agents/openhands/index.js +17 -0
- package/agents/pi/index.js +12 -0
- package/agents/qwen-code/index.js +15 -0
- package/agents/replit/index.js +12 -0
- package/agents/roo/index.js +16 -0
- package/fixtures/aider.json +21 -0
- package/fixtures/amp.json +14 -0
- package/fixtures/antigravity.json +20 -0
- package/fixtures/augment.json +20 -0
- package/fixtures/claude-code.json +41 -0
- package/fixtures/cline.json +36 -0
- package/fixtures/codex.json +31 -0
- package/fixtures/continue.json +20 -0
- package/fixtures/cowork.json +21 -0
- package/fixtures/crush.json +20 -0
- package/fixtures/cursor.json +24 -0
- package/fixtures/devin.json +16 -0
- package/fixtures/gemini-cli.json +14 -0
- package/fixtures/github-copilot.json +52 -0
- package/fixtures/goose.json +22 -0
- package/fixtures/grok.json +51 -0
- package/fixtures/junie.json +20 -0
- package/fixtures/kilo.json +28 -0
- package/fixtures/kiro.json +20 -0
- package/fixtures/opencode.json +16 -0
- package/fixtures/openhands.json +23 -0
- package/fixtures/pi.json +20 -0
- package/fixtures/qwen-code.json +23 -0
- package/fixtures/replit.json +20 -0
- package/fixtures/roo.json +38 -0
- package/index.d.ts +37 -0
- package/index.js +139 -5
- package/package.json +28 -3
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "claude-code",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "live: env inside a Claude Code background session (v2.1.205, macOS)",
|
|
7
|
+
"tier": "probed",
|
|
8
|
+
"env": {
|
|
9
|
+
"AI_AGENT": "claude-code_2-1-205_agent",
|
|
10
|
+
"CLAUDECODE": "1",
|
|
11
|
+
"CLAUDE_CODE_ENTRYPOINT": "cli",
|
|
12
|
+
"CLAUDE_CODE_EXECPATH": "/Users/user/.local/share/claude/versions/2.1.205",
|
|
13
|
+
"CLAUDE_CODE_CHILD_SESSION": "1"
|
|
14
|
+
},
|
|
15
|
+
"expect": {
|
|
16
|
+
"isAgent": true,
|
|
17
|
+
"primary": "claude-code",
|
|
18
|
+
"version": "2.1.205",
|
|
19
|
+
"mode": "agent",
|
|
20
|
+
"claimNames": ["claude-code"]
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"date": "2026-07-12",
|
|
25
|
+
"method": "synthetic: AI_AGENT stripped — vendor tells only; version recovered from CLAUDE_CODE_EXECPATH",
|
|
26
|
+
"tier": "synthetic",
|
|
27
|
+
"env": {
|
|
28
|
+
"CLAUDECODE": "1",
|
|
29
|
+
"CLAUDE_CODE_ENTRYPOINT": "cli",
|
|
30
|
+
"CLAUDE_CODE_EXECPATH": "/Users/user/.local/share/claude/versions/2.1.205"
|
|
31
|
+
},
|
|
32
|
+
"expect": {
|
|
33
|
+
"isAgent": true,
|
|
34
|
+
"primary": "claude-code",
|
|
35
|
+
"version": "2.1.205",
|
|
36
|
+
"mode": null,
|
|
37
|
+
"claimNames": ["claude-code"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "cline",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: VscodeTerminalRegistry.ts:29 \u2014 CLINE_ACTIVE=true injected on VS Code integrated terminals",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"CLINE_ACTIVE": "true"
|
|
10
|
+
},
|
|
11
|
+
"expect": {
|
|
12
|
+
"isAgent": true,
|
|
13
|
+
"primary": "cline",
|
|
14
|
+
"claimNames": [
|
|
15
|
+
"cline"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "2026-07-12",
|
|
21
|
+
"method": "source-derived: standalone/CLI path (StandaloneTerminalProcess.ts:104-116) sets only anti-interactivity overrides, NOT the marker \u2014 the coverage gap",
|
|
22
|
+
"tier": "source",
|
|
23
|
+
"env": {
|
|
24
|
+
"TERM": "xterm-256color",
|
|
25
|
+
"PAGER": "cat",
|
|
26
|
+
"GIT_PAGER": "cat",
|
|
27
|
+
"MANPAGER": "cat"
|
|
28
|
+
},
|
|
29
|
+
"expect": {
|
|
30
|
+
"isAgent": false,
|
|
31
|
+
"primary": null,
|
|
32
|
+
"claimNames": []
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "codex",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: codex-rs/core/src/spawn.rs — network sandbox on (any OS)",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"CODEX_SANDBOX_NETWORK_DISABLED": "1"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "isAgent": true, "primary": "codex", "claimNames": ["codex"] }
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"date": "2026-07-12",
|
|
15
|
+
"method": "source-derived: macOS Seatbelt — both sandbox vars present",
|
|
16
|
+
"tier": "source",
|
|
17
|
+
"env": {
|
|
18
|
+
"CODEX_SANDBOX": "seatbelt",
|
|
19
|
+
"CODEX_SANDBOX_NETWORK_DISABLED": "1"
|
|
20
|
+
},
|
|
21
|
+
"expect": { "isAgent": true, "primary": "codex", "claimNames": ["codex"] }
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"date": "2026-07-12",
|
|
25
|
+
"method": "source-derived: --sandbox danger-full-access — NO env signal exists (the documented hole; ppid walk is the only rung that catches codex here)",
|
|
26
|
+
"tier": "source",
|
|
27
|
+
"env": {},
|
|
28
|
+
"expect": { "isAgent": false, "primary": null, "claimNames": [] }
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "continue",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: cn CLI spawns with no env option (runTerminalCommand.ts:192); VS Code path adds only generic color vars. Env-undetectable; upstream ticket candidate (CONTINUE=1)",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"FORCE_COLOR": "1",
|
|
10
|
+
"COLORTERM": "truecolor",
|
|
11
|
+
"CLICOLOR": "1"
|
|
12
|
+
},
|
|
13
|
+
"expect": {
|
|
14
|
+
"isAgent": false,
|
|
15
|
+
"primary": null,
|
|
16
|
+
"claimNames": []
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "cowork",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "vercel-rules-derived: detect-agent@1.0.1 agents.json (adopted, not independently verified) \u2014 cowork marker atop claude-code vars; claude-code detector defers (specificity wins)",
|
|
7
|
+
"tier": "vercel-rules",
|
|
8
|
+
"env": {
|
|
9
|
+
"CLAUDE_CODE_IS_COWORK": "1",
|
|
10
|
+
"CLAUDECODE": "1"
|
|
11
|
+
},
|
|
12
|
+
"expect": {
|
|
13
|
+
"isAgent": true,
|
|
14
|
+
"primary": "cowork",
|
|
15
|
+
"claimNames": [
|
|
16
|
+
"cowork"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "crush",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: full Setenv/cmd.Env sweep of internal/ \u2014 NO self-identity var on shell children; only generic color-forcing on the PTY path. Env-undetectable; upstream ticket candidate (CRUSH=1)",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"COLORTERM": "truecolor",
|
|
10
|
+
"CLICOLOR_FORCE": "1",
|
|
11
|
+
"FORCE_COLOR": "1"
|
|
12
|
+
},
|
|
13
|
+
"expect": {
|
|
14
|
+
"isAgent": false,
|
|
15
|
+
"primary": null,
|
|
16
|
+
"claimNames": []
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "cursor",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "community/staff-derived: agent shell command env (forum.cursor.com/t/132427, t/37734) — both tells present",
|
|
7
|
+
"tier": "community",
|
|
8
|
+
"env": {
|
|
9
|
+
"CURSOR_AGENT": "1",
|
|
10
|
+
"CURSOR_TRACE_ID": "0000-fixture-trace-id"
|
|
11
|
+
},
|
|
12
|
+
"expect": { "isAgent": true, "primary": "cursor", "claimNames": ["cursor"] }
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"date": "2026-07-12",
|
|
16
|
+
"method": "community-derived: trace id only (CURSOR_AGENT=1 was once accidentally dropped by a CLI release — the degraded state)",
|
|
17
|
+
"tier": "community",
|
|
18
|
+
"env": {
|
|
19
|
+
"CURSOR_TRACE_ID": "0000-fixture-trace-id"
|
|
20
|
+
},
|
|
21
|
+
"expect": { "isAgent": true, "primary": "cursor", "claimNames": ["cursor"] }
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "devin",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "vercel-rules-derived: detect-agent@1.0.1 agents.json (adopted, not independently verified) \u2014 only tell is file_exists /opt/.devin, a disk check outside the edge-safe env core; devin detection belongs to the /node rung",
|
|
7
|
+
"tier": "vercel-rules",
|
|
8
|
+
"env": {},
|
|
9
|
+
"expect": {
|
|
10
|
+
"isAgent": false,
|
|
11
|
+
"primary": null,
|
|
12
|
+
"claimNames": []
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "gemini-cli",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source+doc-derived: shellExecutionService.ts sets GEMINI_CLI=1 on every shell-tool child; documented in docs/tools/shell.md",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"GEMINI_CLI": "1"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "isAgent": true, "primary": "gemini-cli", "claimNames": ["gemini-cli"] }
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "github-copilot",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "doc-derived: vendor changelog:1674 \u2014 COPILOT_CLI=1 is the documented subprocess-detection hook, plus session id (changelog:1128)",
|
|
7
|
+
"tier": "doc",
|
|
8
|
+
"env": {
|
|
9
|
+
"COPILOT_CLI": "1",
|
|
10
|
+
"COPILOT_AGENT_SESSION_ID": "fixture-session"
|
|
11
|
+
},
|
|
12
|
+
"expect": {
|
|
13
|
+
"isAgent": true,
|
|
14
|
+
"primary": "github-copilot",
|
|
15
|
+
"claimNames": [
|
|
16
|
+
"github-copilot"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"date": "2026-07-12",
|
|
22
|
+
"method": "vercel-rules-derived: detect-agent@1.0.1 agents.json (adopted, not independently verified) \u2014 COPILOT_MODEL trio, unverified in vendor changelog; weaker fallback",
|
|
23
|
+
"tier": "vercel-rules",
|
|
24
|
+
"env": {
|
|
25
|
+
"COPILOT_MODEL": "gpt-5"
|
|
26
|
+
},
|
|
27
|
+
"expect": {
|
|
28
|
+
"isAgent": true,
|
|
29
|
+
"primary": "github-copilot",
|
|
30
|
+
"claimNames": [
|
|
31
|
+
"github-copilot"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"date": "2026-07-12",
|
|
37
|
+
"method": "doc-derived: AI_AGENT self-identification (github-copilot-cli dialect via core rung 1)",
|
|
38
|
+
"tier": "doc",
|
|
39
|
+
"env": {
|
|
40
|
+
"AI_AGENT": "github-copilot-cli"
|
|
41
|
+
},
|
|
42
|
+
"expect": {
|
|
43
|
+
"isAgent": true,
|
|
44
|
+
"primary": "github-copilot-cli",
|
|
45
|
+
"claimNames": [
|
|
46
|
+
"github-copilot-cli"
|
|
47
|
+
],
|
|
48
|
+
"note": "verbatim rung-1 name; Vercel's scoped pkg normalizes -cli away, we preserve evidence as-is"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "goose",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: computer-controller / retry path (goose-mcp computercontroller/mod.rs:855-873) — AGENT=goose + GOOSE_TERMINAL=1, corroborating",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"AGENT": "goose",
|
|
10
|
+
"GOOSE_TERMINAL": "1"
|
|
11
|
+
},
|
|
12
|
+
"expect": { "isAgent": true, "primary": "goose", "claimNames": ["goose"] }
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"date": "2026-07-12",
|
|
16
|
+
"method": "source-derived: main developer shell tool sets NEITHER var (shell.rs sets only PATH — source contradicts the docs' blanket claim); goose is env-invisible on its most common path",
|
|
17
|
+
"tier": "source",
|
|
18
|
+
"env": {},
|
|
19
|
+
"expect": { "isAgent": false, "primary": null, "claimNames": [] }
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "grok",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "live: agent -p child env (grok 0.2.45, macOS), inherited identity vars scrubbed — grok sets no identity var, only a non-interactive hygiene bundle",
|
|
7
|
+
"tier": "probed",
|
|
8
|
+
"env": {
|
|
9
|
+
"CI": "true",
|
|
10
|
+
"CLICOLOR": "1",
|
|
11
|
+
"CLICOLOR_FORCE": "1",
|
|
12
|
+
"PAGER": "cat",
|
|
13
|
+
"GIT_PAGER": "cat",
|
|
14
|
+
"GH_PAGER": "cat",
|
|
15
|
+
"MANPAGER": "cat",
|
|
16
|
+
"SYSTEMD_PAGER": "cat",
|
|
17
|
+
"AWS_PAGER": "",
|
|
18
|
+
"GIT_TERMINAL_PROMPT": "0",
|
|
19
|
+
"GIT_SEQUENCE_EDITOR": "true",
|
|
20
|
+
"NPM_CONFIG_PROGRESS": "true",
|
|
21
|
+
"PIP_PROGRESS_BAR": "on",
|
|
22
|
+
"CARGO_TERM_PROGRESS_WHEN": "always",
|
|
23
|
+
"CARGO_TERM_PROGRESS_WIDTH": "80"
|
|
24
|
+
},
|
|
25
|
+
"expect": {
|
|
26
|
+
"isAgent": false,
|
|
27
|
+
"primary": null,
|
|
28
|
+
"claimNames": []
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"date": "2026-07-12",
|
|
33
|
+
"method": "live: agent -p spawned INSIDE a Claude Code session, unscrubbed — grok passes inherited AI_AGENT through (nested-harness contamination; env-only detection reports the outer layer by design — detectDeep resolves the stack)",
|
|
34
|
+
"tier": "probed",
|
|
35
|
+
"env": {
|
|
36
|
+
"AI_AGENT": "claude-code_2-1-205_agent",
|
|
37
|
+
"CI": "true",
|
|
38
|
+
"CLICOLOR": "1",
|
|
39
|
+
"PAGER": "cat",
|
|
40
|
+
"GIT_PAGER": "cat",
|
|
41
|
+
"GIT_TERMINAL_PROMPT": "0"
|
|
42
|
+
},
|
|
43
|
+
"expect": {
|
|
44
|
+
"isAgent": true,
|
|
45
|
+
"primary": "claude-code",
|
|
46
|
+
"claimNames": ["claude-code"],
|
|
47
|
+
"note": "honest limitation, not a bug: the inner harness (grok) is env-invisible"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "junie",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "vercel-rules-derived: detect-agent@1.0.1 agents.json (adopted, not independently verified)",
|
|
7
|
+
"tier": "vercel-rules",
|
|
8
|
+
"env": {
|
|
9
|
+
"JUNIE_DATA": "/tmp/junie"
|
|
10
|
+
},
|
|
11
|
+
"expect": {
|
|
12
|
+
"isAgent": true,
|
|
13
|
+
"primary": "junie",
|
|
14
|
+
"claimNames": [
|
|
15
|
+
"junie"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "kilo",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: cli/setup.ts:56 + server-manager.ts:113-152 + fork-parent index.ts:111-113 \u2014 the richest emitter surveyed; opencode detector legitimately fires too (kilo IS opencode underneath): the claims model represents it",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"KILO": "1",
|
|
10
|
+
"KILO_CLIENT": "vscode",
|
|
11
|
+
"KILOCODE_FEATURE": "vscode-extension",
|
|
12
|
+
"KILOCODE_VERSION": "4.99.0",
|
|
13
|
+
"KILO_PID": "4242",
|
|
14
|
+
"AGENT": "1",
|
|
15
|
+
"OPENCODE": "1"
|
|
16
|
+
},
|
|
17
|
+
"expect": {
|
|
18
|
+
"isAgent": true,
|
|
19
|
+
"primary": "kilo",
|
|
20
|
+
"version": "4.99.0",
|
|
21
|
+
"claimNames": [
|
|
22
|
+
"kilo",
|
|
23
|
+
"opencode"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "kiro",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "vercel-rules-derived: detect-agent@1.0.1 agents.json (adopted, not independently verified) \u2014 their rule gates on no_tty which env-only cannot see; low confidence, ambience not identity",
|
|
7
|
+
"tier": "vercel-rules",
|
|
8
|
+
"env": {
|
|
9
|
+
"TERM_PROGRAM": "kiro"
|
|
10
|
+
},
|
|
11
|
+
"expect": {
|
|
12
|
+
"isAgent": true,
|
|
13
|
+
"primary": "kiro",
|
|
14
|
+
"claimNames": [
|
|
15
|
+
"kiro"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "opencode",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: startup middleware (packages/opencode/src/index.ts:75-77) — OPENCODE=1, AGENT=1 (boolean: anonymous claim), OPENCODE_PID",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"OPENCODE": "1",
|
|
10
|
+
"AGENT": "1",
|
|
11
|
+
"OPENCODE_PID": "12345"
|
|
12
|
+
},
|
|
13
|
+
"expect": { "isAgent": true, "primary": "opencode", "claimNames": ["opencode"] }
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "openhands",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: docker_sandbox_spec_service.py:38-52 + subprocess_terminal.py:150 \u2014 sandbox container furniture + PS1 markers; environment fingerprint, not identity by intent",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"OH_CONVERSATIONS_PATH": "/workspace/conversations",
|
|
10
|
+
"OH_BASH_EVENTS_DIR": "/workspace/bash_events",
|
|
11
|
+
"OPENVSCODE_SERVER_ROOT": "/openhands/.openvscode-server",
|
|
12
|
+
"PS1": "###PS1JSON###{}###PS1END###"
|
|
13
|
+
},
|
|
14
|
+
"expect": {
|
|
15
|
+
"isAgent": true,
|
|
16
|
+
"primary": "openhands",
|
|
17
|
+
"claimNames": [
|
|
18
|
+
"openhands"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
package/fixtures/pi.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "pi",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "vercel-rules-derived: detect-agent@1.0.1 agents.json (adopted, not independently verified) \u2014 PATH fingerprint, weak-signal class",
|
|
7
|
+
"tier": "vercel-rules",
|
|
8
|
+
"env": {
|
|
9
|
+
"PATH": "/usr/bin:/home/u/.pi/agent/bin"
|
|
10
|
+
},
|
|
11
|
+
"expect": {
|
|
12
|
+
"isAgent": true,
|
|
13
|
+
"primary": "pi",
|
|
14
|
+
"claimNames": [
|
|
15
|
+
"pi"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "qwen-code",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: shellExecutionService.ts:723 + shellContextEnv.ts:41-55 \u2014 QWEN_CODE=1 with session-id family on every shell child; renamed from Gemini's GEMINI_CLI (fork, zero GEMINI_CLI hits)",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"QWEN_CODE": "1",
|
|
10
|
+
"QWEN_CODE_SESSION_ID": "fixture-uuid",
|
|
11
|
+
"QWEN_CODE_AGENT_ID": "",
|
|
12
|
+
"QWEN_CODE_PROMPT_ID": ""
|
|
13
|
+
},
|
|
14
|
+
"expect": {
|
|
15
|
+
"isAgent": true,
|
|
16
|
+
"primary": "qwen-code",
|
|
17
|
+
"claimNames": [
|
|
18
|
+
"qwen-code"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "replit",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "vercel-rules-derived: detect-agent@1.0.1 agents.json (adopted, not independently verified) \u2014 REPL_ID marks the Replit environment, not specifically its agent",
|
|
7
|
+
"tier": "vercel-rules",
|
|
8
|
+
"env": {
|
|
9
|
+
"REPL_ID": "fixture-repl"
|
|
10
|
+
},
|
|
11
|
+
"expect": {
|
|
12
|
+
"isAgent": true,
|
|
13
|
+
"primary": "replit",
|
|
14
|
+
"claimNames": [
|
|
15
|
+
"replit"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agent": "roo",
|
|
3
|
+
"probes": [
|
|
4
|
+
{
|
|
5
|
+
"date": "2026-07-12",
|
|
6
|
+
"method": "source-derived: Terminal.ts:153-161 \u2014 ROO_ACTIVE=true on VS Code terminals",
|
|
7
|
+
"tier": "source",
|
|
8
|
+
"env": {
|
|
9
|
+
"ROO_ACTIVE": "true",
|
|
10
|
+
"PAGER": "cat",
|
|
11
|
+
"VTE_VERSION": "0"
|
|
12
|
+
},
|
|
13
|
+
"expect": {
|
|
14
|
+
"isAgent": true,
|
|
15
|
+
"primary": "roo",
|
|
16
|
+
"claimNames": [
|
|
17
|
+
"roo"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"date": "2026-07-12",
|
|
23
|
+
"method": "source-derived: extension-host.ts:182 \u2014 ROO_CLI_RUNTIME=1 process-wide in the headless CLI",
|
|
24
|
+
"tier": "source",
|
|
25
|
+
"env": {
|
|
26
|
+
"ROO_CLI_RUNTIME": "1"
|
|
27
|
+
},
|
|
28
|
+
"expect": {
|
|
29
|
+
"isAgent": true,
|
|
30
|
+
"primary": "roo",
|
|
31
|
+
"mode": "agent",
|
|
32
|
+
"claimNames": [
|
|
33
|
+
"roo"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Hand-written declarations — no build step for a zero-dep package.
|
|
2
|
+
|
|
3
|
+
export interface AgentClaim {
|
|
4
|
+
/** Canonical agent slug, or null when agenthood is proven but unnamed (e.g. AGENT=1). */
|
|
5
|
+
name: string | null;
|
|
6
|
+
vendor: string | null;
|
|
7
|
+
version: string | null;
|
|
8
|
+
mode: string | null;
|
|
9
|
+
/** Which rung produced this claim. */
|
|
10
|
+
source: 'env:AI_AGENT' | 'env:AGENT' | 'env:vendor';
|
|
11
|
+
confidence: 'high' | 'medium' | 'low';
|
|
12
|
+
/** The matched evidence — the env vars this claim rests on. */
|
|
13
|
+
raw: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AgentInfo extends AgentClaim {
|
|
17
|
+
/** Set when an independent signal confirmed the primary claim. */
|
|
18
|
+
corroborated?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Every claim the environment carries, deliberately unordered — env cannot
|
|
21
|
+
* order nesting layers (an outer harness's vars pass through inner ones).
|
|
22
|
+
*/
|
|
23
|
+
claims: AgentClaim[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DetectOptions {
|
|
27
|
+
/** Inject an env (tests, snapshots). Defaults to process.env, copied once per process. */
|
|
28
|
+
env?: Record<string, string | undefined>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Structured detection: primary claim + all claims, or null when nothing matches. */
|
|
32
|
+
export function detect(opts?: DetectOptions): AgentInfo | null;
|
|
33
|
+
|
|
34
|
+
/** Am I running under any agent? */
|
|
35
|
+
export function isAgent(opts?: DetectOptions): boolean;
|
|
36
|
+
/** Assert style: am I running under this specific agent? */
|
|
37
|
+
export function isAgent(name: string, opts?: DetectOptions): boolean;
|