Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ Use `npm create veryfront` when you want to scaffold a new project.
## Coding-agent setup

Starter templates include `AGENTS.md`. For older projects, install the shared
project guide:
project guide with `--target agents`:

```bash
veryfront install agents
veryfront install --target agents
```

Then run `veryfront dev` and connect your MCP-aware coding agent to the printed
Expand Down
13 changes: 8 additions & 5 deletions docs/guides/coding-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,21 @@ bootstrap step, inference setup, and when to use https://veryfront.com/docs.
For older projects, add the same guide with:

```bash
veryfront install agents
veryfront install --target agents
```

Tool-specific files are still available:

```bash
veryfront install claude-code
veryfront install cursor
veryfront install copilot
veryfront install windsurf
veryfront install --target claude-code
veryfront install --target cursor
veryfront install --target copilot
veryfront install --target windsurf
```

Running `veryfront install` without `--target` opens an interactive picker
instead, preselecting the tools it detects in the project.
Comment thread
kojiwakayama marked this conversation as resolved.
Outdated

Use `AGENTS.md` as the shared source of truth when multiple coding agents work
in the same project.

Expand Down
116 changes: 116 additions & 0 deletions tests/docs/cli-install-commands.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* Docs contract: every `veryfront install ...` command printed in the published
* docs must actually select the AI-tool target the surrounding prose promises.
*
* The install command reads its target from `--target` only. A bare positional
* (`veryfront install agents`) is silently ignored and the command falls back to
* auto-detection, which in a fresh project writes `SKILL.md` instead of the
* `AGENTS.md` the docs describe.
*/

import "#veryfront/schemas/_test-setup.ts";
import { assert, assertEquals } from "#veryfront/testing/assert.ts";
import { describe, it } from "#veryfront/testing/bdd.ts";
import { parseCliArgs } from "../../cli/shared/args.ts";
import { parseInstallArgs } from "../../cli/commands/install/handler.ts";
import { parseTargetFlag } from "../../cli/commands/install/install.ts";
import { getToolById } from "../../cli/commands/install/registry.ts";

const DOC_DIRS = ["docs/getting-started", "docs/guides", "docs/concepts"] as const;

interface DocumentedInstall {
file: string;
command: string;
}

async function listDocFiles(dir: string): Promise<string[]> {
const files: string[] = [];
for await (const entry of Deno.readDir(dir)) {
const path = `${dir}/${entry.name}`;
if (entry.isDirectory) {
files.push(...await listDocFiles(path));
} else if (entry.isFile && entry.name.endsWith(".md")) {
files.push(path);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
}
return files;
}

/** Collect `veryfront install ...` lines from fenced shell blocks. */
function extractInstallCommands(file: string, source: string): DocumentedInstall[] {
const found: DocumentedInstall[] = [];
let inShellFence = false;

for (const rawLine of source.split("\n")) {
const line = rawLine.trim();

if (line.startsWith("```")) {
const lang = line.slice(3).trim().toLowerCase();
inShellFence = inShellFence ? false : lang === "bash" || lang === "sh" || lang === "shell";
continue;
}

if (!inShellFence) continue;
if (!line.startsWith("veryfront install")) continue;

found.push({ file, command: line });
}

return found;
}

async function collectDocumentedInstalls(): Promise<DocumentedInstall[]> {
const commands: DocumentedInstall[] = [];
for (const dir of DOC_DIRS) {
for (const file of await listDocFiles(dir)) {
commands.push(...extractInstallCommands(file, await Deno.readTextFile(file)));
}
}
return commands.sort((a, b) => a.command.localeCompare(b.command));
}

/** Run a documented command line through the real CLI parsing pipeline. */
function resolveTargets(command: string): string[] {
const argv = command.replace(/^veryfront\s+/, "").split(/\s+/).filter(Boolean);
const parsed = parseInstallArgs(parseCliArgs(argv));

assert(parsed.success, `\`${command}\` failed argument validation`);
if (parsed.data.target === undefined) return [];

return parseTargetFlag(parsed.data.target);
}

describe("docs: veryfront install commands", () => {
it("every documented install command selects a target non-interactively", async () => {
const documented = await collectDocumentedInstalls();
assert(documented.length > 0, "expected the docs to document `veryfront install`");

const ignored = documented.filter(({ command }) => resolveTargets(command).length === 0);

assertEquals(
ignored.map(({ file, command }) => `${file}: ${command}`),
[],
"these documented commands pass a target the CLI ignores; use `--target <id>`",
);
});

it("the pages that promise AGENTS.md document a command that writes AGENTS.md", async () => {
const pages = ["docs/getting-started/installation.md", "docs/guides/coding-agents.md"];

for (const page of pages) {
const source = await Deno.readTextFile(page);
assert(source.includes("AGENTS.md"), `${page} should describe AGENTS.md`);

const files = extractInstallCommands(page, source)
.flatMap(({ command }) => resolveTargets(command))
.map((id) => getToolById(id).file);

assert(
files.includes("AGENTS.md"),
`${page} promises AGENTS.md but documents no install command that writes it (writes: ${
files.join(", ") || "nothing"
})`,
);
}
});
});
2 changes: 1 addition & 1 deletion tests/docs/guide-code-examples.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ describe("Guide: installation.md", () => {
"yarn global add veryfront",
"bun add -g veryfront",
"npx veryfront@latest",
"veryfront install agents",
"veryfront install --target agents",
"veryfront --version",
];

Expand Down
2 changes: 1 addition & 1 deletion tests/docs/guide-contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ const GUIDE_CONTRACTS: Record<string, GuideContract> = {
"npm create veryfront",
"npm install -g veryfront",
"npx veryfront@latest",
"veryfront install agents",
"veryfront install --target agents",
],
},
"getting-started/create-agent.md": {
Expand Down