aiki-cli 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.
Files changed (78) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/LICENSE +21 -0
  3. package/README.md +275 -0
  4. package/dist/bench/arms.js +104 -0
  5. package/dist/bench/harness.js +251 -0
  6. package/dist/bench/results.js +70 -0
  7. package/dist/bench/scoring/seeded-bugs.js +31 -0
  8. package/dist/cli/bench.js +50 -0
  9. package/dist/cli/config.js +51 -0
  10. package/dist/cli/doctor.js +115 -0
  11. package/dist/cli/index.js +129 -0
  12. package/dist/cli/models.js +51 -0
  13. package/dist/cli/providers.js +31 -0
  14. package/dist/cli/resolve.js +159 -0
  15. package/dist/cli/resume.js +94 -0
  16. package/dist/cli/run.js +155 -0
  17. package/dist/cli/sessions.js +35 -0
  18. package/dist/cli/show.js +73 -0
  19. package/dist/config/config.js +102 -0
  20. package/dist/config/smoke-cache.js +65 -0
  21. package/dist/council/open.js +26 -0
  22. package/dist/council/view.js +873 -0
  23. package/dist/orchestration/cluster.js +83 -0
  24. package/dist/orchestration/context.js +277 -0
  25. package/dist/orchestration/engine.js +92 -0
  26. package/dist/orchestration/git.js +133 -0
  27. package/dist/orchestration/jsonStage.js +32 -0
  28. package/dist/orchestration/skills.js +39 -0
  29. package/dist/orchestration/stages/cr-ladder.js +63 -0
  30. package/dist/orchestration/stages/cr-map.js +62 -0
  31. package/dist/orchestration/stages/cr-report.js +83 -0
  32. package/dist/orchestration/stages/cr-s4-review.js +69 -0
  33. package/dist/orchestration/stages/cr-s8-crossexam.js +104 -0
  34. package/dist/orchestration/stages/cr-s9-judge.js +89 -0
  35. package/dist/orchestration/stages/s0-grill.js +79 -0
  36. package/dist/orchestration/stages/s1-intent.js +25 -0
  37. package/dist/orchestration/stages/s10-render.js +198 -0
  38. package/dist/orchestration/stages/s2-misread.js +76 -0
  39. package/dist/orchestration/stages/s3-prompts.js +55 -0
  40. package/dist/orchestration/stages/s4-analyze.js +50 -0
  41. package/dist/orchestration/stages/s5-drift.js +40 -0
  42. package/dist/orchestration/stages/s6-claims.js +56 -0
  43. package/dist/orchestration/stages/s7-disagreement.js +134 -0
  44. package/dist/orchestration/stages/s8-verify.js +56 -0
  45. package/dist/orchestration/stages/s9-judge.js +152 -0
  46. package/dist/orchestration/stages/s9b-plan.js +192 -0
  47. package/dist/providers/adapter-core.js +131 -0
  48. package/dist/providers/adapters.js +9 -0
  49. package/dist/providers/agy.js +29 -0
  50. package/dist/providers/claude.js +56 -0
  51. package/dist/providers/codex.js +35 -0
  52. package/dist/providers/detect.js +21 -0
  53. package/dist/providers/probe.js +43 -0
  54. package/dist/providers/profiles.js +38 -0
  55. package/dist/providers/profiles.json +5 -0
  56. package/dist/providers/smoke.js +26 -0
  57. package/dist/providers/spawn.js +152 -0
  58. package/dist/providers/types.js +17 -0
  59. package/dist/schemas/index.js +374 -0
  60. package/dist/skills/.gitkeep +0 -0
  61. package/dist/skills/code-review/judge.md +23 -0
  62. package/dist/skills/code-review/reviewer.md +38 -0
  63. package/dist/skills/idea-refinement/analyst.md +45 -0
  64. package/dist/skills/idea-refinement/planner.md +25 -0
  65. package/dist/storage/feedback.js +111 -0
  66. package/dist/storage/paths.js +20 -0
  67. package/dist/storage/replay.js +0 -0
  68. package/dist/storage/runs-read.js +95 -0
  69. package/dist/storage/runs.js +129 -0
  70. package/dist/storage/sessions.js +71 -0
  71. package/dist/tui/app.js +444 -0
  72. package/dist/tui/format.js +27 -0
  73. package/dist/tui/index.js +8 -0
  74. package/dist/tui/smart-entry.js +106 -0
  75. package/dist/tui/timeline.js +91 -0
  76. package/dist/workflows/code-review.js +76 -0
  77. package/dist/workflows/idea-refinement.js +105 -0
  78. package/package.json +64 -0
