Skip to main content
Glama

session_handoff

Capture and restore development session context by automatically recording git state, completed tasks, next steps, and blockers for continuity between work sessions.

Instructions

Write a session handoff primer that auto-captures git state (branch, last 5 commits, modified files), last completed task, next step, and blockers. The next session reads this automatically for seamless context continuity.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
lastTaskNoWhat was completed this session
nextStepNoExact next action for the next session
blockersNoOpen blockers or unresolved issues
openFilesNoKey files being worked on
projectNoProject name (auto-detected from cwd if omitted)
customContextNoAny additional context for the next session

Implementation Reference

  • The actual implementation of the 'session_handoff' tool logic, which captures git state and writes a primer.json file for session continuity.
    function writeSessionHandoff({ project, branch, lastTask, nextStep, blockers, openFiles, customContext } = {}) {
      ensureDir(path.join(CONTEXTFS_ROOT, NAMESPACES.session));
    
      let gitContext = {};
      try {
        const { execSync } = require('child_process');
        const cwd = process.cwd();
        gitContext = {
          branch: branch || execSync('git rev-parse --abbrev-ref HEAD', { cwd, encoding: 'utf8' }).trim(),
          lastCommits: execSync('git log --oneline -5', { cwd, encoding: 'utf8' }).trim().split('\n'),
          modifiedFiles: execSync('git diff --name-only HEAD~1 2>/dev/null || echo ""', { cwd, encoding: 'utf8' }).trim().split('\n').filter(Boolean),
          status: execSync('git status --short', { cwd, encoding: 'utf8' }).trim().split('\n').filter(Boolean),
        };
      } catch (_) {
        gitContext = { branch: branch || 'unknown', lastCommits: [], modifiedFiles: [], status: [] };
      }
    
      const primer = {
        id: `session_${Date.now()}_${crypto.randomBytes(3).toString('hex')}`,
        timestamp: nowIso(),
        project: project || path.basename(process.cwd()),
        git: gitContext,
        lastTask: lastTask || null,
        nextStep: nextStep || null,
        blockers: Array.isArray(blockers) ? blockers : (blockers ? [blockers] : []),
        openFiles: Array.isArray(openFiles) ? openFiles : [],
        customContext: customContext || null,
      };
    
      const primerPath = path.join(CONTEXTFS_ROOT, NAMESPACES.session, 'primer.json');
      fs.writeFileSync(primerPath, JSON.stringify(primer, null, 2));
    
      // Sync to primer.md if it exists
      const mdPrimerPath = path.join(process.cwd(), 'primer.md');
      if (fs.existsSync(mdPrimerPath)) {
        try {
          let md = fs.readFileSync(mdPrimerPath, 'utf8');
          if (primer.lastTask) {
            md = md.replace(/## Last Completed Task\n- .*/, `## Last Completed Task\n- ${primer.lastTask}`);
          }
          if (primer.nextStep) {
            md = md.replace(/## Exact Next Step\n- .*/, `## Exact Next Step\n- ${primer.nextStep}`);
          }
          if (primer.blockers.length > 0) {
            md = md.replace(/## Open Blockers\n(?:- .*\n)*/, `## Open Blockers\n${primer.blockers.map(b => `- ${b}`).join('\n')}\n`);
          }
          fs.writeFileSync(mdPrimerPath, md);
          
          // Trigger full memory refresh (Layer 3, 4, 5)
          const { execSync } = require('child_process');
          execSync('./bin/memory.sh', { stdio: 'ignore' });
        } catch (e) {
          console.error('Warning: Failed to sync to primer.md:', e.message);
        }
      }
    
      recordProvenance({
        action: 'session_handoff',
        source: 'session',
        detail: `Handoff: ${primer.lastTask || 'no task'} → ${primer.nextStep || 'no next step'}`,
      });
    
      return primer;
    }
  • Registration of the 'session_handoff' tool, including its schema and description.
    destructiveTool({
      name: 'session_handoff',
      description: 'Write a session handoff primer that auto-captures git state (branch, last 5 commits, modified files), last completed task, next step, and blockers. The next session reads this automatically for seamless context continuity.',
      inputSchema: {
        type: 'object',
        properties: {
          lastTask: { type: 'string', description: 'What was completed this session' },
          nextStep: { type: 'string', description: 'Exact next action for the next session' },
          blockers: { type: 'array', items: { type: 'string' }, description: 'Open blockers or unresolved issues' },
          openFiles: { type: 'array', items: { type: 'string' }, description: 'Key files being worked on' },
          project: { type: 'string', description: 'Project name (auto-detected from cwd if omitted)' },
          customContext: { type: 'string', description: 'Any additional context for the next session' },
        },
  • MCP tool dispatch logic calling the writeSessionHandoff handler.
    case 'session_handoff':
      return toTextResult(writeSessionHandoff(args));

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/IgorGanapolsky/mcp-memory-gateway'

If you have feedback or need assistance with the MCP directory API, please join our Discord server