Add snippet/command library with CRUD and send-to-session

Full command snippet library for saving and sending reusable commands:

Backend:
- SQLite migration 003 creates snippets table
- Snippet model with name, command, description, folder, tags
- Store CRUD methods and API endpoints

Frontend:
- SnippetLibrary class with searchable list + detail/editor split view
- Create, edit, delete snippets in modal dialog
- 'Send to Session' button writes command to active terminal
- 'Send Snippet' option in terminal right-click context menu
- Ctrl+Shift+S keyboard shortcut to open library
This commit is contained in:
2026-04-17 00:00:00 +01:00
parent 9cf2010c70
commit b6d77e485c
11 changed files with 544 additions and 1 deletions
+48
View File
@@ -574,6 +574,54 @@ func (s *Service) ListAuditEntries(limit int) ([]models.AuditEntry, error) {
return result, nil
}
// ---------------------------------------------------------------------------
// Snippets (command library)
// ---------------------------------------------------------------------------
// ListSnippets returns all saved command snippets.
func (s *Service) ListSnippets() ([]models.Snippet, error) {
snippets, err := s.store.ListSnippets()
if err != nil {
return nil, err
}
result := make([]models.Snippet, len(snippets))
for i, sn := range snippets {
result[i] = *sn
}
return result, nil
}
// CreateSnippet saves a new command snippet.
func (s *Service) CreateSnippet(snippet models.Snippet) (models.Snippet, error) {
if snippet.ID == "" {
snippet.ID = uuid.New().String()
}
now := time.Now()
snippet.CreatedAt = now
snippet.UpdatedAt = now
if snippet.Tags == nil {
snippet.Tags = []string{}
}
if err := s.store.CreateSnippet(&snippet); err != nil {
return models.Snippet{}, fmt.Errorf("failed to create snippet: %w", err)
}
return snippet, nil
}
// UpdateSnippet updates an existing command snippet.
func (s *Service) UpdateSnippet(snippet models.Snippet) (models.Snippet, error) {
snippet.UpdatedAt = time.Now()
if err := s.store.UpdateSnippet(&snippet); err != nil {
return models.Snippet{}, fmt.Errorf("failed to update snippet: %w", err)
}
return snippet, nil
}
// DeleteSnippet removes a command snippet by ID.
func (s *Service) DeleteSnippet(id string) error {
return s.store.DeleteSnippet(id)
}
// ---------------------------------------------------------------------------
// Utility
// ---------------------------------------------------------------------------