SkillAgentSearch skills...

trackit_history

Lightweight modular logger for Dart and Flutter

Install / Use

npx skills add unger1984/trackit

Installs into whichever agent you are using.

About this skill
📐

Cursor Rules

Cursor IDE rules (v2)

Quality Score

64/100

Supported Platforms

Cursor

Our assessment of trackit_history

trackit_history scores 64/100 on our quality scale, 3960th of 4,614 Development & Engineering skills we index.

Its Cursor Rules is 16 KB long, well organised into 51 sections with 41 code examples: a thorough specification that gives an agent plenty to work with.

It has no GitHub stars yet, so there is no community track record; judge it on its content.

Substance
30/30
Structure
20/20
Description
8/15
Adoption
0/20
Freshness
5/15

Maintenance, license and trust

  • We could not determine when the repository was last updated.
  • Our last check on 2026-10-20 found the source still online.
  • No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
  • Its trust signals score 68/100, with 3 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.

AI review by kimi-k2.7-code on 2026-09-25. Automated pattern scan on 2026-09-24. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

trackit_history compared with similar skills

All 4 of these similar skills score higher than trackit_history; compare them before choosing.

SkillScoreStarsUpdatedFormat
trackit_history (this skill)by unger1984640—Cursor Rules
taste-skillby Leonxlnx100111.0k1d agoCLAUDE.md
ai-job-searchby ai-job-search-dev10070.0ktodayCLAUDE.md
claude-howtoby luongnv8910046.6k3d agoCLAUDE.md
lobehubby lobehub10084.2ktodayMCP Server

Frequently asked questions

How do I install trackit_history?
Run npx skills add unger1984/trackit. The install tabs above show the steps for each supported agent.
Which AI agents does trackit_history work with?
It is written for Cursor, as a Cursor Rules file. Other agents that read the same format can often use it too.
Is trackit_history safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It declares no license and scores 68/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is trackit_history still maintained?
We could not determine when the repository was last updated.

TrackIt History Package — Правила разработки

О пакете

trackit_history — модуль-расширение для хранения логов в памяти. Подписывается на поток событий из базового trackit и сохраняет их в FIFO очереди с ограничением по размеру.

Архитектурные паттерны

Singleton Pattern

Глобальное хранилище истории как singleton:

class TrackitHistory {
  factory TrackitHistory() => _instance;

  TrackitHistory._internal();

  static final TrackitHistory _instance = TrackitHistory._internal();

  final TrackitHistoryList _history = [];
  int _maxSize = 1000;
}

Правила:

  • Factory конструктор для доступа к единственному экземпляру
  • Приватный конструктор _internal()
  • Статическое поле _instance с eager initialization
  • Приватные поля для хранения состояния

FIFO Queue Pattern

Очередь с автоматическим удалением старых элементов:

void add(LogEvent event) {
  _history.add(event);
  
  while (_history.length > _maxSize) {
    _history.removeAt(0); // Удаление самого старого
  }
}

Правила:

  • Добавление в конец списка (add)
  • Удаление из начала списка (removeAt(0))
  • Проверка размера после каждого добавления
  • Использовать while, не if для корректной обработки изменения maxSize

Immutable Access Pattern

Защита от внешних изменений:

TrackitHistoryList get history => List.unmodifiable(_history);

Правила:

  • Возвращать List.unmodifiable() для предотвращения изменений
  • Внутреннее хранилище остается приватным
  • Все изменения только через публичные методы класса

Структура класса

TrackitHistory (Singleton)

class TrackitHistory {
  factory TrackitHistory() => _instance;

  TrackitHistory._internal();

  static final TrackitHistory _instance = TrackitHistory._internal();

  final TrackitHistoryList _history = [];
  int _maxSize = 1000;

  /// Добавляет событие в историю
  void add(LogEvent event) {
    _history.add(event);
    while (_history.length > _maxSize) {
      _history.removeAt(0);
    }
  }

  /// Возвращает неизменяемую копию истории
  TrackitHistoryList get history => List.unmodifiable(_history);

  /// Устанавливает максимальный размер истории
  void setMaxSize(int size) {
    _maxSize = size;
    while (_history.length > _maxSize) {
      _history.removeAt(0);
    }
  }

  /// Очищает всю историю
  void clear() {
    _history.clear();
  }
}

Ответственность:

  • Хранение событий в памяти
  • Управление размером истории
  • Предоставление доступа к истории

TrackitHistoryList (Type Alias)

typedef TrackitHistoryList = List<LogEvent>;

Правила:

  • Простой type alias для ясности API
  • Используется для возвращаемых значений
  • Подчеркивает назначение списка

