Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ you: add rate limiting to the /api/upload endpoint

## What you get

**Ambient intelligence.** Devflow detects structured plans for automatic execution — normal prompts get zero overhead, no classification step. You never invoke it manually. Init and forget.
**Ambient intelligence.** Devflow detects workflow intent — start a prompt with `implement`, `explore`, `research`, `debug`, or `plan`, or paste a structured plan, and the matching workflow runs automatically. Normal prompts get zero overhead, no classification step. No slash commands needed. Init and forget.

**Memory that persists.** Session context survives restarts, `/clear`, and context compaction. Your AI picks up exactly where it left off. Architectural decisions and known pitfalls accumulate in `.devflow/decisions/` and inform every future session. No manual bookkeeping.

Expand Down
4 changes: 2 additions & 2 deletions scripts/hooks/preamble
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ shopt -u nocasematch
# prompts and is negligible in practice (~6ms at 200KB). No subprocess required.
if [[ -n "$SKILL" && -n "$REST" ]] && ! [[ "$PROMPT" =~ [?][[:space:]]*$ ]]; then
dbg "WORKFLOW_KEYWORD detected: $SKILL — injecting directive"
json_prompt_output "The user is invoking the \`$SKILL\` workflow. Briefly tell the user you are invoking \`devflow:$SKILL\`, then invoke it via the Skill tool, passing the user's request (the text after the leading \`$SKILL\` keyword) as the task input."
json_prompt_output "The user's prompt begins with the \`$SKILL\` keyword, which signals the \`devflow:$SKILL\` workflow. In one short sentence, tell the user you're invoking \`devflow:$SKILL\`. Then immediately invoke it with the Skill tool, passing the user's full request (everything after the leading \`$SKILL\` keyword) as the skill input. Do not pause to ask whether to proceed."
elif [[ "$PROMPT" == *"## Goal"* ]] && [[ "$PROMPT" == *"## Steps"* ]] && [[ "$PROMPT" == *"## Files"* ]]; then
dbg "EXECUTION_PLAN detected — injecting directive"
json_prompt_output "The user supplied a structured implementation plan. Briefly tell the user you are invoking \`devflow:implement\`, then invoke it via the Skill tool to execute this plan."
json_prompt_output "The user's prompt is a structured implementation plan (it contains ## Goal, ## Steps, and ## Files). In one short sentence, tell the user you're invoking \`devflow:implement\`. Then immediately invoke it with the Skill tool, passing the full plan as the skill input so it can be executed. Do not pause to ask whether to proceed."
else
dbg "No keyword or plan markers detected — no output"
fi
Expand Down
12 changes: 6 additions & 6 deletions src/cli/commands/ambient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export async function addAmbientHook(settingsJson: string, devflowDir: string):
const settings: Settings = JSON.parse(settingsJson);
let changed = filterHookEntries(settings, 'UserPromptSubmit', isLegacy);

// --- UserPromptSubmit: preamble hook (plan detection) ---
// --- UserPromptSubmit: preamble hook (keyword + plan detection) ---
const hasPreamble = settings.hooks?.UserPromptSubmit?.some((m) =>
m.hooks.some((h) => h.command.includes(PREAMBLE_HOOK_MARKER)),
);
Expand Down Expand Up @@ -150,7 +150,7 @@ interface AmbientOptions {
}

