Chapter 3: Memory Architecture and Data Model

April 13, 2026 ยท View on GitHub

Welcome to Chapter 3: Memory Architecture and Data Model. In this part of Cipher Tutorial: Shared Memory Layer for Coding Agents, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.

Cipher captures and retrieves coding memory across interactions, including knowledge and reasoning patterns.

Memory Layers

LayerPurpose
knowledge memoryreusable facts and implementation context
reasoning/reflection memoryhigher-order reasoning traces and patterns
workspace memoryteam/project-scoped shared context

Source References

Summary

You now understand the high-level memory model that powers Cipher across agent interactions.

Next: Chapter 4: Configuration, Providers, and Embeddings

Source Code Walkthrough

src/tui/components/init.tsx

The ProcessedMessage interface in src/tui/components/init.tsx handles a key part of this chapter's functionality:

 * Includes action state for spinner display
 */
export interface ProcessedMessage extends StreamingMessage {
  /** For action_start: whether the action is still running (no matching action_stop) */
  isActionRunning?: boolean
  /** For action_start: the completion message from action_stop */
  stopMessage?: string
}

/**
 * Count the total number of lines in streaming messages (simple newline count)
 *
 * @param messages - Array of streaming messages
 * @returns Total number of lines across all messages
 */
function countOutputLines(messages: StreamingMessage[]): number {
  let total = 0
  for (const msg of messages) {
    total += msg.content.split('\n').length
  }

  return total
}

/**
 * Get messages from the end that fit within maxLines, truncating from the beginning
 *
 * @param messages - Array of streaming messages
 * @param maxLines - Maximum number of lines to display
 * @returns Object containing display messages, skipped lines count, and total lines
 */
function getMessagesFromEnd(

This interface is important because it defines how Cipher Tutorial: Shared Memory Layer for Coding Agents implements the patterns covered in this chapter.

src/tui/components/init.tsx

The InitProps interface in src/tui/components/init.tsx handles a key part of this chapter's functionality:

const INLINE_SEARCH_OVERHEAD = 3

export interface InitProps {
  /** Whether the component should be interactive (for EnterPrompt activation) */
  active?: boolean

  /** Auto-start init without waiting for Enter key in idle state */
  autoStart?: boolean

  /** Custom idle state message (optional) */
  idleMessage?: string

  /** Maximum lines available for streaming output */
  maxOutputLines: number

  /** Optional callback when init completes successfully */
  onInitComplete?: () => void

  /** Show idle state message? (default: true for InitView, false for OnboardingFlow) */
  showIdleMessage?: boolean
}

export const Init: React.FC<InitProps> = ({
  active = true,
  autoStart = false,
  idleMessage = 'Your project needs initializing.',
  maxOutputLines,
  onInitComplete,
  showIdleMessage = true,
}) => {
  const {
    theme: {colors},

This interface is important because it defines how Cipher Tutorial: Shared Memory Layer for Coding Agents implements the patterns covered in this chapter.

src/oclif/commands/debug.ts

The Debug class in src/oclif/commands/debug.ts handles a key part of this chapter's functionality:

}

export default class Debug extends Command {
  public static description = 'Live monitor for daemon internal state (development only)'
  public static examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> --format json',
    '<%= config.bin %> <%= command.id %> --once',
  ]
  public static flags = {
    force: Flags.boolean({
      default: false,
      description: 'Kill existing daemon and start fresh',
    }),
    format: Flags.string({
      char: 'f',
      default: 'tree',
      description: 'Output format',
      options: ['tree', 'json'],
    }),
    once: Flags.boolean({
      default: false,
      description: 'Print once and exit (no live monitoring)',
    }),
  }
  public static hidden = !isDevelopment()

  protected clearScreen(): void {
    if (process.stdout.isTTY) {
      process.stdout.write('\u001B[2J\u001B[H')
    }
  }

This class is important because it defines how Cipher Tutorial: Shared Memory Layer for Coding Agents implements the patterns covered in this chapter.

src/oclif/lib/task-client.ts

The formatToolDisplay function in src/oclif/lib/task-client.ts handles a key part of this chapter's functionality:


/**
 * Format tool call for CLI display (simplified version of TUI formatToolDisplay).
 */
export function formatToolDisplay(toolName: string, args: Record<string, unknown>): string {
  switch (toolName.toLowerCase()) {
    case 'bash': {
      const cmd = args.command ? String(args.command) : ''
      return `Bash ${cmd.length > 60 ? `$ ${cmd.slice(0, 57)}...` : `$ ${cmd}`}`
    }

    case 'code_exec': {
      return 'CodeExec'
    }

    case 'edit': {
      const filePath = args.file_path ?? args.filePath
      return filePath ? `Edit ${filePath}` : 'Edit'
    }

    case 'glob': {
      const {path, pattern} = args
      return pattern ? `Glob "${pattern}"${path ? ` in ${path}` : ''}` : 'Glob'
    }

    case 'grep': {
      const {path, pattern} = args
      return pattern ? `Grep "${pattern}"${path ? ` in ${path}` : ''}` : 'Grep'
    }

    case 'read': {
      const filePath = args.file_path ?? args.filePath

This function is important because it defines how Cipher Tutorial: Shared Memory Layer for Coding Agents implements the patterns covered in this chapter.

How These Components Connect

flowchart TD
    A[ProcessedMessage]
    B[InitProps]
    C[Debug]
    D[formatToolDisplay]
    E[waitForTaskCompletion]
    A --> B
    B --> C
    C --> D
    D --> E