@README.md
TinkerTasker is broken up into two main components:
ai-core: Contains the core AI functionality, including the MCP servers for filesystem and web.
This is the pyproject.toml for the package
@./ai-core/pyproject.toml
cli-ux: Provides the command-line interface for interacting with TinkerTasker.
This is the pyproject.toml for the package
@./cli-ux/pyproject.toml
- KISS principle taken to heart: Keep everything as simple as possible, but no simpler
- Minimize abstractions: Every layer of abstraction must justify its existence
- Start minimal, grow as needed: Begin with the simplest implementation that meets current needs
- Avoid future-proofing: Don't build for hypothetical future requirements
- Question everything: Regularly challenge complexity in the codebase
- Preserve key architectural patterns: MCP for service communication, SSE for events, separate I/O channels, etc.
- Simplify implementations: Maintain pattern benefits with dramatically simpler code
- Scrappy but structured: Lightweight implementations of solid architectural foundations
- End-to-end thinking: Focus on complete flows rather than perfect components
- Use libraries as intended: Minimal wrappers around external libraries
- Direct integration: Avoid unnecessary adapter layers
- Selective dependency: Add dependencies only when they provide substantial value
- Understand what you import: No black-box dependencies
- Emphasis on integration and end-to-end tests
- Manual testability as a design goal
- Focus on critical path testing initially
- Add unit tests for complex logic and edge cases
Some areas justify additional complexity:
- Security: Never compromise on security fundamentals
- Data integrity: Ensure data consistency and reliability
- Core user experience: Make the primary user flows smooth and reliable
- Error visibility: Make problems obvious and diagnosable
Push for extreme simplicity in these areas:
- Internal abstractions: Minimize layers between components
- Generic "future-proof" code: Resist solving non-existent problems
- Edge case handling: Handle the common cases well first
- Framework usage: Use only what you need from frameworks
- State management: Keep state simple and explicit
- It's easier to add complexity later than to remove it
- Code you don't write has no bugs
- Favor clarity over cleverness
- The best code is often the simplest
- Do not use emojis unless asked.
- Do not include exceessive print and logging statements.
- You should only use the dependencies in the provided dependency files. If you need to add a new one, ask first.
- Do not automatically run scripts, tests, or move/rename/delete files. Ask the user to do these tasks.
- Read in the entirety of files to get the full context
- I am using Python version 3.12 on Ubuntu, uv as the package and project manager, and Ruff as a linter and code formatter.
- Follow the Google Python Style Guide.
- Instead of importing
Optionalfrom typing, using the|syntax. - Always add appropriate type hints such that the code would pass Pylance's type check.
- For type hints, use
list, notList. For example, if the variable is[{"name": "Jane", "age": 32}, {"name": "Amy", "age": 28}]the type hint should belist[dict[str. str | int]] - Always prefer pathlib for dealing with files. Use
Path.openinstead ofopen. - When using pathlib, always Use
.parents[i]syntax to go up directories instead of using.parentmultiple times. - When writing multi-line strings, use
"""instead of using string concatenation. Use\to break up long lines in appropriate places. - When writing tests, use pytest and pytest-asyncio.
- Prefer to use pendulum instead of datetime
- Prefer to use loguru instead of logging
- Follow Ruff best practices such as:
- Within an
exceptclause, raise exceptions withraise ... from errorraise ... from Noneto distinguish them from errors in exception handling
- Within an
- Do not use relative imports.
- Use dotenv to load environment variables for local development. Assume we have a
.envfile