API дизайн

Добавление событий

void add(LogEvent event)

Правила:

  • Единственный параметр — LogEvent
  • Void return type (side effect)
  • Автоматически управляет размером
  • Синхронный метод

Доступ к истории

TrackitHistoryList get history

Правила:

  • Геттер, не метод
  • Возвращает неизменяемый список
  • O(n) операция (создается новый список)
  • Не кешировать результат на стороне клиента

Установка максимального размера

void setMaxSize(int size)

Правила:

  • Положительное целое число
  • Применяется немедленно (удаляет лишние элементы)
  • Может уменьшить текущую историю
  • Default значение: 1000

Очистка истории

void clear()

Правила:

  • Удаляет все события
  • Не изменяет maxSize
  • Используется для reset состояния
  • Полезно для тестов и hot reload

Управление памятью

Ограничение размера

Default значение:

int _maxSize = 1000;

Правила:

  • По умолчанию 1000 событий
  • Можно изменить через setMaxSize()
  • Рассчитывать потребление памяти: ~1000 событий ≈ 100-500 KB
  • Для long-running приложений рекомендуется ограничивать размер

Автоматическая очистка

while (_history.length > _maxSize) {
  _history.removeAt(0);
}

Правила:

  • Очистка происходит при добавлении нового события
  • Удаляются самые старые события (FIFO)
  • Использовать while, не if (корректно обрабатывает уменьшение maxSize)
  • O(n) сложность при удалении (допустимо для небольших n)

Оптимизация производительности

Для больших историй:

// Рассмотреть использование Queue вместо List
import 'dart:collection';

final Queue<LogEvent> _history = Queue();

void add(LogEvent event) {
  _history.add(event);
  while (_history.length > _maxSize) {
    _history.removeFirst(); // O(1) вместо O(n)
  }
}

Правила:

  • Для maxSize > 10000 рассмотреть Queue
  • removeFirst() в Queue — O(1) vs removeAt(0) в List — O(n)
  • Компромисс: Queue требует больше памяти

Использование

Базовое использование

import 'package:trackit/trackit.dart';
import 'package:trackit_history/trackit_history.dart';

void main() {
  // Подключение хранилища истории
  Trackit().listen((event) {
    TrackitHistory().add(event);
  });
  
  // Создание логгера
  final log = Trackit.create('MyApp');
  
  // Логирование
  log.info('Event 1');
  log.info('Event 2');
  
  // Доступ к истории
  final history = TrackitHistory().history;
  print('Total events: ${history.length}');
}

Упрощенная подписка

// Короткая форма
Trackit().listen(TrackitHistory().add);

С ограничением размера

void main() {
  // Установка максимального размера
  TrackitHistory().setMaxSize(500);
  
  // Подключение
  Trackit().listen(TrackitHistory().add);
}

Фильтрация событий

// Сохранять только ошибки
Trackit().listen((event) {
  if (event.level is LogLevelError || event.level is LogLevelFatal) {
    TrackitHistory().add(event);
  }
});

Периодическая очистка

// Очищать историю каждый час
Timer.periodic(Duration(hours: 1), (_) {
  TrackitHistory().clear();
});

Доступ к истории

Получение всех событий

final allEvents = TrackitHistory().history;

Фильтрация по уровню

final errors = TrackitHistory()
    .history
    .where((e) => e.level is LogLevelError)
    .toList();

Фильтрация по времени

final lastHour = DateTime.now().subtract(Duration(hours: 1));
final recentEvents = TrackitHistory()
    .history
    .where((e) => e.time != null && e.time!.isAfter(lastHour))
    .toList();

Фильтрация по title

final serviceEvents = TrackitHistory()
    .history
    .where((e) => e.title == 'MyService')
    .toList();

Сортировка

// По времени (по возрастанию)
final sorted = TrackitHistory()
    .history
    .sorted((a, b) => a.compareTo(b));

// По времени (по убыванию)
final reversed = TrackitHistory()
    .history
    .sorted((a, b) => b.compareTo(a));

Последние N событий

final last10 = TrackitHistory()
    .history
    .reversed
    .take(10)
    .toList();

Интеграция с UI

Flutter: Отображение истории логов

class LogHistoryScreen extends StatelessWidget {
  const LogHistoryScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final history = TrackitHistory().history.reversed.toList();
    
    return ListView.builder(
      itemCount: history.length,
      itemBuilder: (context, index) {
        final event = history[index];
        return ListTile(
          leading: Icon(_getIconForLevel(event.level)),
          title: Text(event.message),
          subtitle: Text('${event.title} • ${event.time}'),
        );
      },
    );
  }
}

