+ {activePage.category}
+
- {description && (
-
{description}
- )}
+ ) : null}
- {/* Mobile TOC */}
{sections?.length ? (
-
-
+
+
On this page
@@ -191,7 +159,7 @@ export function DocsShell({
{section.title}
@@ -201,30 +169,22 @@ export function DocsShell({
) : null}
- {/* Content */}
{children}
- {/* Page Navigation */}
- {activePage && (
-
+ {activePage ? (
+
-
-
-
Back to
-
- All Documentation
-
-
+
+ All Documentation
- )}
+ ) : null}
- {/* Table of Contents - Desktop */}
{sections?.length ?
: null}
diff --git a/web/components/memo-hero-remotion.tsx b/web/components/memo-hero-remotion.tsx
index 015d10c1..d7126d72 100644
--- a/web/components/memo-hero-remotion.tsx
+++ b/web/components/memo-hero-remotion.tsx
@@ -1,14 +1,7 @@
'use client'
import { Player } from '@remotion/player'
-import {
- AbsoluteFill,
- Easing,
- interpolate,
- spring,
- useCurrentFrame,
- useVideoConfig,
-} from 'remotion'
+import { AbsoluteFill, useCurrentFrame } from 'remotion'
const FPS = 30
const ACTIVE_FRAMES = 14 * FPS
@@ -17,14 +10,7 @@ const DURATION_IN_FRAMES = ACTIVE_FRAMES + HOLD_FRAMES
const COMPOSITION_WIDTH = 1440
const COMPOSITION_HEIGHT = 900
-const clamp = {
- extrapolateLeft: 'clamp',
- extrapolateRight: 'clamp',
-} as const
-
const welcomeMeta = [
- { label: 'Directory', value: '~/Desktop/workspace/memo-cli' },
- { label: 'Session', value: '7f3bf47d...252a' },
{
label: 'Model',
value: 'deepseek-chat',
@@ -35,55 +21,45 @@ const welcomeMeta = [
]
type ToolEvent = {
+ kind?: 'used' | 'note'
tool: string
args?: string
}
const toolEvents: ToolEvent[] = [
+ { kind: 'note', tool: "I'll examine the project structure to help you understand it better." },
{ tool: 'update_plan' },
{ tool: 'list_dir', args: '.' },
{ tool: 'read_file', args: 'package.json' },
- { tool: 'read_file', args: 'AGENTS.md' },
- { tool: 'exec_command', args: 'pwd' },
- { tool: 'list_dir', args: '/Users/mcell/Desktop/workspace/memo-cli' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/package...' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/AGENTS.md' },
- { tool: 'update_plan' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/tsconfi...' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/README.md' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/pnpm-wo...' },
- { tool: 'update_plan' },
- { tool: 'list_dir', args: '/Users/mcell/Desktop/workspace/memo-cli/packages' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/package...' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/package...' },
+ { tool: 'grep_files', args: 'AGENTS' },
{ tool: 'update_plan' },
- { tool: 'read_file', args: '/Users/mcell/Desktop/workspace/memo-cli/package...' },
- { tool: 'exec_command', args: 'find /Users/mcell/Desktop/workspace/memo-cli -n...' },
+ { tool: 'read_file', args: 'README.md' },
+ { tool: 'read_file', args: 'tsconfig.json' },
+ { tool: 'list_dir', args: 'packages' },
+ { tool: 'read_file', args: 'packages/cli/src/index.tsx' },
+ { tool: 'read_file', args: 'packages/core/src/index.ts' },
{ tool: 'update_plan' },
]
const responseLines = [
- 'Memo Code is a TypeScript CLI coding agent with a monorepo structure:',
+ 'Memo Code is a TypeScript monorepo CLI tool with three main packages:',
'',
- 'Core packages:',
- '- packages/cli: TUI interface with Ink/React',
- '- packages/core: Session state, config, shared types',
- '- packages/tools: Built-in tools + MCP integration',
+ 'Core Structure:',
+ '- packages/cli/: TUI entry point using Ink (React for terminals)',
+ '- packages/core/: Session management, config handling, shared types',
+ '- packages/tools/: Built-in MCP-like tools (exec_command, read_file, etc.)',
'',
- 'Key features:',
- '- Interactive TUI and plain mode for scripts',
- '- DeepSeek/OpenAI providers with config.toml',
- '- MCP server support (local/remote)',
- '- Tool approval system with dangerous mode',
- '- Session history in JSONL format',
+ 'Key Features:',
+ '- Terminal-based coding agent with interactive TUI',
+ '- Supports DeepSeek (default) and OpenAI-compatible APIs',
+ '- Uses MCP (Model Context Protocol) for tool integration',
+ '- Monorepo with pnpm workspace, TypeScript ESM',
'',
'Development:',
- '- Node.js >=18, pnpm workspace',
- '- TypeScript + ESM, Prettier formatting',
- '- Vitest tests next to source files',
- '- Build outputs to dist/index.js',
- '',
- 'The project follows clear boundaries: Core (logic), Tools (capabilities), CLI (UI).',
+ '- Node.js ≥18, pnpm for package management',
+ '- Build with pnpm run build, test with pnpm test',
+ '- Config stored in ~/.memo/config.toml',
+ '- Runtime logs in ~/.memo/',
]
const questionPrompt = 'I want to quickly understand the project so as to develop it better.'
@@ -97,16 +73,10 @@ const typewriter = (text: string, frame: number, startFrame: number, charsPerSte
return text.slice(0, Math.min(text.length, typedChars))
}
-const reveal = (frame: number, startFrame: number, duration = 12) => {
- return interpolate(frame, [startFrame, startFrame + duration], [0, 1], {
- ...clamp,
- easing: Easing.out(Easing.quad),
- })
-}
+const showAt = (frame: number, startFrame: number) => (frame >= startFrame ? 1 : 0)
const MemoHeroComposition = () => {
const frame = useCurrentFrame()
- const { fps } = useVideoConfig()
const playFrame = Math.min(frame, ACTIVE_FRAMES - 1)
const commandStart = 20
const commandCharsPerStep = 3
@@ -119,24 +89,13 @@ const MemoHeroComposition = () => {
const responseStart = toolsStart + toolEvents.length * toolStagger + 18
const finalPromptStart = responseStart + 12
- const entrance = spring({
- frame: playFrame - 4,
- fps,
- config: { damping: 200 },
- durationInFrames: Math.round(0.9 * fps),
- })
-
- const windowOpacity = interpolate(entrance, [0, 1], [0, 1], clamp)
- const windowTranslateY = interpolate(entrance, [0, 1], [36, 0], clamp)
- const windowScale = interpolate(entrance, [0, 1], [0.97, 1], clamp)
-
const commandText = typewriter('memo', playFrame, commandStart, commandCharsPerStep)
const questionText = typewriter(questionPrompt, playFrame, questionStart, questionCharsPerStep)
- const welcomeBlockOpacity = reveal(playFrame, 52, 8)
+ const welcomeBlockOpacity = showAt(playFrame, 52)
const showCommandCursor = playFrame >= commandStart && playFrame < commandDoneFrame
const showQuestionCursor = playFrame >= questionStart && playFrame < questionDoneFrame
- const cursorOpacity = interpolate(playFrame % 26, [0, 13, 26], [1, 0.2, 1], clamp)
+ const cursorOpacity = playFrame % 26 < 13 ? 1 : 0.2
return (
@@ -145,11 +104,8 @@ const MemoHeroComposition = () => {
flex: 1,
borderRadius: 16,
overflow: 'hidden',
- border: '1px solid rgba(140, 148, 255, 0.35)',
- backgroundColor: '#0d1117',
- boxShadow: 'inset 0 0 50px rgba(94, 106, 210, 0.08)',
- opacity: windowOpacity,
- transform: `translateY(${windowTranslateY}px) scale(${windowScale})`,
+ opacity: 1,
+ transform: 'none',
}}
>
{
padding: '18px 22px',
fontFamily:
'"JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo, monospace',
- fontSize: 11,
- lineHeight: 1.16,
+ fontSize: 13,
+ lineHeight: 1.24,
color: '#e5e7eb',
whiteSpace: 'pre',
letterSpacing: 0.2,
@@ -233,8 +189,8 @@ const MemoHeroComposition = () => {
{
style={{
color: '#a1a1aa',
display: 'inline-block',
- width: 70,
+ width: 92,
}}
>
{item.label}:
@@ -273,7 +229,7 @@ const MemoHeroComposition = () => {
@@ -288,24 +244,35 @@ const MemoHeroComposition = () => {
- ●
- Used
- {item.tool}
- {item.args ? (
+ {item.kind === 'note' ? (
+ <>
+ ●
+ {item.tool}
+ >
+ ) : (
<>
- (
- {item.args}
- )
+ ●
+ Used
+ {item.tool}
+ {item.args ? (
+ <>
+ (
+
+ {item.args}
+
+ )
+ >
+ ) : null}
>
- ) : null}
+ )}
))}
-
+
{responseLines.map((line, index) => {
const isHeading = line.endsWith(':') && !line.startsWith('-')
const isBullet = line.startsWith('-')
@@ -330,7 +297,7 @@ const MemoHeroComposition = () => {
diff --git a/web/components/site-header.tsx b/web/components/site-header.tsx
index 0e39382d..f6a23baf 100644
--- a/web/components/site-header.tsx
+++ b/web/components/site-header.tsx
@@ -5,7 +5,7 @@ import { Github, Package, Menu, X, BookOpen } from 'lucide-react'
import Link from 'next/link'
import { useState } from 'react'
-const GITHUB_URL = 'https://github.com/minorcell/memo-cli'
+const GITHUB_URL = 'https://github.com/minorcell/memo-code'
const NPM_URL = 'https://www.npmjs.com/package/@memo-code/memo'
const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? ''
@@ -15,14 +15,14 @@ export function SiteHeader() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
return (
-
+
-