Skip to content

Commit 9800a93

Browse files
committed
fix(cli): respect saved agent config precedence
1 parent 5687ca7 commit 9800a93

4 files changed

Lines changed: 70 additions & 11 deletions

File tree

src/agent/detect.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ export function detectInstalledAgents(): AgentType[] {
1818
.map(([type]) => type as AgentType)
1919
}
2020

21+
/** Detect the active agent from environment variables. */
22+
export function detectEnvAgent(): AgentType | null {
23+
for (const [type, target] of Object.entries(agents)) {
24+
if (target.detectEnv())
25+
return type as AgentType
26+
}
27+
return null
28+
}
29+
2130
/**
2231
* Detect the target agent (where skills are installed) from env vars and cwd.
2332
* This is NOT the generator LLM — it determines the skills directory.
@@ -27,10 +36,9 @@ export function detectInstalledAgents(): AgentType[] {
2736
* rather than silently picking the first match.
2837
*/
2938
export function detectTargetAgent(): AgentType | null {
30-
for (const [type, target] of Object.entries(agents)) {
31-
if (target.detectEnv())
32-
return type as AgentType
33-
}
39+
const envAgent = detectEnvAgent()
40+
if (envAgent)
41+
return envAgent
3442

3543
const cwd = process.cwd()
3644
const projectMatches: AgentType[] = []

src/agent/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export {
1717
// Import detection
1818
export { detectImportedPackages } from './detect-imports.ts'
1919
// Detection
20-
export { detectInstalledAgents, detectProjectAgents, detectTargetAgent, getAgentVersion } from './detect.ts'
20+
export { detectEnvAgent, detectInstalledAgents, detectProjectAgents, detectTargetAgent, getAgentVersion } from './detect.ts'
2121
// Installation
2222
export { computeSkillDirName, installSkillForAgents, linkSkillToAgents, sanitizeName, unlinkSkillFromAgents } from './install.ts'
2323

src/cli/agent-prompt.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
import type { AgentType } from '../agent/index.ts'
22
import { styleText } from 'node:util'
33
import * as p from '@clack/prompts'
4-
import { agents, detectInstalledAgents, detectProjectAgents, detectTargetAgent } from '../agent/index.ts'
4+
import { agents, detectEnvAgent, detectInstalledAgents, detectProjectAgents } from '../agent/index.ts'
55
import { readConfig, updateConfig } from '../core/config.ts'
66
import { isInteractive } from './env.ts'
77

8+
function detectProjectAgent(): AgentType | null {
9+
const projectMatches = detectProjectAgents()
10+
return projectMatches.length === 1 ? projectMatches[0]! : null
11+
}
12+
813
export function resolveAgent(agentFlag?: string): AgentType | 'none' | null {
914
if (process.env.SKILLD_NO_AGENT)
1015
return null
1116
return (agentFlag as AgentType | undefined)
12-
?? detectTargetAgent()
17+
?? detectEnvAgent()
1318
?? (readConfig().agent as AgentType | undefined)
19+
?? detectProjectAgent()
1420
?? null
1521
}
1622

@@ -35,10 +41,6 @@ export function autoResolveAgent(agentFlag?: string): AgentType | null {
3541
if (process.env.SKILLD_NO_AGENT)
3642
return null
3743

38-
const projectMatches = detectProjectAgents()
39-
if (projectMatches.length === 1)
40-
return projectMatches[0]!
41-
4244
const installed = detectInstalledAgents()
4345
if (installed.length === 1)
4446
return installed[0]!

test/unit/agent-prompt.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2+
import { autoResolveAgent } from '../../src/cli/agent-prompt.ts'
3+
4+
const detection = vi.hoisted(() => ({
5+
configAgent: undefined as string | undefined,
6+
envAgent: null as string | null,
7+
installedAgents: [] as string[],
8+
projectAgents: [] as string[],
9+
}))
10+
11+
vi.mock('../../src/agent/index.ts', () => ({
12+
agents: {},
13+
detectEnvAgent: () => detection.envAgent,
14+
detectInstalledAgents: () => detection.installedAgents,
15+
detectProjectAgents: () => detection.projectAgents,
16+
detectTargetAgent: () => detection.envAgent
17+
?? (detection.projectAgents.length === 1 ? detection.projectAgents[0] : null),
18+
}))
19+
20+
vi.mock('../../src/core/config.ts', () => ({
21+
readConfig: () => ({ agent: detection.configAgent }),
22+
updateConfig: vi.fn(),
23+
}))
24+
25+
describe('autoResolveAgent', () => {
26+
const originalNoAgent = process.env.SKILLD_NO_AGENT
27+
28+
beforeEach(() => {
29+
detection.configAgent = undefined
30+
detection.envAgent = null
31+
detection.installedAgents = []
32+
detection.projectAgents = []
33+
delete process.env.SKILLD_NO_AGENT
34+
})
35+
36+
afterEach(() => {
37+
if (originalNoAgent === undefined)
38+
delete process.env.SKILLD_NO_AGENT
39+
else
40+
process.env.SKILLD_NO_AGENT = originalNoAgent
41+
})
42+
43+
it('prefers the saved config over a single project marker', () => {
44+
detection.configAgent = 'claude-code'
45+
detection.projectAgents = ['cursor']
46+
47+
expect(autoResolveAgent()).toBe('claude-code')
48+
})
49+
})

0 commit comments

Comments
 (0)