Реактивное обновление

class LogHistoryProvider extends ChangeNotifier {
  List<LogEvent> get history => TrackitHistory().history;
  
  void _updateHistory(LogEvent event) {
    TrackitHistory().add(event);
    notifyListeners();
  }
  
  void init() {
    Trackit().listen(_updateHistory);
  }
}

Stream для UI

// Создать Stream для реактивного UI
Stream<TrackitHistoryList> get historyStream async* {
  await for (final _ in Trackit()) {
    yield TrackitHistory().history;
  }
}

Экспорт истории

В JSON

String exportToJson() {
  final history = TrackitHistory().history;
  final json = history.map((event) => {
    'level': event.level.toString(),
    'title': event.title,
    'message': event.message,
    'time': event.time?.toIso8601String(),
    'exception': event.exception?.toString(),
    'stackTrace': event.stackTrace?.toString(),
  }).toList();
  
  return jsonEncode(json);
}

В текстовый файл

Future<void> exportToFile(String path) async {
  final history = TrackitHistory().history;
  final buffer = StringBuffer();
  
  for (final event in history) {
    buffer.writeln('[${event.level}] ${event.time} - ${event.title}');
    buffer.writeln('  ${event.message}');
    if (event.exception != null) {
      buffer.writeln('  Exception: ${event.exception}');
    }
    buffer.writeln();
  }
  
  final file = File(path);
  await file.writeAsString(buffer.toString());
}

Зависимости

dependencies:
  trackit: ^0.1.0  # Базовый пакет
  meta: ^1.15.0

dev_dependencies:
  lints: ^5.0.0
  test: ^1.25.8

Правила:

  • Зависимость от базового trackit
  • Никаких других runtime зависимостей
  • Чистый Dart код без platform-specific логики

Тестирование

Что тестировать

  • Добавление событий в историю
  • Ограничение по размеру (FIFO)
  • Изменение maxSize с удалением лишних элементов
  • Очистка истории
  • Неизменяемость возвращаемого списка
  • Singleton поведение

Пример теста

import 'package:test/test.dart';
import 'package:trackit/trackit.dart';
import 'package:trackit_history/trackit_history.dart';

void main() {
  setUp(() {
    TrackitHistory().clear();
  });

  group('TrackitHistory', () {
    test('should add events to history', () {
      final event = LogEvent(
        level: const LogLevel.info(),
        title: 'Test',
        message: 'Test message',
      );
      
      TrackitHistory().add(event);
      
      expect(TrackitHistory().history.length, equals(1));
      expect(TrackitHistory().history.first, equals(event));
    });

    test('should limit history size', () {
      TrackitHistory().setMaxSize(3);
      
      for (var i = 0; i < 5; i++) {
        TrackitHistory().add(LogEvent(
          level: const LogLevel.info(),
          title: 'Test',
          message: 'Message $i',
        ));
      }
      
      expect(TrackitHistory().history.length, equals(3));
      expect(TrackitHistory().history.last.message, equals('Message 4'));
      expect(TrackitHistory().history.first.message, equals('Message 2'));
    });

    test('should clear history', () {
      TrackitHistory().add(LogEvent(
        level: const LogLevel.info(),
        title: 'Test',
        message: 'Test',
      ));
      
      expect(TrackitHistory().history.length, equals(1));
      
      TrackitHistory().clear();
      
      expect(TrackitHistory().history.length, equals(0));
    });

    test('should return unmodifiable list', () {
      final history = TrackitHistory().history;
      
      expect(
        () => history.add(LogEvent(
          level: const LogLevel.info(),
          title: 'Test',
          message: 'Test',
        )),
        throwsUnsupportedError,
      );
    });

    test('should be singleton', () {
      final instance1 = TrackitHistory();
      final instance2 = TrackitHistory();
      
      expect(identical(instance1, instance2), isTrue);
    });
  });
}

Best Practices

  1. Установить разумный maxSize: Для production рекомендуется 500-2000 событий в зависимости от частоты логирования
  2. Фильтровать перед добавлением: Для экономии памяти фильтровать события по уровню или источнику
  3. Периодическая очистка: Для long-running приложений настроить автоматическую очистку
  4. Не злоупотреблять доступом: Геттер history создает новый список — кешировать результат если нужно
  5. Использовать для отладки: В production отключать или ограничивать размер для экономии памяти

Антипаттерны

❌ **Хранение

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars0
CategoryDevelopment
UpdatedNaNy ago
Forks0

Trust signals

68/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

2 medium1 low