Skip to content

feat(cli,core): M2 — CLI MVP + settings.json + permissions matcher + credentials#2

Merged
oratis merged 1 commit into
mainfrom
feat/m2-cli-mvp
May 27, 2026
Merged

feat(cli,core): M2 — CLI MVP + settings.json + permissions matcher + credentials#2
oratis merged 1 commit into
mainfrom
feat/m2-cli-mvp

Conversation

@oratis

@oratis oratis commented May 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • Implements DEVELOPMENT_PLAN.md §6 M2 core scope: settings.json 3-layer loader, permission matcher with 4 pattern types, Keychain+file credentials, CLI onboarding, REPL, 14 slash commands, trust store.
  • Also includes the CI fix needed after M1's first run failed on `pnpm/action-setup@v4` version mismatch.
  • 151 tests across all packages (110 core + 41 CLI, 4 skipped on ripgrep-less hosts, 0 failed).

Test plan

  • `pnpm typecheck` → green (tsc -b)
  • `pnpm build` → all dist/ artifacts emitted
  • `pnpm test` → 151 passed / 4 skipped / 0 failed
  • `pnpm format:check` → conformant
  • CLI smoke:
    • `node apps/cli/dist/cli.js --version` → 0.1.0
    • `--help` → full usage
    • `doctor` → env summary
    • `--nope` → unknown-flag error, exit 2

CI will validate ripgrep-dependent grep tests (skipped locally).

Documentation

  • New: `docs/cli-flags.md` (27 flags with milestone status)
  • New: `docs/milestones/M2.md` (delivery report)
  • `docs/core-api.md` (M1) still accurate

Release notes label

  • `release-notes:feature` — major new surface (CLI + config + permissions)

What's NOT in this PR

Parser accepts but enforcement deferred to M3+ subsystems:

  • Trust dialog UX prompt (persistence shipped; prompt needs M3 `` injector)
  • apiKeyHelper 401-refresh-loop (M3 harness event loop)
  • 16 of 30 slash commands (each needs its subsystem)
  • `--allowedTools` / `--disallowedTools` enforcement (M3 tool dispatcher)
  • `--system-prompt` threading in REPL (M3)
  • Headless `-p` mode (M8 whole subsystem)
  • `--resume` interactive picker (M3)

Design notes flagged for review

  1. Argv parser is dependency-free — ~200 lines beats yargs/commander's ~3MB.
  2. `promptHidden()` uses `★` mask (not `*`) — visually distinguishable from real key chars.
  3. Slash commands return `string[]` (pure functions over context) — trivially testable, REPL is sole writer.
  4. `TrustStore` separate from `CredentialsStore` — different concerns (per-dir authorization vs per-install secret).
  5. No `/login` in M2 — re-onboarding (via clearing creds + restart) is supported re-auth path until M3's OAuth flow.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

…credentials

Implements DEVELOPMENT_PLAN.md §6 M2 core scope. Adds CI fix from M1's first
run-failure.

What ships
----------
Core (packages/core/src/):
- config/types.ts         — full ~50-field DeepCodeSettings schema
- config/loader.ts        — 3-layer load/merge (user → project → local)
- config/permissions.ts   — 4 rule pattern types (bare / subcommand `:*` /
                            prefix ` *` / domain `domain:`); precedence
                            deny > ask > allow
- credentials/index.ts    — Keychain (macOS) + chmod-600 file fallback;
                            dual header (apiKey / authToken); apiKeyHelper
                            shell-resolver

CLI (apps/cli/src/):
- parse-args.ts           — dependency-free argv parser, 27 flags
- commands.ts             — 14 slash commands + registry (/help /clear /exit
                            /status /model /mode /effort /cost /context
                            /config /add-dir /resume /init /todos)
- repl.ts                 — readline-based REPL, agent dispatch, event render
- onboarding.ts           — hidden-input API key prompt (★ mask, raw mode)
- trust.ts                — ~/.deepcode/trusted-dirs.json persistence
- cli.ts                  — bin entry: flag dispatch → onboarding/REPL/doctor

CI:
- .github/workflows/ci.yml — remove `version: 9` (conflicted with package.json's
                            packageManager field, made setup-pnpm fail on
                            ubuntu runner)

Tests
-----
- packages/core/src/config/loader.test.ts       (8 tests)
- packages/core/src/config/permissions.test.ts  (25 tests, all 4 pattern types)
- packages/core/src/credentials/index.test.ts   (11 tests, file backend)
- apps/cli/src/parse-args.test.ts               (14 tests)
- apps/cli/src/commands.test.ts                 (13 tests)
- apps/cli/src/trust.test.ts                    (5 tests)

