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
22 changes: 22 additions & 0 deletions PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,28 @@ devmap config model auto
The override applies to AI-powered commands. `auto` restores the defaults in
the model routing table.

### Machine-Readable Output

All MVP commands support `--json` for AI agents, scripts, and editor
integrations:

```bash
devmap init --json
devmap analyze --json
devmap ask "how does authentication work?" --json
devmap doctor --json
devmap config model auto --json
```

JSON mode rules:

- stdout contains exactly one valid JSON document
- no ANSI colors, Markdown rendering, box drawing, or progress text
- runtime errors use a stable `{ "status": "error", "error": "...", "hint": "..." }` shape
- `init --json` is non-interactive and requires `GROQ_API_KEY` or existing config
- human-readable output remains the default
- package-manager wrappers may still write their own warnings to stderr

---

## 10. Generated Files
Expand Down
18 changes: 16 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -670,15 +670,29 @@ Run devmap init again or check your provider dashboard.

---

## Output Strategy
## Output Strategy

CLI output should be:

* readable
* minimal
* actionable
* friendly for developers
* consistent across commands
* consistent across commands

### Agent Output

Every MVP command supports `--json`. JSON mode is implemented at the output
context layer so nested operations, such as `ask` triggering quick analysis,
do not leak human progress text into stdout.

Rules:

* emit exactly one JSON document to stdout
* suppress ANSI, Markdown rendering, bullets, and separators
* keep human output as the default
* use structured error objects and preserve non-zero exit codes for thrown failures
* keep command result schemas stable enough for agents and scripts

### Output Should Include

Expand Down
31 changes: 30 additions & 1 deletion docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,36 @@ devmap [command] --no-color
| `--version` | Print DevMap version |
| `--help` | Print help |
| `--json` | Output machine-readable JSON |
| `--no-color` | Disable colored terminal output |
| `--no-color` | Disable colored terminal output |

### JSON Contract

Use `--json` when DevMap is called by an AI agent, script, CI job, or editor
integration.

```bash
devmap init --json
devmap analyze --json
devmap analyze --deep --json
devmap ask "where is authentication handled?" --json
devmap doctor --json
devmap config model auto --json
```

Contract:

* stdout contains exactly one JSON document
* ANSI codes and terminal decoration are disabled
* progress sections and Markdown rendering are omitted
* runtime failures return a JSON object with `status`, `error`, and optional `hint`
* `init --json` never prompts and therefore requires `GROQ_API_KEY` or an
existing API key
* package-manager wrapper warnings may appear on stderr and are not part of the
DevMap JSON document

`analyze --json` returns the project snapshot. `ask --json` returns the answer,
selected files, model, and token usage. `doctor --json` returns diagnostics and
issues as structured fields.

---

Expand Down
16 changes: 16 additions & 0 deletions docs/development-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# DevMap Development Testing

## Agent JSON Output

Packaged-command verification should include machine-readable output:

```bash
devmap analyze --json
devmap ask "where is the main entry point?" --json
devmap doctor --json
```

Parse stdout directly as JSON and verify that it contains no ANSI codes or
terminal decoration. When invoking through `npm exec` or another package
manager, ignore wrapper-owned stderr warnings and validate DevMap stdout
separately.
13 changes: 13 additions & 0 deletions docs/for-me-personal/PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ Terakhir diperbarui: 2026-06-14

## Update 2026-06-14

### Agent JSON Output

- Seluruh command MVP mendukung `--json`.
- stdout JSON hanya berisi satu dokumen valid tanpa ANSI, Markdown renderer,
bullet, separator, atau progress text.
- `analyze --json` mengembalikan snapshot project.
- `ask --json` mengembalikan answer, relevant files, model, dan token usage.
- `doctor --json` mengembalikan diagnostics dan issues terstruktur.
- `config model --json` mengembalikan model state tanpa membocorkan API key.
- `init --json` berjalan non-interaktif dan membutuhkan environment API key
atau existing config.
- Generated `DEVMAP.md` sekarang mengarahkan AI agent memakai `--json`.

### Model Routing And Config

- Default `devmap ask` memakai `llama-3.1-8b-instant`.
Expand Down
31 changes: 31 additions & 0 deletions docs/for-me-personal/TEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,37 @@ pnpm dev:cli config model auto
The first command should preserve the existing API key and provider. The last
command should restore automatic command-based routing.

## Agent JSON Output

Focused contract test:

```powershell
pnpm --filter devmap exec tsx --test test/json-output.test.ts
```