@@ -0,0 +1,91 @@
1
+ // Pure timeline model for the run screen (T8, §4.2). No Ink here — the reducer that turns the
2
+ // engine's stage events into row states, plus provider resolution and glyphs. Unit-tested directly.
3
+ import { DISPLAY_NAME } from '../providers/types.js';
4
+ /** §4.2 state glyphs. */
5
+ export const GLYPH = {
6
+ pending: '○',
7
+ running: '◐',
8
+ done: '●',
9
+ failed: '✖',
10
+ skipped: '⊘',
11
+ };
12
+ /** Which provider chip(s) a row shows, from its role hint + the resolved roles. */
13
+ export function stageProviders(role, roles, available) {
14
+ switch (role) {
15
+ case 'analyst':
16
+ return [roles.analyst];
17
+ case 'judge':
18
+ return [roles.judge];
19
+ case 'verifier':
20
+ return [roles.verifier];
21
+ case 's4':
22
+ return roles.s4;
23
+ case 'all':
24
+ return available;
25
+ case null:
26
+ return [];
27
+ }
28
+ }
29
+ /** All rows pending, providers resolved — the skeleton drawn before the run starts. */
30
+ export function initTimeline(stages, roles, available) {
31
+ return stages.map((s) => ({
32
+ id: s.id,
33
+ label: s.label,
34
+ providers: stageProviders(s.role, roles, available),
35
+ status: 'pending',
36
+ }));
37
+ }
38
+ export function markStart(rows, id, now) {
39
+ return rows.map((r) => (r.id === id ? { ...r, status: 'running', startedAt: now } : r));
40
+ }
41
+ export function markEnd(rows, id, status, now) {
42
+ return rows.map((r) => (r.id === id ? { ...r, status, endedAt: now } : r));
43
+ }
44
+ /** Elapsed label for a row: final duration once ended, live seconds while running, else empty. */
45
+ export function elapsedLabel(row, now) {
46
+ if (row.status === 'done' || row.status === 'failed') {
47
+ if (row.startedAt === undefined || row.endedAt === undefined)
48
+ return '';
49
+ return `${((row.endedAt - row.startedAt) / 1000).toFixed(1)}s`;
50
+ }
51
+ if (row.status === 'running' && row.startedAt !== undefined)
52
+ return `${Math.floor((now - row.startedAt) / 1000)}s`;
53
+ return '';
54
+ }
55
+ export const displayNames = (ps) => ps.map((p) => DISPLAY_NAME[p]).join(', ');
56
+ // ── V10 run-screen life: rotating status phrases + progress bar + total time. Pure; unit-tested. ────
57
+ /** Stage-flavored status phrases, rotated every 4s so long stages feel alive (not stuck). */
58
+ const PHRASES = {
59
+ S0: ['grilling the intent', 'sharpening the run brief'],
60
+ S1: ['pinning down what you actually asked', 'writing the task contract'],
61
+ S2: ['checking every model read it the same way', 'guarding against a misread'],
62
+ S3: ["writing each seat's brief", 'tailoring the role prompts'],
63
+ S4: ['council working in separate rooms', 'independent takes incoming'],
64
+ S5: ['checking nobody drifted off-task', 'comparing echoes against the contract'],
65
+ S6: ['boiling the output down to claims', 'extracting the claims'],
66
+ S7: ['mapping where they disagree', 'drawing the disagreement map'],
67
+ S8: ['cross-examining the claims', 'stress-testing the evidence'],
68
+ S9: ['the judge is deliberating', 'weighing evidence over confidence'],
69
+ S9b: ['planning decisive validation', 'ordering the next tests'],
70
+ S10: ['writing the report', 'assembling the decision brief'],
71
+ };
72
+ /** The phrase for a running stage at `seconds` elapsed (cycles its list every 4s). */
73
+ export function runningPhrase(stageId, seconds) {
74
+ const list = PHRASES[stageId];
75
+ if (!list || list.length === 0)
76
+ return 'working';
77
+ return list[Math.floor(seconds / 4) % list.length];
78
+ }
79
+ /** Overall progress: finished-stage count (done/failed/skipped) as a ▰▱ bar + counts. */
80
+ export function progressBar(rows) {
81
+ const done = rows.filter((r) => r.status === 'done' || r.status === 'failed' || r.status === 'skipped').length;
82
+ return { bar: '▰'.repeat(done) + '▱'.repeat(rows.length - done), done, total: rows.length };
83
+ }
84
+ /** Whole-run elapsed (first start → last end), e.g. "84s"; '' before anything ran. */
85
+ export function totalElapsed(rows) {
86
+ const starts = rows.map((r) => r.startedAt).filter((n) => n !== undefined);
87
+ const ends = rows.map((r) => r.endedAt).filter((n) => n !== undefined);
88
+ if (starts.length === 0 || ends.length === 0)
89
+ return '';
90
+ return `${((Math.max(...ends) - Math.min(...starts)) / 1000).toFixed(0)}s`;
91
+ }
@@ -0,0 +1,76 @@
1
+ // code-review workflow (§12.2, T10). Stage COMPOSITION only. A bespoke lean pipeline — NOT the idea
2
+ // S1–S10 stages (findings have no assumption/attack structure): deterministic S1/S3 (no model calls) →
3
+ // S4 reviewers + file:line validator → S8 mutual cross-exam → deterministic ReviewMap → S9 judge → S10
4
+ // report. ~5 model calls. `input` is the unified diff (the CLI computed it via git; §12.2).
5
+ //
6
+ // Artifact order note: the ReviewMap (07) is written BEFORE the cross-exam verifications (08) even though
7
+ // it's derived from them — the artifact writer requires ascending stage ordinals, so S8 returns its data
8
+ // and the workflow orders the two writes.
9
+ import { resolve } from 'node:path';
10
+ import { runStage } from '../orchestration/context.js';
11
+ import { parseDiffFiles } from '../orchestration/git.js';
12
+ import { s4Review } from '../orchestration/stages/cr-s4-review.js';
13
+ import { s8CrossExam } from '../orchestration/stages/cr-s8-crossexam.js';
14
+ import { buildReviewMap } from '../orchestration/stages/cr-map.js';
15
+ import { s9ReviewJudge } from '../orchestration/stages/cr-s9-judge.js';
16
+ import { s10ReviewRender } from '../orchestration/stages/cr-report.js';
17
+ import { loadSkill } from '../orchestration/skills.js';
18
+ /** §12.2 reviewer prompt (per reviewer). S3 fills {{DIFF_PATH}} deterministically (no model call). */
19
+ export const CR_REVIEWER_TEMPLATE = `ROLE: Independent senior code reviewer. You work ALONE. You have READ-ONLY
20
+ access to the repository at your working directory.
21
+
22
+ Review ONLY the changes in the diff at {{DIFF_PATH}} (context: repo root = your cwd). Investigate
23
+ surrounding code as needed before reporting.{{SKILL}}
24
+
25
+ Produce ONLY JSON:
26
+ - task_echo (≤2 sentences),
27
+ - findings: ≤12, each {id "F1"..., file, line_start, line_end, severity P0|P1|P2|P3,
28
+ category CORRECTNESS|SECURITY|CONCURRENCY|ERROR_HANDLING|PERF|MAINTAINABILITY,
29
+ claim, evidence "<the code/behavior that proves it>", suggested_fix, self_confidence 0-1}.
30
+ Rules: severity P0 = correctness/security/data-loss. No style nits below P2.
31
+ Every finding MUST cite a file and line range you verified exists (paths relative to the repo root). JSON only.`;
32
+ /**
33
+ * Fill the reviewer template: {{DIFF_PATH}} → the diff file, {{SKILL}} → the role playbook (or nothing).
34
+ * An empty skill collapses the slot to nothing, so the prompt is byte-for-byte the pre-skill baseline.
35
+ */
36
+ export function buildReviewerPrompt(diffPath, skill) {
37
+ return CR_REVIEWER_TEMPLATE.replace('{{DIFF_PATH}}', diffPath).replace('{{SKILL}}', skill ? `\n\n${skill}` : '');
38
+ }
39
+ /** Timeline manifest (T8) for the code-review pipeline. S7 (map) is pure/deterministic (role null). */
40
+ export const CR_STAGES = [
41
+ { id: 'S4', label: 'Parallel review', role: 's4' },
42
+ { id: 'S8', label: 'Cross-exam', role: 's4' },
43
+ { id: 'S7', label: 'Disagreement map', role: null },
44
+ { id: 'S9', label: 'Judge adjudication', role: 'judge' },
45
+ { id: 'S10', label: 'Report', role: null },
46
+ ];
47
+ export async function runCodeReview(ctx, input) {
48
+ // `input` is the unified diff. Persist it where the reviewer prompt points; parse the touched files.
49
+ await ctx.writer.writeInput('diff.patch', input);
50
+ const diffPath = resolve(ctx.writer.dir, 'inputs', 'diff.patch');
51
+ const files = parseDiffFiles(input);
52
+ // S1 (deterministic, NO call): a trivial contract, for artifact consistency + forensics.
53
+ const contract = {
54
+ task: 'Review the changes in the supplied diff.',
55
+ task_type: 'code-review',
56
+ constraints: [],
57
+ unknowns: [],
58
+ success_criteria: ['adjudicated findings on the diff, with derived confidence'],
59
+ };
60
+ await ctx.writer.writeJson('intent-contract', contract);
61
+ // S3 (deterministic, NO call): fill the reviewer template's slots — DIFF_PATH + the reviewer
62
+ // playbook (skill); persist the assembled prompt for forensics.
63
+ const prompt = buildReviewerPrompt(diffPath, loadSkill('code-review', 'reviewer'));
64
+ await ctx.writer.writePrompt('reviewer.md', prompt);
65
+ const reviewers = await runStage(ctx, 'S4', () => s4Review(ctx, prompt, files));
66
+ const cross = await runStage(ctx, 'S8', () => s8CrossExam(ctx, reviewers));
67
+ // S7 — build + persist the ReviewMap (07), then the cross-exam verifications (08). Order: 07 < 08.
68
+ const map = await runStage(ctx, 'S7', async () => {
69
+ const m = buildReviewMap(reviewers, cross.byKey);
70
+ await ctx.writer.writeJson('review-map', m);
71
+ await ctx.writer.writeJson('verifications', { verifications: cross.verifications });
72
+ return m;
73
+ });
74
+ const judge = await runStage(ctx, 'S9', () => s9ReviewJudge(ctx, map));
75
+ await runStage(ctx, 'S10', () => s10ReviewRender(ctx, map, judge));
76
+ }
@@ -0,0 +1,105 @@
1
+ // idea-refinement workflow (§12.1). Stage COMPOSITION only — no orchestration mechanics (those
2
+ // live in the engine) and, for now, prompts inline here rather than in skills/<workflow>/ (the
3
+ // full skill loader + registry, §11, is deferred; it must not register without bench/ + validate.ts).
4
+ //
5
+ // v1 T5 scope: S1 → S2 → S3. S4–S10 are added as later tasks extend this composition.
6
+ import { resolve } from 'node:path';
7
+ import { runStage } from '../orchestration/context.js';
8
+ import { renderGrilledInput, s0Grill } from '../orchestration/stages/s0-grill.js';
9
+ import { s1Intent } from '../orchestration/stages/s1-intent.js';
10
+ import { s2Misread } from '../orchestration/stages/s2-misread.js';
11
+ import { s3Prompts } from '../orchestration/stages/s3-prompts.js';
12
+ import { s4Analyze } from '../orchestration/stages/s4-analyze.js';
13
+ import { s5Drift } from '../orchestration/stages/s5-drift.js';
14
+ import { s6Claims } from '../orchestration/stages/s6-claims.js';
15
+ import { s7Disagreement } from '../orchestration/stages/s7-disagreement.js';
16
+ import { s8Verify } from '../orchestration/stages/s8-verify.js';
17
+ import { s9Judge } from '../orchestration/stages/s9-judge.js';
18
+ import { s9bPlan } from '../orchestration/stages/s9b-plan.js';
19
+ import { s10Render } from '../orchestration/stages/s10-render.js';
20
+ import { loadSkill } from '../orchestration/skills.js';
21
+ /** §12.1 idea-vetting rubric: 12 mandatory coverage items. S7 flags any item no analyst addressed
22
+ * as a blind spot. Inlined here (like the S4 template) while the skill/`rubric.json` loader (§11)
23
+ * is deferred; it moves to skills/idea-refinement/rubric.json when that loader lands. */
24
+ export const IDEA_RUBRIC = [
25
+ { id: 'R1', label: 'target user / audience', keywords: ['target user', 'audience', 'customer', 'persona'] },
26
+ { id: 'R2', label: 'existing alternatives / competition', keywords: ['existing', 'alternative', 'competitor', 'incumbent'] },
27
+ { id: 'R3', label: 'differentiation / unique value', keywords: ['differentiation', 'unique', 'moat', 'advantage'] },
28
+ { id: 'R4', label: 'feasibility / technical viability', keywords: ['feasibility', 'feasible', 'viable', 'technical'] },
29
+ { id: 'R5', label: 'cost / effort / resources', keywords: ['cost', 'effort', 'budget', 'resource'] },
30
+ { id: 'R6', label: 'policy / legal / compliance risk', keywords: ['policy', 'legal', 'compliance', 'regulatory'] },
31
+ { id: 'R7', label: 'kill criteria / failure conditions', keywords: ['kill criteria', 'failure', 'abandon', 'stop'] },
32
+ { id: 'R8', label: 'business model / monetization', keywords: ['business model', 'monetization', 'revenue', 'pricing'] },
33
+ { id: 'R9', label: 'distribution / go-to-market', keywords: ['distribution', 'market', 'adoption', 'channel'] },
34
+ { id: 'R10', label: 'timing / market readiness', keywords: ['timing', 'readiness', 'trend', 'now'] },
35
+ { id: 'R11', label: 'scalability / growth', keywords: ['scalability', 'scale', 'growth'] },
36
+ { id: 'R12', label: 'key risks / assumptions to validate', keywords: ['risk', 'assumption', 'validate', 'uncertain'] },
37
+ ];
38
+ /** §13 S4 analyst template (idea-refinement). S3 fills its slots; S4 will consume it (T6). */
39
+ export const IDEA_S4_ANALYST_TEMPLATE = `ROLE: Independent analyst on a decision panel. You work ALONE; you will not see
40
+ other analysts' output. Be adversarial toward the idea, not polite.
41
+
42
+ TASK CONTRACT: {{INTENT_CONTRACT_JSON}}
43
+ INPUT DOCUMENT: read the file at {{INPUT_PATH}}{{SKILL}}
44
+
45
+ Produce ONLY JSON matching {{S4_SCHEMA_REF}} with:
46
+ - task_echo: restate the task in ≤2 sentences (drift check).
47
+ - strongest_version: the best honest version of this idea in ≤150 words.
48
+ - assumptions: ≤8, each {id "A1"..., statement, type VERIFIABLE|JUDGMENT, load_bearing bool}.
49
+ - attacks: ≤6, each {id "X1"..., target_assumption, argument, severity HIGH|MED|LOW}.
50
+ Every attack MUST target an assumption id. Unanchored attacks will be discarded.
51
+ - open_questions: ≤5 questions whose answers would change the verdict.
52
+ Rules: no motivation, no summaries of your own output, no markdown, JSON only.`;
53
+ /**
54
+ * Resolve the {{SKILL}} slot in the analyst template BEFORE S3 (S3 is a model call that tailors the
55
+ * template + errors on any leftover {{...}}). An empty skill collapses the slot → exact pre-skill
56
+ * baseline; the S3 deterministic fallback then preserves the embedded playbook verbatim.
57
+ */
58
+ export function buildAnalystTemplate(skill) {
59
+ return IDEA_S4_ANALYST_TEMPLATE.replace('{{SKILL}}', skill ? `\n\n${skill}` : '');
60
+ }
61
+ /** Timeline manifest (T8): the stages in order, each with the provider-role its row displays.
62
+ * The TUI draws the pending skeleton from this and resolves chips from `ctx.roles`. Ids match the
63
+ * `runStage` calls below. S7 shows the judge (it makes the grouping call); S5/S6/S10 are pure (—). */
64
+ export const IDEA_STAGES = [
65
+ { id: 'S0', label: 'Intent preflight', role: 'analyst' },
66
+ { id: 'S1', label: 'Intent contract', role: 'analyst' },
67
+ { id: 'S2', label: 'Misunderstanding guard', role: 'all' },
68
+ { id: 'S3', label: 'Prompt generation', role: 'analyst' },
69
+ { id: 'S4', label: 'Parallel analysis', role: 's4' },
70
+ { id: 'S5', label: 'Drift check', role: null },
71
+ { id: 'S6', label: 'Claim extraction', role: null },
72
+ { id: 'S7', label: 'Disagreement map', role: 'judge' },
73
+ { id: 'S8', label: 'Verifier loop', role: 'verifier' },
74
+ { id: 'S9', label: 'Judge synthesis', role: 'judge' },
75
+ { id: 'S9b', label: 'Validation plan', role: 'judge' },
76
+ { id: 'S10', label: 'Report', role: null },
77
+ ];
78
+ /** Runs the full idea-refinement pipeline S0–S10. Throws on any fatal condition; the engine's
79
+ * `executeRun` wrapper turns that into a graceful failure + meta. Each stage is wrapped in
80
+ * `runStage` so the TUI timeline (T8) gets start/end events; headless, that's a no-op. */
81
+ export async function runIdeaRefinement(ctx, input) {
82
+ const brief = await runStage(ctx, 'S0', () => s0Grill(ctx, input));
83
+ const grilledInput = renderGrilledInput(input, brief);
84
+ const contract = await runStage(ctx, 'S1', () => s1Intent(ctx, grilledInput));
85
+ const guard = await runStage(ctx, 'S2', () => s2Misread(ctx, contract, grilledInput));
86
+ // Persist the input as a file so S4's "read the file at {{INPUT_PATH}}" resolves (not a stage).
87
+ await ctx.writer.writeInput('idea.md', input);
88
+ await ctx.writer.writeInput('idea-brief.md', grilledInput);
89
+ const inputPath = resolve(ctx.writer.dir, 'inputs', 'idea-brief.md');
90
+ const stagePrompts = await runStage(ctx, 'S3', () => s3Prompts(ctx, {
91
+ contract,
92
+ interpretation: guard.chosen.my_interpretation,
93
+ templates: { analyst: buildAnalystTemplate(loadSkill('idea-refinement', 'analyst')) },
94
+ slots: { INPUT_PATH: inputPath, S4_SCHEMA_REF: 'the idea-refinement S4 RoleOutput schema' },
95
+ }));
96
+ // s3Prompts guarantees an entry for every template key (it iterates them), so `analyst` is present.
97
+ const seats = await runStage(ctx, 'S4', () => s4Analyze(ctx, stagePrompts.prompts.analyst));
98
+ const { kept } = await runStage(ctx, 'S5', () => s5Drift(ctx, contract, seats));
99
+ const claimSet = await runStage(ctx, 'S6', () => s6Claims(ctx, kept));
100
+ const map = await runStage(ctx, 'S7', () => s7Disagreement(ctx, claimSet, kept, IDEA_RUBRIC));
101
+ const verifications = await runStage(ctx, 'S8', () => s8Verify(ctx, map));
102
+ const judgeReport = await runStage(ctx, 'S9', () => s9Judge(ctx, contract, map, verifications, IDEA_RUBRIC));
103
+ const actionPlan = await runStage(ctx, 'S9b', () => s9bPlan(ctx, contract, kept, map, judgeReport));
104
+ await runStage(ctx, 'S10', () => s10Render(ctx, { contract, seats: kept, map, verifications, judgeReport, actionPlan, rubric: IDEA_RUBRIC }));
105
+ }
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "aiki-cli",
3
+ "version": "0.2.0",
4
+ "description": "Local-first orchestration CLI binding your installed AI coding CLIs into schema-validated multi-model workflows.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Gaurav Palaspagar",
8
+ "homepage": "https://github.com/kratos619/Aiki#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/kratos619/Aiki.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/kratos619/Aiki/issues"
15
+ },
16
+ "keywords": [
17
+ "cli",
18
+ "llm",
19
+ "orchestration",
20
+ "code-review",
21
+ "multi-model",
22
+ "claude",
23
+ "codex",
24
+ "gemini",
25
+ "local-first"
26
+ ],
27
+ "bin": {
28
+ "aiki": "dist/cli/index.js"
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "CHANGELOG.md",
34
+ "LICENSE"
35
+ ],
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "scripts": {
40
+ "build": "tsc -p tsconfig.json && node -e \"require('fs').copyFileSync('src/providers/profiles.json','dist/providers/profiles.json')\" && node -e \"require('fs').cpSync('src/skills','dist/skills',{recursive:true})\"",
41
+ "typecheck": "tsc -p tsconfig.json --noEmit",
42
+ "test": "vitest run",
43
+ "test:watch": "vitest",
44
+ "prepublishOnly": "npm run build && npm run typecheck && npm test",
45
+ "aiki": "node --loader tsx dist/cli/index.js"
46
+ },
47
+ "dependencies": {
48
+ "commander": "^12.1.0",
49
+ "execa": "^9.5.1",
50
+ "ink": "^5.1.0",
51
+ "ink-spinner": "^5.0.0",
52
+ "ink-text-input": "^6.0.0",
53
+ "pino": "^9.5.0",
54
+ "react": "^18.3.1",
55
+ "zod": "^3.24.1"
56
+ },
57
+ "devDependencies": {
58
+ "@types/node": "^20.17.10",
59
+ "@types/react": "^18.3.18",
60
+ "tsx": "^4.19.2",
61
+ "typescript": "^5.7.2",
62
+ "vitest": "^2.1.8"
63
+ }
64
+ }