Quick Start

GrowToward Quick Start

Section 1: Signup and Hello World

Notes for signup:

  • Pick a username that you'd be comfortable sharing with your employer and/or customers.
  • Make sure you have a Python version >= 3.10 installed. Version 3.9 will not work.
  • Make sure you have a TOTP app for two-factor authentication.
  • If you don't see your email verification code, check your spam.
  • Please read the terms of service very carefully! Don't respond "y" unless you agree whole-heartedly. If there's something you disagree with, please email your suggested change to jason_twohy@growtoward.com.

To sign up, open a shell and enter the following:

pip install growtoward
gt signup --code <your code>

After signing up, use `gt logout` and `gt login` to toggle your session, or use your API key as indicated in the signup flow.

Once you're authenticated, use the following commands to get started.

To list your instances:

gt instance list

Signup automatically creates two instances: `_global` and `work`. These have special hardcoded behavior, so the first step after signup is to create a new instance for ordinary tasks. You can call it whatever you want. In this example, I'll call it "Hello World".

gt instance create name="Hello World"

This creates an instance with name "Hello World" and handle hello_world. To open the GrowToward shell in this instance:

gt shell hello_world

The first thing you'll see is a placeholder "miscellaneous" task. To create your first task, just type it out and press enter. Press enter again to go to your newly-created task. Miscellaneous tasks disappear automatically, so your task is now first on your to-do list.

Enter `am` twice to turn off time tracking.

Enter `/h` to see the full list of commands.

Enter `q` to quit the shell.

For more guidance with the gt shell, see Section 4 below.

Section 2: Core Concepts

Instances are collections of Tasks.

a. Vectors

Vectors are long-running Tasks. Vectors have other Vectors as weighted components.

Vectors can have other Vectors as ingredients. Vectors with ingredients are called Recipes.

Recipes can have some or all of their ingredients' weights set by a zero-sum allocation algorithm. The abstract problem from game theory known as Colonel Blotto is the framework used to decide such allocations. Recipes set by the zero-sum allocator are called Contests.

Each Instance has an Instance Recipe that represents the long-term purpose of all of its Tasks. The Vectors that form the leaves of the tree of ingredients under the Instance Recipe are called End Vectors or simply Ends.

Every Vector maintains an up-to-date set of weighted pointers to Ends, which represents its contribution to the Instance's end purpose. This mapping is a special aggregation of all paths from the Vector to the Ends.

Tasks have zero or more weighted Vector components, from which Ends maps are computed. (This is just like Vectors.)

b. Tasks and the Opportunity Chain

Every Task has a name, a duration, and a priority. Most tasks have a lot more than that (cost, due date, etc.).

A Task's priority can be low, medium, high, next, or urgent. High-priority tasks are selected 5 times as often as medium-priority tasks, which are selected 5 times as often as low-priority tasks. "Next" tasks are selected to fill the allotted time. Urgent tasks are selected unconditionally. By default, the goal generator considers a Task's progress toward Ends to be just as important as its priority, with privilege for next and urgent tasks.

Tasks can have other Tasks as steps. Steps are an ordered list of prerequisites.

Tasks can also have other Tasks as opportunities. At least one opportunity must be checked off before the Task can be done. Not all opportunities are a sure thing -- an opportunity has a user-defined probability of permitting the Task.

An "opportunity chain" is the forest of steps and selected opportunities under a generated to-do list. The gt shell is a powerful tool for wrangling opportunity chains.

For a Task that recurs on a schedule, a RecurringTask can be created to record its RRULE.

Section 3: Introduction to the API

a. Using the API Directly in the CLI

The typical API call is of the form `gt =...`.

The resource types are: user, instance, vector, task, recurring-task, logs, subcontest-group, opposition, document

Type `gt ` without an endpoint to see a list of available endpoints for that resource type.

Endpoint lists are resource-specific and omit operations the server does not expose. For example, vectors can be listed and retrieved directly, but `gt vector create` is not available.

The primary graph-mutation routes are `instance update-vectors` for structured alias-keyed maps and the GT-file workflows `instance import-gt`, `instance load-document`, and `document instantiate`.

gt instance update-vectors <instance-id> component_map=@vectors.yaml
gt instance import-gt <instance-id> materialization=patch text=@plan.gt
gt document instantiate <document-id> materialization=replace

IMPORTANT: Django's double-underscore joins are available on the client side. For example, to find a vector with a given alias, you can run `gt vector filter instance__handle=my_instance aliases__alias="my vec"`

b. The Python Client

Client classes include:

  • UserClient for user/account endpoints
  • InstanceClient for instances/workspaces
  • DocumentClient for documents
  • VectorClient for vectors
  • ContestClient for contests
  • TaskClient for tasks
  • RecurringTaskClient for recurring tasks
  • LogClient for logs
  • GoalParametersClient for goal parameters
  • APIKeyClient for API key operations
  • OppositionClient for oppositions
  • SubcontestGroupClient for subcontest groups
  • ReminderClient for reminders

Here's a small python script leveraging the API:

import growtoward as gt

user_client = gt.UserClient()
my_uu = user_client.whoami()['uu']
print(f'my uu: {my_uu}')

instance_client = gt.InstanceClient()
work_instance = instance_client.filter(handle='work')[0]
instance_client.update_vectors(
    work_instance['id'],
    component_map={'important_work': {'customer_value': 1}},
)
todo_list = instance_client.get_todo_list(work_instance['id'])
print()
print('Current to-do list in my work instance:')
for t in todo_list:
    print(f"- {t['name']}")

Section 4: GrowToward Shell Cheat Sheet

Launch the shell:
    gt shell <instance handle>

Create a 5-minute urgent task:
    this is my new task 5 !!

Create a $5 high-priority task:
    this is my new task $5 hh

Create a medium-priority task:
    this is my new task mm

Create a task at step 4 under this task:
    /as 4::this is my new task

Delete the task at step 4 under this task:
    @.4 d

Regenerate the to-do list:
    /wg

Go to the immediate step under this task:
    @now

Go to the last step of the parent task of the immediate step under this task:
    @now..-1

Go to the 5th task's second-to-last step in another instance:
    @other_instance.5.-2

Show all steps under the current task:
    /show .

Show all steps under the current task in a prompt-ready format:
    /show prompt

Set the current task to recur every Saturday:
    /rr FREQ=WEEKLY;BYDAY=SA

Create a low-priority task in a separate instance without leaving the current task:
    @other_instance new task ll

Add an existing vector as a component of the current task:
    /push components::my vector::0.6

Change the current task's name:
    /push name::new name