export const ambientCommand = new Command('ambient')
.description('Enable or disable ambient mode (plan auto-detection)')
.description('Enable or disable ambient mode (keyword + plan auto-detection)')
.option('--enable', 'Register ambient mode hook')
.option('--disable', 'Remove ambient mode hook')
.option('--status', 'Check if ambient mode is enabled')
Expand All @@ -159,8 +159,8 @@ export const ambientCommand = new Command('ambient')
if (!hasFlag) {
p.intro(color.bgMagenta(color.white(' Ambient Mode ')));
p.note(
`${color.cyan('devflow ambient --enable')} Register plan detection hook\n` +
`${color.cyan('devflow ambient --disable')} Remove plan detection hook\n` +
`${color.cyan('devflow ambient --enable')} Register detection hook\n` +
`${color.cyan('devflow ambient --disable')} Remove detection hook\n` +
`${color.cyan('devflow ambient --status')} Check current state`,
'Usage',
);
Expand Down Expand Up @@ -219,8 +219,8 @@ export const ambientCommand = new Command('ambient')
return;
}
await fs.writeFile(settingsPath, updated, 'utf-8');
p.log.success('Ambient mode enabled — plan detection hook registered');
p.log.info(color.dim('Structured plans auto-execute'));
p.log.success('Ambient mode enabled — detection hook registered');
p.log.info(color.dim('Keyword prompts and structured plans auto-run their workflow'));
}

if (options.disable) {
Expand Down
9 changes: 5 additions & 4 deletions src/cli/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export const initCommand = new Command('init')
.option('--plugin <names>', 'Install specific plugin(s), comma-separated (e.g., implement,code-review)')
.option('--teams', 'Enable Agent Teams (peer debate, adversarial review)')
.option('--no-teams', 'Disable Agent Teams (use parallel subagents instead)')
.option('--ambient', 'Enable ambient mode (plan auto-detection)')
.option('--ambient', 'Enable ambient mode (keyword + plan auto-detection)')
.option('--no-ambient', 'Disable ambient mode')
.option('--memory', 'Enable working memory (session context preservation)')
.option('--no-memory', 'Disable working memory hooks')
Expand Down Expand Up @@ -552,9 +552,10 @@ export const initCommand = new Command('init')
ambientEnabled = options.ambient;
} else {
p.note(
'Detects implementation plans and auto-executes them.\n' +
'When the first message is a structured plan, automatically\n' +
'invokes the implement workflow to execute it.\n\n' +
'Detects workflow intent in your prompt and runs it automatically.\n' +
'Start a prompt with implement, explore, research, debug, or plan\n' +
'(or paste a structured plan) and the matching workflow runs —\n' +
'no slash command needed.\n\n' +
'Zero overhead for normal prompts.',
'Ambient Mode',
);
Expand Down
2 changes: 1 addition & 1 deletion src/cli/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export const DEVFLOW_PLUGINS: PluginDefinition[] = [
},
{
name: 'devflow-ambient',
description: 'Plan auto-detection',
description: 'Keyword + plan auto-detection',
commands: ['/ambient'],
agents: ['coder', 'validator', 'simplifier', 'scrutinizer', 'evaluator', 'tester', 'skimmer', 'reviewer', 'git', 'synthesizer', 'resolver', 'designer', 'knowledge', 'researcher'],
skills: [
Expand Down
10 changes: 6 additions & 4 deletions tests/shell-hooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1108,9 +1108,11 @@ describe('preamble keyword detection', () => {
/** Expected additionalContext message for a matched skill. */
function expectedContext(skill: string): string {
return (
`The user is invoking the \`${skill}\` workflow. Briefly tell the user you are invoking ` +
`\`devflow:${skill}\`, then invoke it via the Skill tool, passing the user's request ` +
`(the text after the leading \`${skill}\` keyword) as the task input.`
`The user's prompt begins with the \`${skill}\` keyword, which signals the ` +
`\`devflow:${skill}\` workflow. In one short sentence, tell the user you're invoking ` +
`\`devflow:${skill}\`. Then immediately invoke it with the Skill tool, passing the user's ` +
`full request (everything after the leading \`${skill}\` keyword) as the skill input. ` +
`Do not pause to ask whether to proceed.`
);
}

Expand Down Expand Up @@ -1198,7 +1200,7 @@ describe('preamble keyword detection', () => {
const ctx = parsed.hookSpecificOutput.additionalContext;
expect(ctx).toContain('`devflow:research`');
expect(ctx).toContain('Skill tool');
expect(ctx).toContain('Briefly tell the user');
expect(ctx).toContain("tell the user you're invoking");
});
});

Expand Down
Loading