Manual source-mode checks:

```powershell
pnpm dev:cli analyze --json
pnpm dev:cli ask "where scanner" --json
pnpm dev:cli doctor --json
pnpm dev:cli config model auto --json
```

Pipe output into a JSON parser:

```powershell
pnpm dev:cli doctor --json | ConvertFrom-Json
```

Expected:

- parsing succeeds without stripping ANSI;
- stdout contains one JSON document;
- no section header, separator, bullet, or Markdown formatting appears;
- API keys are never included;
- packed package E2E verifies JSON output after tarball installation.

## Urutan Testing Yang Direkomendasikan

Untuk development harian:
Expand Down
7 changes: 6 additions & 1 deletion docs/generated-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ devmap init

Purpose:

Direct AI agents to DevMap.
Direct AI agents to DevMap.

Generated `DEVMAP.md` tells AI agents to use command-level `--json` output
instead of parsing decorated terminal text. This applies to `analyze`, `ask`,
and `doctor`, while `init --json` is intended for non-interactive setup with an
environment API key.

Rules:

Expand Down
32 changes: 25 additions & 7 deletions packages/cli/src/commands/analyze.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { createProjectMap } from "../analyzers/projectMap.js";
import { inspectSnapshot, saveSnapshot } from "../cache/snapshot.js";
import { readConfig, type DevmapConfig } from "../utils/config.js";
import { DevmapError } from "../utils/errors.js";
import { output } from "../utils/output.js";
import { output, withJsonOutput } from "../utils/output.js";

export type AnalyzeOptions = {
deep?: boolean;
fresh?: boolean;
json?: boolean;
};

export type AnalyzeDependencies = {
Expand All @@ -23,6 +24,22 @@ export async function analyzeCommand(
options: AnalyzeOptions = {},
dependencies: AnalyzeDependencies = {}
): Promise<void> {
if (options.json) {
await withJsonOutput(async () => {
const snapshot = await runAnalyze(target, options, dependencies);
output.json(snapshot);
});
return;
}

await runAnalyze(target, options, dependencies);
}

async function runAnalyze(
target: string,
options: AnalyzeOptions,
dependencies: AnalyzeDependencies
): Promise<Awaited<ReturnType<typeof createProjectMap>>> {
const projectRoot = resolve(target);

output.section("DevMap Analyze");
Expand All @@ -34,13 +51,12 @@ export async function analyzeCommand(
if (previous.status === "valid" && previous.snapshot.fingerprint === snapshot.fingerprint) {
printSnapshot(previous.snapshot, options.deep);
output.success("Project is unchanged. Reused existing snapshot.");
await printOrGenerateInterpretation(
return printOrGenerateInterpretation(
projectRoot,
previous.snapshot,
options,
dependencies
);
return;
}

await saveSnapshot(projectRoot, snapshot);
Expand All @@ -51,7 +67,7 @@ export async function analyzeCommand(
output.success("Fresh analysis completed");
}

await printOrGenerateInterpretation(projectRoot, snapshot, options, dependencies);
return printOrGenerateInterpretation(projectRoot, snapshot, options, dependencies);
}

function printSnapshot(
Expand Down Expand Up @@ -109,19 +125,19 @@ async function printOrGenerateInterpretation(
snapshot: Awaited<ReturnType<typeof createProjectMap>>,
options: AnalyzeOptions,
dependencies: AnalyzeDependencies
): Promise<void> {
): Promise<Awaited<ReturnType<typeof createProjectMap>>> {
if (snapshot.ai && !options.fresh) {
output.section("Architecture");
output.markdown(snapshot.ai.architecture);
output.note(formatAiMetadata(snapshot.ai.model, snapshot.ai.usage, true));
return;
return snapshot;
}

const loadConfig = dependencies.loadConfig ?? readConfig;
const config = await loadConfig();
if (!config?.apiKey) {
output.note("AI architecture interpretation is not configured. Run devmap init to enable it.");
return;
return snapshot;
}

const createAiClient = dependencies.createAiClient
Expand Down Expand Up @@ -160,6 +176,7 @@ async function printOrGenerateInterpretation(
interpretation.usage,
false
));
return updatedSnapshot;
} catch (error) {
if (!(error instanceof DevmapError)) {
throw error;
Expand All @@ -170,6 +187,7 @@ async function printOrGenerateInterpretation(
output.note(`Tip: ${error.hint}`);
}
output.note("Static analysis and snapshot were still completed successfully.");
return snapshot;
}
}

Expand Down
Loading
Loading