Total: 151 passed / 4 skipped (ripgrep-deps) / 0 failed across all packages.

Smoke (apps/cli/dist/cli.js):
- --version → 0.1.0
- --help    → full usage
- doctor    → environment summary
- --nope    → 'Unknown or invalid flags' + exit 2

Docs
----
- docs/cli-flags.md      — every flag with milestone status
- docs/milestones/M2.md  — delivery report + design decisions + what's deferred

Deferred to M3+
---------------
Trust-dialog UX prompt, apiKeyHelper 401-refresh-loop, 16 of 30 slash commands,
--allowedTools enforcement, --system-prompt threading, headless -p mode,
--resume interactive picker. All have parser-level acceptance — enforcement
arrives with their owning subsystem.

Verified
--------
  pnpm typecheck    → green (tsc -b project references)
  pnpm build        → all packages emit dist/
  pnpm test         → 151 passed
  pnpm format:check → all conformant
  node apps/cli/dist/cli.js --version → 0.1.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@oratis oratis merged commit a592ab4 into main May 27, 2026
1 of 2 checks passed
@oratis oratis deleted the feat/m2-cli-mvp branch May 27, 2026 16:23
oratis added a commit that referenced this pull request May 28, 2026
)

Aligns the desktop client to docs/VISUAL_DESIGN.html. Phase 1 covers
the three highest-traffic surfaces — Onboarding, Sidebar (Sessions),
and the main Chat/REPL — built on a shared design system. The
remaining 6 screens ship in 0.1.2 (P2).

**Version bumps (everywhere consistent now):**
- tauri.conf.json 0.1.0 → 0.1.1
- apps/desktop/package.json 0.1.0 → 0.1.1
- apps/cli/package.json 0.1.0 → 0.1.1
- src-tauri/Cargo.toml 0.1.0 → 0.1.1
- CHANGELOG.md added

**Design tokens (apps/desktop/src/index.css):**
- DeepSeek brand blue (#4D6BFE) + soft (#E8EDFF) + mint (#14E4A2)
- Dark-mode 4-tier surface (--bg-0/1/2/3) + 4-tier text + line/line-soft
- --radius-sm/--radius/--radius-lg + spec --shadow
- Inter + JetBrains Mono via @import (matches design)
- ~700 lines replacing the old hand-rolled utility classes from M6

**Primitives (apps/desktop/src/components/):**
- BrandMark — elephant SVG in gradient .mark / .mark-lg container
- Badge — ok / warn / err / info (matches design tool-card statuses)
- Pill — chat-header status chips with optional leading dot
- ToolCard — head (▸ name · target · badge) + body (mono, scrollable,
  diff-add / diff-del color)
- InspectorRail — 48 px right column with 6 rail buttons

**3-column shell (App.tsx rewrite):**
- Grid: 240 px sidebar | 1fr main | 48 px inspector rail
- Onboarding bypasses shell (standalone hero per design screen #2)
- Sidebar lists sessions bucketed by Today/Yesterday/Earlier with
  active state highlight and relative-time meta column
- Inspector rail surfaces Plan badge, context fill, files, info,
  settings (expand panel deferred to P2)

**Chat redesign (Repl.tsx rewrite):**
- chat-header with crumb + 3 status pills (connected · model · approval)
- chat-stream renders msg.user / msg.assistant rows with 28 px avatars
  (YO for user, DC gradient for assistant)
- Tool calls appear inline as ToolCard components with status badge
  reflecting running / done / error
- Inline approval (Approve / Reject / Always allow) sits IMMEDIATELY
  under the relevant tool card per spec note ③ (not at screen bottom)
- composer is the design's .box + .toolbar: + button · mode badge
  (clickable to cycle default→plan→bypass) · vim chip (when on) ·
  model picker (clickable to toggle chat ↔ reasoner) · effort dropdown
  · send button. Below: ctx-bar with token usage + cost estimate
- Streaming cursor (.streaming-cursor) appears at end of assistant text
  while turn is active

**Onboarding redesign:**
- Standalone hero: radial-gradient bg, big brand chip, gradient-text
  headline matching design screen #2
- Form panel with .input style + helper link to platform.deepseek.com
  + Continue button with loading spinner

**Conversation fix carries forward:**
- dangerouslyAllowBrowser: true is bundled in the new Vite output
  (verified via grep on dist/assets)
- Version bump to 0.1.1 lets users definitively verify they installed
  the new build via the About screen

All workspaces typecheck clean. 533+ tests pass. Bundle is 673 KB
(vs. 660 KB before — added ~13 KB for the new components + tokens).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant